資料科學和人工智慧技術筆記 十、模型選擇
阿新 • • 發佈:2018-12-29
十、模型選擇
作者:Chris Albon
譯者:飛龍
在模型選擇期間尋找最佳預處理步驟
在進行模型選擇時,我們必須小心正確處理預處理。 首先,GridSearchCV
使用交叉驗證來確定哪個模型表現最好。 然而,在交叉驗證中,我們假裝作為測試集被留出的一折是不可見的,因此不適合一些預處理步驟(例如縮放或標準化)。 出於這個原因,我們無法預處理資料然後執行GridSearchCV
。
其次,一些預處理方法有自己的引數,通常必須由使用者提供。 通過在搜尋空間中包括候選成分值,可以像對待任何想要搜尋其他超引數一樣對待它們。
# 載入庫
import numpy as np
from sklearn import datasets
from sklearn.feature_selection import SelectKBest
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import Pipeline, FeatureUnion
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
# 設定隨機種子
np.random.seed(0)
# 載入資料
iris = datasets.load_iris()
X = iris.data
y = iris.target
我們包括兩個不同的預處理步驟:主成分分析和 k 最佳特徵選擇。
# 建立組合預處理物件
preprocess = FeatureUnion([('pca', PCA()), ("kbest", SelectKBest(k=1))])
# 建立流水線
pipe = Pipeline([('preprocess', preprocess), ('classifier', LogisticRegression())])
# 建立候選值空間
search_space = [{'preprocess__pca__n_components': [1, 2, 3],
'classifier__penalty': ['l1', 'l2'],
'classifier__C': np.logspace(0, 4, 10)}]
# 建立網格搜尋
clf = GridSearchCV(pipe, search_space, cv=5, verbose=0, n_jobs=-1)
# 擬合網格搜尋
best_model = clf.fit(X, y)
# 檢視最佳超引數
print('Best Number Of Princpal Components:', best_model.best_estimator_.get_params()['preprocess__pca__n_components'])
print('Best Penalty:', best_model.best_estimator_.get_params()['classifier__penalty'])
print('Best C:', best_model.best_estimator_.get_params()['classifier__C'])
'''
Best Number Of Princpal Components: 3
Best Penalty: l1
Best C: 59.9484250319
'''
使用網格搜尋的超引數調優
# 載入庫
import numpy as np
from sklearn import linear_model, datasets
from sklearn.model_selection import GridSearchCV
# 載入資料
iris = datasets.load_iris()
X = iris.data
y = iris.target
# 建立邏輯迴歸
logistic = linear_model.LogisticRegression()
# 建立正則化懲罰空間
penalty = ['l1', 'l2']
# 建立正則化超引數空間
C = np.logspace(0, 4, 10)
# 建立超引數選項
hyperparameters = dict(C=C, penalty=penalty)
# 使用 5 折交叉驗證建立網格搜尋
clf = GridSearchCV(logistic, hyperparameters, cv=5, verbose=0)
# 擬合網格搜尋
best_model = clf.fit(X, y)
# 檢視最佳超引數
print('Best Penalty:', best_model.best_estimator_.get_params()['penalty'])
print('Best C:', best_model.best_estimator_.get_params()['C'])
'''
Best Penalty: l1
Best C: 7.74263682681
'''
# 預測目標向量
best_model.predict(X)
'''
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])
'''
使用隨機搜尋的超引數調優
# 載入庫
from scipy.stats import uniform
from sklearn import linear_model, datasets
from sklearn.model_selection import RandomizedSearchCV
# 載入資料
iris = datasets.load_iris()
X = iris.data
y = iris.target
# 建立邏輯迴歸
logistic = linear_model.LogisticRegression()
# 建立正則化懲罰空間
penalty = ['l1', 'l2']
# 使用均勻分佈建立正則化超引數分佈
C = uniform(loc=0, scale=4)
# 建立超引數選項
hyperparameters = dict(C=C, penalty=penalty)
# 使用 5 折交叉驗證和 100 個迭代
clf = RandomizedSearchCV(logistic, hyperparameters, random_state=1, n_iter=100, cv=5, verbose=0, n_jobs=-1)
# 擬合隨機搜尋
best_model = clf.fit(X, y)
# 檢視最佳超引數
print('Best Penalty:', best_model.best_estimator_.get_params()['penalty'])
print('Best C:', best_model.best_estimator_.get_params()['C'])
'''
Best Penalty: l1
Best C: 1.66808801881
'''
# 預測目標向量
best_model.predict(X)
'''
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])
'''
使用網格搜尋的模型選擇
# 載入庫
import numpy as np
from sklearn import datasets
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import Pipeline
# 設定隨機種子
np.random.seed(0)
# 載入資料
iris = datasets.load_iris()
X = iris.data
y = iris.target
請注意,我們包括需要搜尋的多個可能的學習演算法和多個可能的超引數值。
# 建立流水線
pipe = Pipeline([('classifier', RandomForestClassifier())])
# 建立候選學習演算法和它們的超引數的空間
search_space = [{'classifier': [LogisticRegression()],
'classifier__penalty': ['l1', 'l2'],
'classifier__C': np.logspace(0, 4, 10)},
{'classifier': [RandomForestClassifier()],
'classifier__n_estimators': [10, 100, 1000],
'classifier__max_features': [1, 2, 3]}]
# 建立網格搜尋
clf = GridSearchCV(pipe, search_space, cv=5, verbose=0)
# 擬合網格搜尋
best_model = clf.fit(X, y)
# 檢視最佳模型
best_model.best_estimator_.get_params()['classifier']
'''
LogisticRegression(C=7.7426368268112693, class_weight=None, dual=False,
fit_intercept=True, intercept_scaling=1, max_iter=100,
multi_class='ovr', n_jobs=1, penalty='l1', random_state=None,
solver='liblinear', tol=0.0001, verbose=0, warm_start=False)
'''
# 預測目標向量
best_model.predict(X)
'''
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])
'''
帶有引數選項的流水線
# 匯入所需的包
import numpy as np
from sklearn import linear_model, decomposition, datasets
from sklearn.pipeline import Pipeline
from sklearn.model_selection import GridSearchCV, cross_val_score
from sklearn.preprocessing import StandardScaler
# 載入乳腺癌資料集
dataset = datasets.load_breast_cancer()
# 從資料集特徵中建立 X
X = dataset.data
# 從資料集目標中建立 y
y = dataset.target
# 建立縮放器物件
sc = StandardScaler()
# 建立 PCA 物件
pca = decomposition.PCA()
# 建立邏輯迴歸物件,帶有 L2 懲罰
logistic = linear_model.LogisticRegression()
# 建立三步流水線。首先,標準化資料。
# 其次,使用 PCA 轉換資料。
# 然後在資料上訓練邏輯迴歸。
pipe = Pipeline(steps=[('sc', sc),
('pca', pca),
('logistic', logistic)])
# 建立 1 到 30 的一列整數(X + 1,特徵序號)
n_components = list(range(1,X.shape[1]+1,1))
# 建立正則化引數的一列值
C = np.logspace(-4, 4, 50)
# 為正則化乘法建立一列選項
penalty = ['l1', 'l2']
# 為所有引數選項建立字典
# 注意,你可以使用 '__' 來訪問流水線的步驟的引數
parameters = dict(pca__n_components=n_components,
logistic__C=C,
logistic__penalty=penalty)
# 建立網格搜尋物件
clf = GridSearchCV(pipe, parameters)
# 擬合網格搜尋
clf.fit(X, y)
# 檢視超引數
print('Best Penalty:', clf.best_estimator_.get_params()['logistic__penalty'])
print('Best C:', clf.best_estimator_.get_params()['logistic__C'])
print('Best Number Of Components:', clf.best_estimator_.get_params()['pca__n_components'])
# 使用 3 折交叉驗證擬合網格搜尋
cross_val_score(clf, X, y)