模型選擇
- 1. 窮舉搜尋選擇最佳模型
- 2. 随機搜尋選擇最佳模型
- 3. 從多種學習算法中選擇最佳模型
- 4. 将資料預處理加入模型選擇過程
- 5. 并行化加速模型選擇
- 6. 使用針對特定算法的方法加速模型選擇
- 7. 模型選擇後的性能評估
在機器學習中,通過最小化某個損失函數的值來訓練算法以學習一個模型的參數。此外,許多算法(如支援向量機和随機森林)還有一些超參數,這些超參數必須在學習過程之外定義。
将選擇最佳學習算法以及選擇最佳超參數的過程稱為模型選擇。
1. 窮舉搜尋選擇最佳模型
通過搜尋一系列的超參數來選擇最佳模型
使用sklaern的GridSearchCV:
import numpy as np
from sklearn import linear_model,datasets
from sklearn.model_selection import GridSearchCV
#加載資料
iris = datasets.load_iris()
features = iris.data
target = iris.target
#建立邏輯回歸對象
logistic = linear_model.LogisticRegression()
#建立正則化懲罰的候選超參數區間
penalty = ["l1","l2"]
#建立正則化候選超參數區間
C= np.logspace(0,4,10)
#建立候選超參數的字典
hyperparameters = dict(C=C,penalty = penalty)
#建立網格搜尋對象
gridsearch = GridSearchCV(logistic,hyperparameters,cv=5,verbose=0)
#訓練網格搜尋
best_model = gridsearch.fit(features,target)
#檢視最佳超參數
print('Best Penalty:',best_model.best_estimator_.get_params()['penalty'])
print('C:',best_model.best_estimator_.get_params()['C'])
--->
Best Penalty: l2
C: 7.742636826811269
#預測目标向量
best_model.predict(features)
2. 随機搜尋選擇最佳模型
使用scikit-learn的RandomizedSearchCV來選擇模型,比窮舉搜尋更節省資源。
from scipy.stats import uniform
from sklearn import linear_model,datasets
from sklearn.model_selection import RandomizedSearchCV
#加載資料
iris = datasets.load_iris()
features = iris.data
target = iris.target
#建立邏輯回歸對象
logistic = linear_model.LogisticRegression()
#建立正則化懲罰的候選超參數區間
penalty = ['l1','l2']
#建立正則化候選超參數區間
C = uniform(loc = 0,scale = 4)
#建立候選超參數的字典
hyperparameters = dict(C=C,penalty = penalty)
#建立随機搜尋對象
randomizedsearch = RandomizedSearchCV(logistic,hyperparameters,random_state=1,n_iter=100,cv=5,verbose=0,n_jobs=-1)
#訓練網格搜尋
best_model = randomizedsearch.fit(features,target)
比GridSearchCV更有效的是,在使用者提供的參數分布(如正态分布、均勻分布)上選取特定數量的超參數随機組合。
使用RandomizedSearchCV時,如果指定分布,那麼sklearn将從該分布中對超參數進行無放回的随機采樣。
#檢視最佳超參數
print('Best Penalty:',best_model.best_estimator_.get_params()['penalty'])
print('C:',best_model.best_estimator_.get_params()['C'])
--->
Best Penalty: l2
C: 3.730229437354635
#預測目标向量
best_model.predict(features)
對超參數組合的采樣數(即候選模型的數量)由參數n_iter(疊代次數)指定。
3. 從多種學習算法中選擇最佳模型
為候選的學習算法及其超參數建立一個字典,通過搜尋一系列學習算法及其超參數來選擇最佳模型:
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()
features = iris.data
target = iris.target
#建立pipeline
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]}]
#建立GridSearchCV搜尋對象
randomizedsearch = GridSearchCV(pipe,search_space,cv=5,verbose=0)
#訓練網格搜尋
best_model = gridsearch.fit(features,target)
現在的sklearn允許将學習算法作為搜尋空間的一部分。在以上的解決方案中,定義了一個包含兩種學習算法的搜尋空間:邏輯回歸和随機森林。每種算法都有各自的超參數,并且采用classifier__[hyperparameter_name]這種格式定義超參數的候選值。
在搜尋完成後,使用best_estimator_來檢視模型及其超參數:
best_model.best_estimator_.get_params()
-->
{'C': 7.742636826811269,
'class_weight': None,
'dual': False,
'fit_intercept': True,
'intercept_scaling': 1,
'l1_ratio': None,
'max_iter': 100,
'multi_class': 'auto',
'n_jobs': None,
'penalty': 'l2',
'random_state': None,
'solver': 'lbfgs',
'tol': 0.0001,
'verbose': 0,
'warm_start': False}
4. 将資料預處理加入模型選擇過程
建立一個包含資料預處理步驟及其參數的pipeline,将資料預處理步驟納入模型選擇過程:
import numpy as np
from sklearn import datasets
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()
features = iris.data
target = iris.target
#建立一個包含StandardScaler和PCA的預處理對象
preprocess = FeatureUnion([("std",StandardScaler()),("pca",PCA())])
#建立一個pipeline
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(features,target)
FeatureUnion可以組合多個預處理操作,在以上解決方案中,FeatureUnion組合了兩個預處理步驟:特征值标準化(StandardScaler)和主成分分析(PCA),生成一個名為preprocess的對象,包含兩個預處理步驟。然後,用學習算法将preprocess一同包含到流水線中,最終就是,将拟合、轉換和使用各種超參數組合訓練模型等複雜操作全部交給scikit-learn來處理。
模型選擇結束後,檢視最佳模型的預處理參數。在本解決方案中,可以看到主成分數量:
best_model.best_estimator_.get_params()['preprocess__pca__n_components']
--->
2
5. 并行化加速模型選擇
設定n_jobs=-1,以使用所有的CPU核,加快模型選擇的 過程:
import numpy as np
from sklearn import linear_model,datasets
from sklearn.model_selection import GridSearchCV
#加載資料
iris = datasets.load_iris()
features = iris.data
target = iris.target
#建立邏輯回歸對象
logistic = linear_model.LogisticRegression()
#建立正則化懲罰的候選超參數區間
penalty = ["l1","l2"]
#建立正則化候選超參數區間
C= np.logspace(0,4,10)
#建立候選超參數的字典
hyperparameters = dict(C=C,penalty = penalty)
#建立網格搜尋對象
gridsearch = GridSearchCV(logistic,hyperparameters,cv=5,n_jobs=-1,verbose=0)
#訓練網格搜尋
best_model = gridsearch.fit(features,target)
在不涉及太多技術細節的情況下,scikit-learn可以同時訓練的模型數量等于機器的CPU核的數量。n_jobs的值預設為1,表示隻使用一個核。
6. 使用針對特定算法的方法加速模型選擇
如果使用的是特定的學習算法,可以使用sklearn的模型特有的交叉驗證超參數調優功能來加速模型選擇。例如使用LogisticRegressionCV:
from sklearn import linear_model,datasets
#加載資料
iris = datasets.load_iris()
features = iris.data
target = iris.target
#建立LogisticRegressionCV對象
logistic = linear_model.LogisticRegressionCV(Cs=100)
#訓練模型
logistic.fit(features,target)
—>output:
LogisticRegressionCV(Cs=100, class_weight=None, cv=None, dual=False,
fit_intercept=True, intercept_scaling=1.0, l1_ratios=None,
max_iter=100, multi_class='auto', n_jobs=None,
penalty='l2', random_state=None, refit=True, scoring=None,
solver='lbfgs', tol=0.0001, verbose=0)
有時,利用學習算法的特性能夠比暴力搜尋或随機模型搜尋更快地找到最佳超參數。在sklearn中,許多學習算法(如嶺回歸、彈性網絡回歸)都有特定的交叉驗證方法來利用其自身的優勢尋找最佳超參數。例如,LogisticRegression用于執行标準邏輯回歸分類器,而LogisticsRegressionCV則實作了一個高效的交叉驗證邏輯回歸分類器,能夠識别超參數C的最佳值。
7. 模型選擇後的性能評估
問題描述:評估通過模型選擇找到的模型的性能
使用嵌套交叉驗證來避免評估偏差:
import numpy as np
from sklearn import linear_model,datasets
from sklearn.model_selection import GridSearchCV,cross_val_score
#加載資料
iris = datasets.load_iris()
features = iris.data
target = iris.target
#建立邏輯回歸對象
logistic = linear_model.LogisticRegression()
#建立候選超參數C的20個候選值
C= np.logspace(0,4,10)
#建立候選超參數的字典
hyperparameters = dict(C=C)
#建立網格搜尋對象
gridsearch = GridSearchCV(logistic,hyperparameters,cv=5,n_jobs=-1,verbose=0)
#執行嵌套交叉驗證并輸出平均分
cross_val_score(gridsearch,features,target).mean()
—>
在一般模型選擇方法中(即GridSearch和RandomizedCV),都使用了交叉驗證來評估哪些超參數生成了最佳模型。然而有一個問題:由于使用這些資料來選擇最佳超參數,是以就不能再使用它們評估模型的性能了。解決方法:在交叉驗證中包含另一個用于模型搜尋的交叉驗證即可!在嵌套交叉驗證中,"内部"交叉驗證用于選擇最佳模型,而“外部”交叉驗證對模型性能進行無偏估計。在本解決方案中,進行内部交叉驗證的是GridSearchCV對象,然後使用cross_val_score方法将其封裝到外部交叉驗證中。