機器學習--模型參數優化及scoring可選參數

全棧工程師開發手冊 (作者:欒鵬)

python數據挖掘系列教程

優化的相關的知識內容可以參考
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))

    關於參數空間的設置,比如優化函數q,輸入fmin(q,space=hp.uniform(‘a’,0,1))
    hp.uniform函數的第一個參數是標籤,每個超參數在參數空間內必須具有獨一無二的標籤。

    • 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)前閉後開的區間內的隨機整數。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章