全棧工程師開發手冊 (作者:欒鵬)
優化的相關的知識內容可以參考
https://blog.csdn.net/luanpeng825485697/article/details/78765923
網格搜索GridSearchCV
GridSearchCV用於系統地遍歷多種參數組合,通過交叉驗證確定最佳效果參數。
classsklearn.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的誤差估計函數。下文表格中詳細指定了score可取的值和函數形式。
cv :交叉驗證參數,默認None,使用三折交叉驗證。指定fold數量,默認爲3,也可以是yield訓練/測試數據的生成器。也可是是諸如StratifiedKFold(n_splits=10)這樣的類對象。
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次
隨機參數優化RandomizedSearchCV
儘管使用參數設置的網格法是目前最廣泛使用的參數優化方法, 其他搜索方法也具有更有利的性能。 RandomizedSearchCV 實現了對參數的隨機搜索, 其中每個設置都是從可能的參數值的分佈中進行取樣。 這對於窮舉搜索有兩個主要優勢:
- 可以選擇獨立於參數個數和可能值的預算
- 添加不影響性能的參數不會降低效率
指定如何取樣的參數是使用字典完成的, 非常類似於爲 GridSearchCV 指定參數。 此外, 通過 n_iter 參數指定計算預算, 即取樣候選項數或取樣迭代次數。 對於每個參數, 可以指定在可能值上的分佈或離散選擇的列表 (均勻取樣):
{'C': scipy.stats.expon(scale=100), 'gamma': scipy.stats.expon(scale=.1),
'kernel': ['rbf'], 'class_weight':['balanced', None]}
對象返回值grid的屬性
1.cv_results_:給出不同參數情況下的評價結果的記錄,這是一個字典,可以通過grid.cv_results_.keys()打印該字典的所有詳細鍵值対信息。
2.best_params_:描述了已取得最佳結果的參數的組合,是一個字典
3.best_score_:成員提供優化過程期間觀察到的最好的評分
4.best_estimator_:返回最佳的估計器對象。
from sklearn.datasets import load_iris # 自帶的樣本數據集
from sklearn.neighbors import KNeighborsClassifier # 要估計的是knn裏面的參數,包括k的取值和樣本權重分佈方式
import matplotlib.pyplot as plt # 可視化繪圖
from sklearn.model_selection import GridSearchCV,RandomizedSearchCV # 網格搜索和隨機搜索
iris = load_iris()
X = iris.data # 150個樣本,4個屬性
y = iris.target # 150個類標號
k_range = range(1, 31) # 優化參數k的取值範圍
weight_options = ['uniform', 'distance'] # 代估參數權重的取值範圍。uniform爲統一取權值,distance表示距離倒數取權值
# 下面是構建parameter grid,其結構是key爲參數名稱,value是待搜索的數值列表的一個字典結構
param_grid = {'n_neighbors':k_range,'weights':weight_options} # 定義優化參數字典,字典中的key值必須是分類算法的函數的參數名
print(param_grid)
knn = KNeighborsClassifier(n_neighbors=5) # 定義分類算法。n_neighbors和weights的參數名稱和param_grid字典中的key名對應
# ================================網格搜索=======================================
# 這裏GridSearchCV的參數形式和cross_val_score的形式差不多,其中param_grid是parameter grid所對應的參數
# GridSearchCV中的n_jobs設置爲-1時,可以實現並行計算(如果你的電腦支持的情況下)
grid = GridSearchCV(estimator = knn, param_grid = param_grid, cv=10, scoring='accuracy') #針對每個參數對進行了10次交叉驗證。scoring='accuracy'使用準確率爲結果的度量指標。可以添加多個度量指標
grid.fit(X, y)
print('網格搜索-度量記錄:',grid.cv_results_) # 包含每次訓練的相關信息
print('網格搜索-最佳度量值:',grid.best_score_) # 獲取最佳度量值
print('網格搜索-最佳參數:',grid.best_params_) # 獲取最佳度量值時的代定參數的值。是一個字典
print('網格搜索-最佳模型:',grid.best_estimator_) # 獲取最佳度量時的分類器模型
# 使用獲取的最佳參數生成模型,預測數據
knn = KNeighborsClassifier(n_neighbors=grid.best_params_['n_neighbors'], weights=grid.best_params_['weights']) # 取出最佳參數進行建模
knn.fit(X, y) # 訓練模型
print(knn.predict([[3, 5, 4, 2]])) # 預測新對象
# =====================================隨機搜索===========================================
rand = RandomizedSearchCV(knn, param_grid, cv=10, scoring='accuracy', n_iter=10, random_state=5) #
rand.fit(X, y)
print('隨機搜索-度量記錄:',grid.cv_results_) # 包含每次訓練的相關信息
print('隨機搜索-最佳度量值:',grid.best_score_) # 獲取最佳度量值
print('隨機搜索-最佳參數:',grid.best_params_) # 獲取最佳度量值時的代定參數的值。是一個字典
print('隨機搜索-最佳模型:',grid.best_estimator_) # 獲取最佳度量時的分類器模型
# 使用獲取的最佳參數生成模型,預測數據
knn = KNeighborsClassifier(n_neighbors=grid.best_params_['n_neighbors'], weights=grid.best_params_['weights']) # 取出最佳參數進行建模
knn.fit(X, y) # 訓練模型
print(knn.predict([[3, 5, 4, 2]])) # 預測新對象
# =====================================自定義度量===========================================
from sklearn import metrics
# 自定義度量函數
def scorerfun(estimator, X, y):
y_pred = estimator.predict(X)
return metrics.accuracy_score(y, y_pred)
rand = RandomizedSearchCV(knn, param_grid, cv=10, scoring='accuracy', n_iter=10, random_state=5) #
rand.fit(X, y)
print('隨機搜索-最佳度量值:',grid.best_score_) # 獲取最佳度量值
當你的調節參數是連續的,比如迴歸問題的正則化參數,有必要指定一個連續分佈而不是可能值的列表,這樣RandomizeSearchCV就可以執行更好的grid search。
Scoring | Function | Comment |
---|---|---|
分類 | ||
‘accuracy’ | metrics.accuracy_score | 準確率 |
‘average_precision’ | metrics.average_precision_score | 平均準確率 |
‘f1’ | metrics.f1_score | for binary targets |
‘f1_micro’ | metrics.f1_score | micro-averaged |
‘f1_macro’ | metrics.f1_score | macro-averaged |
‘f1_weighted’ | metrics.f1_score | weighted average |
‘f1_samples’ | metrics.f1_score | by multilabel sample |
‘neg_log_loss’ | metrics.log_loss | requires predict_proba support |
‘precision’ etc. | metrics.precision_score | suffixes apply as with ‘f1’ |
‘recall’ etc. | metrics.recall_score | suffixes apply as with ‘f1’ |
‘roc_auc’ | metrics.roc_auc_score | roc_auc曲線 |
Clustering | ||
‘adjusted_rand_score’ | metrics.adjusted_rand_score | |
‘adjusted_mutual_info_score’ | metrics.adjusted_mutual_info_score | |
‘completeness_score’ | metrics.completeness_score | |
‘fowlkes_mallows_score’ | metrics.fowlkes_mallows_score | |
‘homogeneity_score’ | metrics.homogeneity_score | |
‘mutual_info_score’ | metrics.mutual_info_score | |
‘normalized_mutual_info_score’ | metrics.normalized_mutual_info_score | |
‘v_measure_score’ | metrics.v_measure_score | |
Regression | ||
‘explained_variance’ | metrics.explained_variance_score | |
‘neg_mean_absolute_error’ | metrics.mean_absolute_error | |
‘neg_mean_squared_error’ | metrics.mean_squared_error | |
‘neg_mean_squared_log_error’ | metrics.mean_squared_log_error | |
‘neg_median_absolute_error’ | metrics.median_absolute_error | |
‘r2’ | metrics.r2_score |
如果沒有我們想要的度量字符串表達,我們可以自定義度量函數,將函數名設置爲scoring參數的值。函數名必須爲
# 自定義度量函數
def scorerfun(estimator, X, y):
。。。
return 。。
- 1
- 2
- 3
- 4
python調參神器hyperopt
Hyperopt庫爲python中的模型選擇和參數優化提供了算法和並行方案。
給一段代碼,一看就明白
from sklearn.model_selection import cross_val_score
import pickle
from hyperopt import fmin, tpe, hp,space_eval,rand,Trials,partial,STATUS_OK
from xgboost.sklearn import XGBClassifier
import xgboost as xgb
# 定義一個目標函數,接受一個變量,計算後返回一個函數的損失值,
def GBM(argsDict):
max_depth = argsDict["max_depth"] + 5
n_estimators = argsDict['n_estimators'] * 5 + 50
learning_rate = argsDict["learning_rate"] * 0.02 + 0.05
subsample = argsDict["subsample"] * 0.1 + 0.7
min_child_weight = argsDict["min_child_weight"]+1
global attr_train,label_train
gbm = xgb.XGBClassifier(nthread=4, #進程數
max_depth=max_depth, #最大深度
n_estimators=n_estimators, #樹的數量
learning_rate=learning_rate, #學習率
subsample=subsample, #採樣數
min_child_weight=min_child_weight, #孩子數
max_delta_step = 10, #10步不降則停止
objective="binary:logistic")
metric = cross_val_score(gbm,attr_train,label_train,cv=5,scoring="roc_auc").mean()
print(metric)
return -metric
# 定義參數的搜索空間
space = {"max_depth":hp.randint("max_depth",15),
"n_estimators":hp.randint("n_estimators",10), #[0,1,2,3,4,5] -> [50,]
"learning_rate":hp.randint("learning_rate",6), #[0,1,2,3,4,5] -> 0.05,0.06
"subsample":hp.randint("subsample",4),#[0,1,2,3] -> [0.7,0.8,0.9,1.0]
"min_child_weight":hp.randint("min_child_weight",5), #
}
algo = partial(tpe.suggest,n_startup_jobs=1) # 定義隨機搜索算法。搜索算法本身也有內置的參數決定如何去優化目標函數
best = fmin(GBM,space,algo=algo,max_evals=4) # 對定義的參數範圍,調用搜索算法,對模型進行搜索
print(best)
print(GBM(best))
- hp.choice返回一個選項,選項可以是list或者tuple.options可以是嵌套的表達式,用於組成條件參數。
- hp.pchoice(label,p_options)以一定的概率返回一個p_options的一個選項。這個選項使得函數在搜索過程中對每個選項的可能性不均勻。
- hp.uniform(label,low,high)參數在low和high之間均勻分佈。
- hp.quniform(label,low,high,q),參數的取值是round(uniform(low,high)/q)*q,適用於那些離散的取值。
- hp.loguniform(label,low,high)繪製exp(uniform(low,high)),變量的取值範圍是[exp(low),exp(high)]
- hp.randint(label,upper) 返回一個在[0,upper)前閉後開的區間內的隨機整數。
關於參數空間的設置,比如優化函數q,輸入fmin(q,space=hp.uniform(‘a’,0,1))
hp.uniform函數的第一個參數是標籤,每個超參數在參數空間內必須具有獨一無二的標籤。