1. 程式人生 > >資料科學和人工智慧技術筆記 十、模型選擇

資料科學和人工智慧技術筆記 十、模型選擇

十、模型選擇

作者:Chris Albon

譯者:飛龍

協議:CC BY-NC-SA 4.0

在模型選擇期間尋找最佳預處理步驟

在進行模型選擇時,我們必須小心正確處理預處理。 首先,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)