天天看點

學習器模型中的超參數(Hyperparameter)怎麼選?

作者:騰科IT教育

學習器模型中一般有兩類參數:

一類是可以從資料中學習估計得到,我們稱為參數(Parameter)。

還有一類參數時無法從資料中估計,隻能靠人的經驗進行設計指定,我們稱為超參數(Hyper parameter)。超參數是在開始學習過程之前設定值的參數。相反,其他參數的值通過訓練得出。

我們在選擇超參數有兩個途徑:

1)憑經驗;

2)選擇不同大小的參數,帶入到模型中,挑選表現最好的參數。通過途徑2選擇超參數時,人力手動調節注意力成本太高,非常不值得。For循環或類似于for循環的方法受限于太過分明的層次,不夠簡潔與靈活,注意力成本高,易出錯。

有一種選擇方法叫做網絡搜尋(GridSearchCV),利用計算機快速計算的特點周遊所有的參數組合,找到最好的參數組合。聽起來很高大上,本質上就是暴力搜尋。注意的是,該方法在小資料集上很有用,資料集大了就不太适用了。會比較耗費時間和計算資源。資料量比較大的時候可以使用一個快速調優的方法——坐标下降。它其實是一種貪心算法:拿目前對模型影響最大的參數調優,直到最優化;再拿下一個影響最大的參數調優,如此下去,直到所有的參數調整完畢。這個方法的缺點就是可能會調到局部最優而不是全局最優,但是省時間省力。

使用示例:

from sklearn.model_selection import GridSearchCV 
from sklearn.svm import SVR 
from sklearn import datasets 
dataset = datasets.load_iris() 
X = dataset.data 
y = dataset.target 
grid = GridSearchCV( 
    estimator=SVR(kernel='rbf'), 	
    param_grid={ 	
        'C': [0.1, 1, 10, 100], 
        'epsilon': [0.0001, 0.001, 0.01, 0.1, 1, 10], 
        'gamma': [0.001, 0.01, 0.1, 1] 
    }, 
    cv=5, scoring='neg_mean_squared_error', verbose=0, n_jobs=-1) 
grid.fit(X, y) 
print(grid.best_score_) 
print(grid.best_params_)            

還有一種方法叫做随機搜尋(RandomizedSearchCV),再參數量較大的時候使用這種方法可以快速或者較好的參數組合,在搜尋超參數的時候,如果超參數個數較少(三四個或者更少),那麼我們可以采用網格搜尋,一種窮盡式的搜尋方法。

但是當超參數個數比較多的時候,我們仍然采用網格搜尋,那麼搜尋所需時間将會指數級上升。是以有人就提出了随機搜尋的方法,随機在超參數空間中搜尋幾十幾百個點,其中就有可能有比較小的值。這種做法比上面稀疏化網格的做法快,而且實驗證明,随機搜尋法結果比稀疏網格法稍好。RandomizedSearchCV使用方法和類GridSearchCV 很相似,但他不是嘗試所有可能的組合,而是通過選擇每一個超參數的一個随機值的特定數量的随機組合,這個方法有兩個優點:

相比于整體參數空間,可以選擇相對較少的參數組合數量。如果讓随機搜尋運作,它會探索每個超參數的不同的值 可以友善的通過設定搜尋次數,控制超參數搜尋的計算量,但是這個方法也有缺點,他會再搜尋的過程中逐漸偏向某些更加重要的超參數,會影響搜尋的方向。

使用示例:

from scipy.stats import randint as sp_randint 
from sklearn.model_selection import RandomizedSearchCV 
from sklearn.datasets import load_digits 
from sklearn.ensemble import RandomForestClassifier 
# 載入資料 
digits = load_digits() 
X, y = digits.data, digits.target 
# 建立一個分類器或者回歸器 
clf = RandomForestClassifier(n_estimators=20) 
# 給定參數搜尋範圍:list or distribution 
param_dist = {"max_depth": [3, None],  # 給定list 
              "max_features": sp_randint(1, 11),  # 給定distribution 
              "min_samples_split": sp_randint(2, 11),  # 給定distribution 
              "bootstrap": [True, False],  # 給定list 
              "criterion": ["gini", "entropy"]}  # 給定list 
# 用RandomSearch+CV選取超參數 
n_iter_search = 20 
random_search=RandomizedSearchCV(clf,param_distributions=param_dist,n_iter=n_iter_search, cv=5, iid=False) 
random_search.fit(X, y) 
print(random_search.best_score_) 
print(random_search.best_params_)            

還有一種方法叫貝葉斯優化(Bayesian optimization),給定一組超參數,為了計算相應的模型泛化誤差,我們需要進行一次完整的模型訓練,對于大型的深度學習模型可能需要花上幾個小時的時間。注意到網格搜尋和随機搜尋中,不同的超參數采樣是互相獨立的,一個直接的想法是,能否充分利用已采樣資料來決定下一次采樣,以提高搜尋效率(或者說減少采樣次數)。

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

1、使用先前評估的點 X 1:n,計算損失 f 的後驗期望。

2、在新的點 X 的抽樣損失 f,進而最大化f的期望的某些方法。該方法指定 f 域的哪些區域最适于抽樣。

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

使用例子:

from skopt import BayesSearchCV
import warnings
warnings.filterwarnings("ignore")
from skopt.space import Real, Categorical, Integer
knn = KNeighborsClassifier()
定義參數
grid_param = { 'n_neighbors' : list(range(2,11)) , 
              'algorithm' : ['auto','ball_tree','kd_tree','brute'] }
#初始化貝葉斯搜尋
Bayes = BayesSearchCV(knn , grid_param , n_iter=30 , random_state=14)
Bayes.fit(X_train,y_train)
#最好的參數組合
Bayes.best_params_
#最好分數
Bayes.best_score_
#所有的參數組合
Bayes.cv_results_['params']           

繼續閱讀