機器學習最困難的部分:超引數除錯

希望每天漲粉發表於2021-12-07

介紹

  維基百科上說,“Hyperparameter optimization或tuning是為學習演算法選擇一組最優的hyperparameters的問題”。

  ML工作流中最困難的部分之一是為模型找到最好的超引數。ML模型的效能與超引數直接相關。超引數調優的越好,得到的模型就越好。調優超引數可能是非常乏味和困難的,更像是一門藝術而不是科學。

超引數

  超引數是在建立模型時用於控制演算法行為的引數。這些引數不能從常規訓練過程中獲得。在對模型進行訓練之前,需要對它們進行賦值。

     

內容

1.傳統手工搜尋

  在傳統的調參過程中,我們通過訓練演算法手動檢查隨機超引數集,並選擇符合我們目標的最佳引數集。

  我們看看程式碼:

#importing required libraries
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.model_selection import KFold , cross_val_score
from sklearn.datasets import load_wine

wine = load_wine()
X = wine.data
y = wine.target

#splitting the data into train and test set
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size = 0.3,random_state = 14)

#declaring parameters grid
k_value = list(range(2,11))
algorithm = ['auto','ball_tree','kd_tree','brute']
scores = []
best_comb = []
kfold = KFold(n_splits=5)

#hyperparameter tunning
for algo in algorithm:
  for k in k_value:
    knn = KNeighborsClassifier(n_neighbors=k,algorithm=algo)
    results = cross_val_score(knn,X_train,y_train,cv = kfold)

    print(f'Score:{round(results.mean(),4)} with algo = {algo} , K = {k}')
    scores.append(results.mean())
    best_comb.append((k,algo))

best_param = best_comb[scores.index(max(scores))]
print(f'\nThe Best Score : {max(scores)}')
print(f"['algorithm': {best_param[1]} ,'n_neighbors': {best_param[0]}]")

  缺點

    1. 沒辦法確保得到最佳的引數組合。
    2. 這是一個不斷試錯的過程,所以,非常的耗時。

2. 網格搜尋

  網格搜尋是一種基本的超引數調優技術。它類似於手動調優,為網格中指定的所有給定超引數值的每個排列構建模型,評估並選擇最佳模型。考慮上面的例子,其中兩個超引數k_value =[2,3,4,5,6,7,8,9,10] & algorithm =[' auto ', ' ball_tree ', ' kd_tree ', ' brute '],在這個例子中,它總共構建了9*4 = 36不同的模型。

        

  讓我們來了解一下sklearn的GridSearchCV是如何工作的:

from sklearn.model_selection import GridSearchCV

knn = KNeighborsClassifier()
grid_param = { 'n_neighbors' : list(range(2,11)) , 
              'algorithm' : ['auto','ball_tree','kd_tree','brute'] }
              
grid = GridSearchCV(knn,grid_param,cv = 5)
grid.fit(X_train,y_train)

#best parameter combination
grid.best_params_

#Score achieved with best parameter combination
grid.best_score_

#all combinations of hyperparameters
grid.cv_results_['params']

#average scores of cross-validation
grid.cv_results_['mean_test_score']

  缺點

  由於它嘗試了超引數的每一個組合,並根據交叉驗證得分選擇了最佳組合,這使得GridsearchCV非常慢。

3. 隨機搜尋

  使用隨機搜尋代替網格搜尋的動機是,在許多情況下,所有的超引數可能不是同等重要的。隨機搜尋從超引數空間中隨機選擇引數組合,引數由n_iter給定的固定迭代次數的情況下選擇。實驗證明,隨機搜尋的結果優於網格搜尋。

        

  讓我們來了解sklearn的RandomizedSearchCV是如何工作的,

from sklearn.model_selection import RandomizedSearchCV

knn = KNeighborsClassifier()

grid_param = { 'n_neighbors' : list(range(2,11)) , 
              'algorithm' : ['auto','ball_tree','kd_tree','brute'] }

rand_ser = RandomizedSearchCV(knn,grid_param,n_iter=10)
rand_ser.fit(X_train,y_train)

#best parameter combination
rand_ser.best_params_

#score achieved with best parameter combination
rand_ser.best_score_

#all combinations of hyperparameters
rand_ser.cv_results_['params']

#average scores of cross-validation
rand_ser.cv_results_['mean_test_score']

  缺點

  隨機搜尋的問題是它不能保證給出最好的引數組合。

4. 貝葉斯搜尋

  貝葉斯優化屬於一類優化演算法,稱為基於序列模型的優化(SMBO)演算法。這些演算法使用先前對損失f的觀察結果,以確定下一個(最優)點來抽樣f。該演算法大致可以概括如下。

    1. 使用先前評估的點X1*:n*,計算損失f的後驗期望。
    2. 在新的點X的抽樣損失f,從而最大化f的期望的某些方法。該方法指定f域的哪些區域最適於抽樣。

  重複這些步驟,直到滿足某些收斂準則。

        

  讓我們用scikit- optimization的BayesSearchCV來理解這

    Installation: pip install scikit-optimize

from skopt import BayesSearchCV

import warnings
warnings.filterwarnings("ignore")

# parameter ranges are specified by one of below
from skopt.space import Real, Categorical, Integer

knn = KNeighborsClassifier()
#defining hyper-parameter grid
grid_param = { 'n_neighbors' : list(range(2,11)) , 
              'algorithm' : ['auto','ball_tree','kd_tree','brute'] }

#initializing Bayesian Search
Bayes = BayesSearchCV(knn , grid_param , n_iter=30 , random_state=14)
Bayes.fit(X_train,y_train)

#best parameter combination
Bayes.best_params_

#score achieved with best parameter combination
Bayes.best_score_

#all combinations of hyperparameters
Bayes.cv_results_['params']

#average scores of cross-validation
Bayes.cv_results_['mean_test_score']

  另一個實現貝葉斯搜尋的類似庫是bayesian-optimization

    Installation: pip install bayesian-optimization

  缺點

  要在2維或3維的搜尋空間中得到一個好的代理曲面需要十幾個樣本,增加搜尋空間的維數需要更多的樣本。

總結

  在確定引數的最佳組合的保證和計算時間之間總是存在權衡。如果超引數空間(超引數個數)非常大,則使用隨機搜尋找到超引數的潛在組合,然後在該區域性使用網格搜尋(超引數的潛在組合)選擇最優特徵。

『總結不易,加個關注唄!』

  

相關文章