利用Grid Search進行調參
Grid Search是咩?
即,網格搜尋,是一種自動調參的方法。
為想要調參的引數設定一組候選值,然後網格搜尋會窮舉各種引數組合,根據設定的評分機制找到最好的那一組設定,主要用於系統地遍歷多種引數組合,通過交叉驗證確定最佳效果引數。
缺點:這個方法適合於小資料集,一旦資料的量級上去了,很難得出結果。
官網:http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html
引數及方法介紹
這個是每個API最關心的問題,因為堅持拿來主義的我們,還是得需要看下說明書。
class sklearn.model_selection.GridSearchCV(estimator, param_grid, scoring=None, fit_params=None, n_jobs=1, iid=True, refit=True, cv=None, verbose=0, pre_dispatch='2*n_jobs', error_score='raise', return_train_score=True)
-
estimator
:所使用的分類器,如estimator=RandomForestClassifier(min_samples_split=100,min_samples_leaf=20,max_depth=8,max_features=‘sqrt’,random_state=10), 並且傳入除需要確定最佳的引數之外的其他引數。每一個分類器都需要一個scoring引數,或者score方法。 -
param_grid
:值為字典或者列表,即需要最優化的引數的取值,param_grid =param_test1,param_test1 = {‘n_estimators’:range(10,71,10)}。 -
scoring
:準確度評價標準,預設None,這時需要使用score函式;或者如scoring=‘roc_auc’,根據所選模型不同,評價準則不同。字串(函式名),或是可呼叫物件,需要其函式簽名形如:scorer(estimator, X, y);如果是None,則使用estimator的誤差估計函式。 -
cv
:交叉驗證引數,預設None,使用三折交叉驗證。指定fold數量,預設為3,也可以是yield訓練/測試資料的生成器。 -
refit
:預設為True,程式將會以交叉驗證訓練集得到的最佳引數,重新對所有可用的訓練集與開發集進行,作為最終用於效能評估的最佳模型引數。即在搜尋引數結束後,用最佳引數結果再次fit一遍全部資料集。 -
iid
:預設True,為True時,預設為各個樣本fold概率分佈一致,誤差估計為所有樣本之和,而非各個fold的平均。 -
verbose
:日誌冗長度,int:冗長度,0:不輸出訓練過程,1:偶爾輸出,>1:對每個子模型都輸出。 -
n_jobs
: 並行數,int:個數,-1:跟CPU核數一致, 1:預設值。 -
pre_dispatch
:指定總共分發的並行任務數。當n_jobs大於1時,資料將在每個執行點進行復制,這可能導致OOM,而設定pre_dispatch引數,則可以預先劃分總共的job數量,使資料最多被複制pre_dispatch次。 -
grid.fit()
:執行網格搜尋 -
grid_scores_
:給出不同引數情況下的評價結果 -
best_params_
:描述了已取得最佳結果的引數的組合 -
best_score_
:成員提供優化過程期間觀察到的最好的評分
一個小竅門
GridSearchCV模組中,不同超引數的組合方式及其計算結果以字典的形式儲存在 clf.cv_results_中,python的pandas模組提供了高效整理資料的方法,只需要3行程式碼即可解決問題。
cv_result = pd.DataFrame.from_dict(clf.cv_results_)
with open('cv_result.csv','w') as f:
cv_result.to_csv(f)
程式碼
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import classification_report
from sklearn.svm import SVC
digits = datasets.load_digits()
n_samples = len(digits.images)
X = digits.images.reshape((n_samples, -1))
y = digits.target
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.5, random_state=0)
tuned_parameters = [{'kernel': ['rbf'], 'gamma': [1e-3, 1e-4],
'C': [1, 10, 100, 1000]},
{'kernel': ['linear'], 'C': [1, 10, 100, 1000]}]
scores = ['precision', 'recall']
for score in scores:
print("# Tuning hyper-parameters for %s" % score)
print()
# 呼叫 GridSearchCV,將 SVC(), tuned_parameters, cv=5, 還有 scoring 傳遞進去,
clf = GridSearchCV(SVC(), tuned_parameters, cv=5,
scoring='%s_macro' % score)
# 用訓練集訓練這個學習器 clf
clf.fit(X_train, y_train)
print("Best parameters set found on development set:")
print()
# 再呼叫 clf.best_params_ 就能直接得到最好的引數搭配結果
print(clf.best_params_)
print()
print("Grid scores on development set:")
print()
means = clf.cv_results_['mean_test_score']
stds = clf.cv_results_['std_test_score']
# 看一下具體的引數間不同數值的組合後得到的分數是多少
for mean, std, params in zip(means, stds, clf.cv_results_['params']):
print("%0.3f (+/-%0.03f) for %r"
% (mean, std * 2, params))
print()
print("Detailed classification report:")
print()
print("The model is trained on the full development set.")
print("The scores are computed on the full evaluation set.")
print()
y_true, y_pred = y_test, clf.predict(X_test)
# 列印在測試集上的預測結果與真實值的分數
print(classification_report(y_true, y_pred))
print()
執行結果
# Tuning hyper-parameters for precision
Best parameters set found on development set:
{'C': 10, 'gamma': 0.001, 'kernel': 'rbf'}
Grid scores on development set:
0.986 (+/-0.016) for {'C': 1, 'gamma': 0.001, 'kernel': 'rbf'}
0.959 (+/-0.029) for {'C': 1, 'gamma': 0.0001, 'kernel': 'rbf'}
0.988 (+/-0.017) for {'C': 10, 'gamma': 0.001, 'kernel': 'rbf'}
0.982 (+/-0.026) for {'C': 10, 'gamma': 0.0001, 'kernel': 'rbf'}
0.988 (+/-0.017) for {'C': 100, 'gamma': 0.001, 'kernel': 'rbf'}
0.982 (+/-0.025) for {'C': 100, 'gamma': 0.0001, 'kernel': 'rbf'}
0.988 (+/-0.017) for {'C': 1000, 'gamma': 0.001, 'kernel': 'rbf'}
0.982 (+/-0.025) for {'C': 1000, 'gamma': 0.0001, 'kernel': 'rbf'}
0.975 (+/-0.014) for {'C': 1, 'kernel': 'linear'}
0.975 (+/-0.014) for {'C': 10, 'kernel': 'linear'}
0.975 (+/-0.014) for {'C': 100, 'kernel': 'linear'}
0.975 (+/-0.014) for {'C': 1000, 'kernel': 'linear'}
Detailed classification report:
The model is trained on the full development set.
The scores are computed on the full evaluation set.
precision recall f1-score support
0 1.00 1.00 1.00 89
1 0.97 1.00 0.98 90
2 0.99 0.98 0.98 92
3 1.00 0.99 0.99 93
4 1.00 1.00 1.00 76
5 0.99 0.98 0.99 108
6 0.99 1.00 0.99 89
7 0.99 1.00 0.99 78
8 1.00 0.98 0.99 92
9 0.99 0.99 0.99 92
micro avg 0.99 0.99 0.99 899
macro avg 0.99 0.99 0.99 899
weighted avg 0.99 0.99 0.99 899
# Tuning hyper-parameters for recall
Best parameters set found on development set:
{'C': 10, 'gamma': 0.001, 'kernel': 'rbf'}
Grid scores on development set:
0.986 (+/-0.019) for {'C': 1, 'gamma': 0.001, 'kernel': 'rbf'}
0.957 (+/-0.029) for {'C': 1, 'gamma': 0.0001, 'kernel': 'rbf'}
0.987 (+/-0.019) for {'C': 10, 'gamma': 0.001, 'kernel': 'rbf'}
0.981 (+/-0.028) for {'C': 10, 'gamma': 0.0001, 'kernel': 'rbf'}
0.987 (+/-0.019) for {'C': 100, 'gamma': 0.001, 'kernel': 'rbf'}
0.981 (+/-0.026) for {'C': 100, 'gamma': 0.0001, 'kernel': 'rbf'}
0.987 (+/-0.019) for {'C': 1000, 'gamma': 0.001, 'kernel': 'rbf'}
0.981 (+/-0.026) for {'C': 1000, 'gamma': 0.0001, 'kernel': 'rbf'}
0.972 (+/-0.012) for {'C': 1, 'kernel': 'linear'}
0.972 (+/-0.012) for {'C': 10, 'kernel': 'linear'}
0.972 (+/-0.012) for {'C': 100, 'kernel': 'linear'}
0.972 (+/-0.012) for {'C': 1000, 'kernel': 'linear'}
Detailed classification report:
The model is trained on the full development set.
The scores are computed on the full evaluation set.
precision recall f1-score support
0 1.00 1.00 1.00 89
1 0.97 1.00 0.98 90
2 0.99 0.98 0.98 92
3 1.00 0.99 0.99 93
4 1.00 1.00 1.00 76
5 0.99 0.98 0.99 108
6 0.99 1.00 0.99 89
7 0.99 1.00 0.99 78
8 1.00 0.98 0.99 92
9 0.99 0.99 0.99 92
micro avg 0.99 0.99 0.99 899
macro avg 0.99 0.99 0.99 899
weighted avg 0.99 0.99 0.99 899