机器学习——超参数调优
超參數是在開始學習過程之前設置值的參數,而不是通過訓練得到的參數數據。超參數可以分為兩種類型:定義模型及結構本身的參數,目標函數與與優化算法所需的參數,前者用于訓練和預測階段,后者用于訓練階段。
在實戰過程中,需要對機器學習模型進行優化以確保模型的最高準確率,因此,超參數調優參數應運而生,常見的超參數搜索算法有網格搜索、隨機搜索、貝葉斯優化等。超參數搜索算法一般包括三個要素:
-
目標函數,即算法需要最大化/最小化目標;
-
搜索范圍,一般通過上限和下限來確定;
-
算法的其他參數,如搜索步長。
1、傳統的機器學習超參優化
1.1 網格搜索
1.1.1 算法原理
網格搜索是較簡單、應用最廣泛的超參數搜索算法,它通過查找搜索范圍內的所有的點來確定最優值(窮舉)。然而,這種方法比較消耗計算資源和時間。在實際應用中,網格搜索一般會先使用較大的搜索范圍和步長,來尋找全局最優值可能的位置;然后逐漸縮小搜索范圍和步長,來尋找更精確的最優值。
1.1.2 參數說明
函數:sklearn.model_selection.GridSearchCV
參數:
- estimator:sklearn的估計器
- param_grid:(字典 or 字典列表 )超參數
- scoring:(str)在測試集進行交叉驗證的評估策略
- n_jobs:(int)并行處理幾個job
- refit:(bool)使用最佳參數重新調整estimator
- cv:(int)確定交叉驗證的策略,None:默認使用5-fold交叉驗證
屬性:
- cv_results_:字典的keys是列名,values是列的DataFrame
- best_estimator_:最佳參數的估計器
- best_score_:最佳參數的估計器交叉驗證的平均得分
- best_params_:最佳參數
1.1.3算法實現
from sklearn import svm, datasets from sklearn.model_selection import GridSearchCV#獲取數據 iris = datasets.load_iris()#超參數 parameters = {'kernel':('linear', 'rbf'), 'C':[1, 10]} #估計器 svc = svm.SVC() #網格搜索 clf = GridSearchCV(svc, parameters) clf.fit(iris.data, iris.target) sorted(clf.cv_results_.keys())1.2 隨機搜索
1.2.1 算法原理
隨機搜索和網格搜索類似,只是不再測試上界和下界之間的所有值,而是在搜索范圍中隨機選取樣本點,如果樣本點集足夠大,通過隨機采樣也能大概率找到全局最優值或其近似值。
比網格搜索的好處:一是獨立于參數數量和可能的值被選中;二是添加不影響性能的參數不會降低效率
1.2.2 參數說明
函數:sklearn.model_selection.RandomizedSearchCV
參數:
- estimator:sklearn的估計器
- param_distributions:(字典 or 字典列表 )超參數的樣本分布
- scoring:(str)在測試集進行交叉驗證的評估策略
- n_iter:(int)采樣參數的設置數
- n_jobs:(int)并行處理幾個job
- refit:(bool)使用最佳參數重新調整estimator
- cv:(int)確定交叉驗證的策略,None:默認使用5-fold交叉驗證
屬性:
- cv_results_:字典的keys是列名,values是列的DataFrame
- best_estimator_:最佳參數的估計器
- best_score_:最佳參數的估計器交叉驗證的平均得分
- best_params_:最佳參數
1.2.3算法實現
from sklearn.datasets import load_iris from sklearn.linear_model import LogisticRegression from sklearn.model_selection import RandomizedSearchCV from scipy.stats import uniform iris = load_iris() logistic = LogisticRegression(solver='saga', tol=1e-2, max_iter=200,random_state=0) distributions = dict(C=uniform(loc=0, scale=4),penalty=['l2', 'l1']) clf = RandomizedSearchCV(logistic, distributions, random_state=0) search = clf.fit(iris.data, iris.target) print(search.best_params_)2 基于模型的序列超參優化
基于模型的序列超參優化的核心成分是:代理模型選擇、代理模型更新、基于后驗分布下新的超參組合的選擇。
(1)代理模型選擇
模型選擇是使用一個概率模型作為目標函數的代理函數,通過這個模型對目標函數進行預估評價。
(2)代理模型更新
剛開始模型隨機選擇一個超參組合,但隨著觀測的增加,可以基于新的觀測去更新模型進而增強模型能力。
(3)新超參組的選擇
代理模型都采用概率代理模型,可以提供更高的靈活性,每一個超參組合的評估結果都可以用一個概率分布表達。,其次,基于概率分布的模型可以用于選取期望最大的新超參組合并支持模型的更新迭代。通過新超參組選擇的方法定義采集函數來計算超參組合優劣程度,常見方法有:
- PI(Probability Improvement)
PI即概率提升法,它的核心思路是尋找在期望上最有可能獲得更好結果的超參組合。
效用函數:
是目標函數(誤差率),是當前最小誤差率的值,計算效用函數的期望。
- EI(Expected Improvement)
EI即期望提升法,PI沒有考慮優化的幅度,因此EI引入了優化幅度從而計算期望優化度。
效用函數:
- UCB(Upper Confidence Bound)
UCB的核心思想是統計學的置信區間,如果目標函數是往最大值優化,就使用上邊界,如果目標函數是往最小值優化,就使用下邊界。
2.1 貝葉斯優化
2.1.1 算法原理
貝葉斯優化是一種黑盒優化算法,用于求解表達式未知的函數的極值問題。算法根據一組采樣點處的函數值預測出任意點處函數值的概率分布,這通過高斯過程回歸而實現。根據高斯過程回歸的結果構造采集函數,用于衡量每一個點值得探索的程度,求解采集函數的極值從而確定下一個采樣點。最后返回這組采樣點的極值作為函數的極值。
其核心由兩部分構成:
- 1. 高斯過程回歸。計算每一點處函數值的均值和方差;
- 2. 根據均值和方差構造采集函數,用于決定本次迭代時在哪個點處進行采樣。
(1)高斯分布
? ? ? 若隨機變量服從一個位置參數為、尺度參數為的概率分布,且其概率密度函數為
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ?則這個隨機變量就稱為正態隨機變量,正態隨機變量服從的分布就稱為正態分布,記作,讀作服從,或服從正態分布。
(2)高斯過程
高斯過程(Gaussian Process, GP)是概率論和數理統計中隨機過程(stochastic process)的一種,是一系列服從正態分布的隨機變量(random variable)在一指數集(index set)內的組合,這個集合里面的任意有限個隨機變量都服從聯合正態分布。
對于一個連續域T,我們在連續域任選n個時刻,使得獲得一個n維向量都滿足其是一個n維高斯分布,則這個就是高斯過程。一個高斯過程可以通過一個均值函數和一個協方差函數完全確定。
高斯過程和高斯混合模型的區別?
高斯過程是無限個高斯分布的變量,高斯混合模型是有限個高斯分布的隨機變量。
(3)高斯過程回歸
高斯過程回歸模型是一個不太依賴于m(x)但是比較依賴核函數選擇的模型。(詳解另寫)
(4)采集函數
采集函數用于確定在何處采集下一個樣本點,它需要滿足下面的條件。
- 在已有的采樣點處采集函數的值更小,因為這些點已經被探索過,再在這些點處計算函數值對解決問題沒有什么用;
- 在置信區間更寬的點處采集函數的值更大,因為這些點具有更大的不確定性,更值得探索;
- 在函數均值更大的點處采集函數的值更大,因為均值是對該點處函數值的估計值,這些點更可能在極值點附近。
2.1.2 參數說明
目標函數:
fmin(fn=目標函數)
搜索空間:
fmin(fn=目標函數,space=搜索空間)
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)前閉后開的區間內的隨機整數。?
搜索算法:
fmin(fn=目標函數,space=搜索空間,algo=搜索算法)
隨機搜索(對應是hyperopt.rand.suggest),模擬退火(對應是hyperopt.anneal.suggest),TPE算法
可視化(Trials)偽代碼:
trials = Trials() best = fmin(fn=fn_dtree, space=space_dtree, algo=tpe.suggest, max_evals=1000, trials=trials)parameters = ['max_depth', 'max_features', 'criterion', 'scale','normalize'] # decision tree cols = len(parameters) f, axes = plt.subplots(nrows=1, ncols=cols, figsize=(20, 5)) cmap = plt.cm.jet for i, val in enumerate(parameters):xs = np.array([t['misc']['vals'][val] for t in trials.trials]).ravel()ys = [-t['result']['loss'] for t in trials.trials]ys = np.array(ys)axes[i].scatter(xs,ys,s=20,linewidth=0.01,alpha=0.5,c=cmap(float(i) / len(parameters)))axes[i].set_title(val)2.1.3算法實現
from sklearn.datasets import load_digits from sklearn.tree import DecisionTreeClassifier from sklearn.svm import SVC from sklearn.neighbors import KNeighborsClassifier from sklearn.model_selection import cross_val_score from hyperopt import fmin, tpe, hp,STATUS_OK, Trials #from sklearn.model_selection import RandomizedSearchCV #from scipy.stats import uniform digits = load_digits() X = digits.data y = digits.target print (X.shape, y.shape)def hyperopt_train_test(params):t = params['type']del params['type']if t == 'svm':clf = SVC(**params)elif t == 'dtree':clf = DecisionTreeClassifier(**params)elif t == 'knn':clf = KNeighborsClassifier(**params)else:return 0return cross_val_score(clf, X, y).mean()space = hp.choice('classifier_type', [{'type': 'naive_bayes','alpha': hp.uniform('alpha', 0.0, 2.0)},{'type': 'svm','C': hp.uniform('C', 0, 10.0),'kernel': hp.choice('kernel', ['linear', 'rbf']),'gamma': hp.uniform('gamma', 0, 20.0)},{'type': 'randomforest','max_depth': hp.choice('max_depth', range(1,20)),'max_features': hp.choice('max_features', range(1,5)),'n_estimators': hp.choice('n_estimators', range(1,20)),'criterion': hp.choice('criterion', ["gini", "entropy"]),'scale': hp.choice('scale', [0, 1]),'normalize': hp.choice('normalize', [0, 1])},{'type': 'knn','n_neighbors': hp.choice('knn_n_neighbors', range(1,50))} ])count = 0 best = 0 def f(params):global best, countcount += 1acc = hyperopt_train_test(params.copy())if acc > best:print ('new best:', acc, 'using', params['type'])best = accif count % 50 == 0:print ('iters:', count, ', acc:', acc, 'using', params)return {'loss': -acc, 'status': STATUS_OK}trials = Trials() best = fmin(f, space, algo=tpe.suggest, max_evals=1500, trials=trials) print ('best:') print (best)除了高斯過程回歸的序列超參優化之外,還有基于隨機森林、TPE的序列超參優化
參考:
一文秒懂貝葉斯優化/Bayesian Optimization
Hyperopt 入門指南
......
總結
以上是生活随笔為你收集整理的机器学习——超参数调优的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux C高级编程——文件操作之库函
- 下一篇: MOOC|Coursera课程批量下载(