學習器模型中一般有兩類參數:
一類是可以從資料中學習估計得到,我們稱為參數(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']