算法模型自動(dòng)超參數(shù)優(yōu)化方法
什么是超參數(shù)?
學(xué)習(xí)器模型中一般有兩類參數(shù),一類是可以從數(shù)據(jù)中學(xué)習(xí)估計(jì)得到,我們稱為參數(shù)(Parameter)。還有一類參數(shù)時(shí)無法從數(shù)據(jù)中估計(jì),只能靠人的經(jīng)驗(yàn)進(jìn)行設(shè)計(jì)指定,我們稱為超參數(shù)(Hyper parameter)。超參數(shù)是在開始學(xué)習(xí)過程之前設(shè)置值的參數(shù)。相反,其他參數(shù)的值通過訓(xùn)練得出。
超參數(shù):
定義關(guān)于模型的更高層次的概念,如復(fù)雜性或?qū)W習(xí)能力 不能直接從標(biāo)準(zhǔn)模型培訓(xùn)過程中的數(shù)據(jù)中學(xué)習(xí),需要預(yù)先定義 可以通過設(shè)置不同的值,訓(xùn)練不同的模型和選擇更好的測(cè)試值來決定 參數(shù)空間的搜索一般由以下幾個(gè)部分構(gòu)成:
-
一個(gè)estimator(回歸器 or 分類器)
-
一個(gè)參數(shù)空間
-
一個(gè)搜索或采樣方法來獲得候選參數(shù)集合
-
一個(gè)交叉驗(yàn)證機(jī)制
-
一個(gè)評(píng)分函數(shù)
Scikit-Learn中的超參數(shù)優(yōu)化方法
在機(jī)器學(xué)習(xí)模型中,比如隨機(jī)森林中決策樹的個(gè)數(shù),人工神經(jīng)網(wǎng)絡(luò)模型中的隱藏層層數(shù)和每層的節(jié)點(diǎn)個(gè)數(shù),正則項(xiàng)中常數(shù)大小等等,它們都需要事先指定。超參數(shù)選擇不恰當(dāng),就會(huì)出現(xiàn)欠擬合或者過擬合的問題。在Scikit-Learn中,超參數(shù)是在學(xué)習(xí)過程開始之前設(shè)置其值的參數(shù)。典型的例子包括支持向量機(jī)里的C、kernel、gamma等。
- class sklearn.svm.SVC(*, C=1.0, kernel='rbf', degree=3, gamma='scale', coef0=0.0, shrinking=True, probability=False, tol=0.001, cache_size=200, class_weight=None, verbose=False, max_iter=-1, decision_function_shape='ovr', break_ties=False, random_state=None)
使用過程中可以使用estimator.get_params() 獲得學(xué)習(xí)器模型的超參數(shù)列表和當(dāng)前取值。
Sklearn提供了兩種通用的超參數(shù)優(yōu)化方法:網(wǎng)格搜索與隨機(jī)搜索。
交叉驗(yàn)證 (Cross-Validation)- CV 簡(jiǎn)介
在機(jī)器學(xué)習(xí)里,通常來說我們不能將全部用于數(shù)據(jù)訓(xùn)練模型,否則我們將沒有數(shù)據(jù)集對(duì)該模型進(jìn)行驗(yàn)證,從而評(píng)估我們的模型的預(yù)測(cè)效果。為了解決這一問題,有如下常用的方法:
The Validation Set Approach(驗(yàn)證集方案)
這種是方法最簡(jiǎn)單的,也是很容易就想到的。我們可以把整個(gè)數(shù)據(jù)集分成兩部分,一部分用于訓(xùn)練,一部分用于驗(yàn)證,這也就是我們經(jīng)常提到的訓(xùn)練集(training set)和測(cè)試集(test set)。
不過,這個(gè)簡(jiǎn)單的方法存在兩個(gè)弊端:
-
最終模型與參數(shù)的選取將極大程度依賴于你對(duì)訓(xùn)練集和測(cè)試集的劃分方法。在不同的劃分方法下,test MSE的變動(dòng)是很大的,而且對(duì)應(yīng)的最優(yōu)degree也不一樣。所以如果我們的訓(xùn)練集和測(cè)試集的劃分方法不夠好,很有可能無法選擇到最好的模型與參數(shù)。
-
該方法只用了部分?jǐn)?shù)據(jù)進(jìn)行模型的訓(xùn)練。當(dāng)用于模型訓(xùn)練的數(shù)據(jù)量越大時(shí),訓(xùn)練出來的模型通常效果會(huì)越好。所以訓(xùn)練集和測(cè)試集的劃分意味著我們無法充分利用我們手頭已有的數(shù)據(jù),所以得到的模型效果也會(huì)受到一定的影響。
基于這樣的背景,有人就提出了Cross-Validation方法,也就是交叉驗(yàn)證。
Cross-Validation
LOOCV(留一法)
LOOCV即(Leave-one-out cross-validation)。像Test set approach一樣,LOOCV方法也包含將數(shù)據(jù)集分為訓(xùn)練集和測(cè)試集這一步驟。但是不同的是,我們只用一個(gè)數(shù)據(jù)作為測(cè)試集,其他的數(shù)據(jù)都作為訓(xùn)練集,并將此步驟重復(fù)N次(N為數(shù)據(jù)集的數(shù)據(jù)數(shù)量)。
假設(shè)我們現(xiàn)在有n個(gè)數(shù)據(jù)組成的數(shù)據(jù)集,那么LOOCV的方法就是每次取出一個(gè)數(shù)據(jù)作為測(cè)試集的唯一元素,而其他n-1個(gè)數(shù)據(jù)都作為訓(xùn)練集用于訓(xùn)練模型和調(diào)參。結(jié)果就是我們最終訓(xùn)練了n個(gè)模型,每次都能得到一個(gè)MSE。而計(jì)算最終test MSE則就是將這n個(gè)MSE取平均。
比起test set approach,LOOCV有很多優(yōu)點(diǎn)。首先它不受測(cè)試集合訓(xùn)練集劃分方法的影響,因?yàn)槊恳粋€(gè)數(shù)據(jù)都單獨(dú)的做過測(cè)試集。同時(shí),其用了n-1個(gè)數(shù)據(jù)訓(xùn)練模型,也幾乎用到了所有的數(shù)據(jù),保證了模型的bias更小。不過LOOCV的缺點(diǎn)也很明顯,那就是計(jì)算量過于大,是test set approach耗時(shí)的n-1倍。
K-fold Cross Validation(k 折交叉驗(yàn)證)
K折交叉驗(yàn)證,和LOOCV的不同在于,我們每次的測(cè)試集將不再只包含一個(gè)數(shù)據(jù),而是多個(gè),具體數(shù)目將根據(jù)K的選取決定。比如,如果K=5,那么我們利用五折交叉驗(yàn)證的步驟就是:
-
將所有數(shù)據(jù)集分成5份
-
不重復(fù)地每次取其中一份做測(cè)試集,用其他四份做訓(xùn)練集訓(xùn)練模型,之后計(jì)算該模型在測(cè)試集上的MSE
-
將5次的MSE取平均作為最后而得到MSE
不難理解,其實(shí)LOOCV是一種特殊的K-fold Cross Validation(K=N)。最后K的選取是一個(gè)Bias和Variance的trade-off。K越大,每次投入的訓(xùn)練集的數(shù)據(jù)越多,模型的Bias越小。但是K越大,又意味著每一次選取的訓(xùn)練集之前的相關(guān)性越大(考慮最極端的例子,當(dāng)k=N,也就是在LOOCV里,每次都訓(xùn)練數(shù)據(jù)幾乎是一樣的)。而這種大相關(guān)性會(huì)導(dǎo)致最終的test error具有更大的Variance。一般K值選擇5或10。
網(wǎng)格搜索 GridSearchCV
我們?cè)谶x擇超參數(shù)有兩個(gè)途徑:1)憑經(jīng)驗(yàn);2)選擇不同大小的參數(shù),帶入到模型中,挑選表現(xiàn)最好的參數(shù)。通過途徑2選擇超參數(shù)時(shí),人力手動(dòng)調(diào)節(jié)注意力成本太高,非常不值得。For循環(huán)或類似于for循環(huán)的方法受限于太過分明的層次,不夠簡(jiǎn)潔與靈活,注意力成本高,易出錯(cuò)。GridSearchCV 稱為網(wǎng)格搜索交叉驗(yàn)證調(diào)參,它通過遍歷傳入的參數(shù)的所有排列組合,通過交叉驗(yàn)證的方式,返回所有參數(shù)組合下的評(píng)價(jià)指標(biāo)得分。
GridSearchCV聽起來很高大上,其實(shí)就是暴力搜索。注意的是,該方法在小數(shù)據(jù)集上很有用,數(shù)據(jù)集大了就不太適用了。數(shù)據(jù)量比較大的時(shí)候可以使用一個(gè)快速調(diào)優(yōu)的方法——坐標(biāo)下降。它其實(shí)是一種貪心算法:拿當(dāng)前對(duì)模型影響最大的參數(shù)調(diào)優(yōu),直到最優(yōu)化;再拿下一個(gè)影響最大的參數(shù)調(diào)優(yōu),如此下去,直到所有的參數(shù)調(diào)整完畢。這個(gè)方法的缺點(diǎn)就是可能會(huì)調(diào)到局部最優(yōu)而不是全局最優(yōu),但是省時(shí)間省力。
GridSearchCV使用說明
- class sklearn.model_selection.GridSearchCV(estimator, param_grid, scoring=None, n_jobs=None, refit=True, cv='warn', verbose=0, pre_dispatch='2*n_jobs', error_score='raise-deprecating', return_train_score='warn')
參數(shù)詳解:
-
estimator:所使用的模型,傳入除需要確定最佳的參數(shù)之外的其他參數(shù)。模型都需要一個(gè)score方法,或傳入scoring參數(shù)。
-
param_grid:需要搜索調(diào)參的參數(shù)字典,參數(shù)值類型為字典(dict)或由字典組成的列表(list)。用于設(shè)置待評(píng)測(cè)參數(shù)和對(duì)應(yīng)的參數(shù)值。
-
scoring:模型評(píng)價(jià)標(biāo)準(zhǔn),默認(rèn)None,這時(shí)需要使用score函數(shù);或者如scoring=’roc_auc’,根據(jù)所選模型不同,評(píng)價(jià)準(zhǔn)則不同。字符串(函數(shù)名),或是可調(diào)用對(duì)象,需要其函數(shù)簽名形如:scorer(estimator, X, y);如果是None,則使用estimator的誤差估計(jì)函數(shù)。下文表格中詳細(xì)指定了score可取的值和函數(shù)形式。
-
n_jobs:并行計(jì)算線程個(gè)數(shù),1:默認(rèn)值,可以設(shè)置為 -1(跟CPU核數(shù)一致),這樣可以充分使用機(jī)器的所有處理器。
-
refit:默認(rèn)為True,程序?qū)?huì)以交叉驗(yàn)證訓(xùn)練集得到的最佳參數(shù)。即在搜索參數(shù)結(jié)束后,用最佳參數(shù)結(jié)果再次fit一遍全部數(shù)據(jù)集。
-
cv:交叉驗(yàn)證參數(shù),可接受的參數(shù):
-
默認(rèn)None,使用3折交叉驗(yàn)證。
-
指定fold數(shù)量
-
CV splitter
-
yield訓(xùn)練、測(cè)試數(shù)據(jù)的生成器。
-
-
verbose:日志冗長(zhǎng)度
-
0:不輸出訓(xùn)練過程
-
1:偶爾輸出
-
dayda'y'd1:對(duì)每個(gè)子模型都輸出
-
-
pre_dispatch:指定總共分發(fā)的并行任務(wù)數(shù)。當(dāng)n_jobs大于1時(shí),數(shù)據(jù)將在每個(gè)運(yùn)行點(diǎn)進(jìn)行復(fù)制,這可能導(dǎo)致內(nèi)存問題,而設(shè)置pre_dispatch參數(shù),則可以預(yù)先劃分總共的job數(shù)量,使數(shù)據(jù)最多被復(fù)制pre_dispatch次。
-
error_score:擬合中發(fā)生錯(cuò)誤時(shí)分配的值,如果設(shè)置為’raise’則會(huì)引發(fā)錯(cuò)誤。如果設(shè)置的是一個(gè)數(shù)字,則為引發(fā)FitFailedWarning的警告信息,默認(rèn)值將在22版本其由原先的’raise’ 更改為np.nan。
-
return_train_score:如果“False”,cv_results_屬性將不包括訓(xùn)練分?jǐn)?shù)。
GridSearchCV對(duì)象
-
cv_results_:用來輸出cv結(jié)果的,可以是字典形式也可以是numpy形式,還可以轉(zhuǎn)換成DataFrame格式
-
best_estimator_:通過搜索參數(shù)得到的最好的估計(jì)器,當(dāng)參數(shù)refit=False時(shí)該對(duì)象不可用
-
best_score_:float類型,輸出最好的成績(jī)
-
best_params_:通過網(wǎng)格搜索得到的score最好對(duì)應(yīng)的參數(shù)
-
best_index_:對(duì)應(yīng)于最佳候選參數(shù)設(shè)置的索引(cv_results_數(shù)組)。cv_results _ [‘params’] [search.best_index_]中的dict給出了最佳模型的參數(shù)設(shè)置,給出了最高的平均分?jǐn)?shù)(best_score_)。
-
scorer_:評(píng)分函數(shù)
-
n_splits_:交叉驗(yàn)證的數(shù)量
-
refit_time_:refit所用的時(shí)間,當(dāng)參數(shù)refit=False時(shí)該對(duì)象不可用
GridSearchCV方法
-
decision_function(X):返回決策函數(shù)值(比如svm中的決策距離)
-
fit(X,y=None,groups=None,fit_params):在數(shù)據(jù)集上運(yùn)行所有的參數(shù)組合
-
get_params(deep=True):返回估計(jì)器的參數(shù)
-
inverse_transform(Xt):Call inverse_transform on the estimator with the best found params.
-
predict(X):返回預(yù)測(cè)結(jié)果值(0/1)
-
predict_log_proba(X):Call predict_log_proba on the estimator with the best found parameters.
-
predict_proba(X):返回每個(gè)類別的概率值(有幾類就返回幾列值)
-
score(X, y=None):返回函數(shù)
-
set_params(**params):Set the parameters of this estimator.
-
transform(X):在X上使用訓(xùn)練好的參數(shù)
使用示例:
- 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_)
隨機(jī)搜索 RandomizedSearchCV
我們?cè)谒阉鞒瑓?shù)的時(shí)候,如果超參數(shù)個(gè)數(shù)較少(三四個(gè)或者更少),那么我們可以采用網(wǎng)格搜索,一種窮盡式的搜索方法。但是當(dāng)超參數(shù)個(gè)數(shù)比較多的時(shí)候,我們?nèi)匀徊捎镁W(wǎng)格搜索,那么搜索所需時(shí)間將會(huì)指數(shù)級(jí)上升。所以有人就提出了隨機(jī)搜索的方法,隨機(jī)在超參數(shù)空間中搜索幾十幾百個(gè)點(diǎn),其中就有可能有比較小的值。這種做法比上面稀疏化網(wǎng)格的做法快,而且實(shí)驗(yàn)證明,隨機(jī)搜索法結(jié)果比稀疏網(wǎng)格法稍好。
RandomizedSearchCV使用方法和類GridSearchCV 很相似,但他不是嘗試所有可能的組合,而是通過選擇每一個(gè)超參數(shù)的一個(gè)隨機(jī)值的特定數(shù)量的隨機(jī)組合,這個(gè)方法有兩個(gè)優(yōu)點(diǎn):
相比于整體參數(shù)空間,可以選擇相對(duì)較少的參數(shù)組合數(shù)量。如果讓隨機(jī)搜索運(yùn)行,它會(huì)探索每個(gè)超參數(shù)的不同的值 可以方便的通過設(shè)定搜索次數(shù),控制超參數(shù)搜索的計(jì)算量。添加參數(shù)節(jié)點(diǎn)不會(huì)影響性能,不會(huì)降低效率。RandomizedSearchCV的使用方法其實(shí)是和GridSearchCV一致的,但它以隨機(jī)在參數(shù)空間中采樣的方式代替了GridSearchCV對(duì)于參數(shù)的網(wǎng)格搜索,在對(duì)于有連續(xù)變量的參數(shù)時(shí),RandomizedSearchCV會(huì)將其當(dāng)做一個(gè)分布進(jìn)行采樣進(jìn)行這是網(wǎng)格搜索做不到的,它的搜索能力取決于設(shè)定的n_iter參數(shù)。
RandomizedSearchCV使用說明
- class sklearn.model_selection.RandomizedSearchCV(estimator, param_distributions, *, n_iter=10, scoring=None, n_jobs=None , refit=True, cv=None, verbose=0, pre_dispatch='2*n_jobs', random_state=None, error_score=nan, return_train_score=False)
與GridSearchCV不同的主要有以下兩參數(shù):
-
param_distributions:參數(shù)分布,字典格式。將我們所傳入模型當(dāng)中的參數(shù)組合為一個(gè)字典。其搜索策略如下:
-
對(duì)于搜索范圍是distribution的超參數(shù),根據(jù)給定的distribution隨機(jī)采樣
-
對(duì)于搜索范圍是list的超參數(shù),在給定的list中等概率采樣
-
-
n_iter:訓(xùn)練300次,數(shù)值越大,獲得的參數(shù)精度越大,但是搜索時(shí)間越長(zhǎng) 使用示例:
- 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
- # 載入數(shù)據(jù)
- digits = load_digits()
- X, y = digits.data, digits.target
- # 建立一個(gè)分類器或者回歸器
- clf = RandomForestClassifier(n_estimators=20)
- # 給定參數(shù)搜索范圍: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選取超參數(shù)
- 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_)
自動(dòng)超參數(shù)優(yōu)化方法
貝葉斯優(yōu)化方法(Bayesian Optimization)
貝葉斯優(yōu)化用于機(jī)器學(xué)習(xí)調(diào)參由J. Snoek(2012)提出,主要思想是,給定優(yōu)化的目標(biāo)函數(shù)(廣義的函數(shù),只需指定輸入和輸出即可,無需知道內(nèi)部結(jié)構(gòu)以及數(shù)學(xué)性質(zhì)),通過不斷地添加樣本點(diǎn)來更新目標(biāo)函數(shù)的后驗(yàn)分布(高斯過程,直到后驗(yàn)分布基本貼合于真實(shí)分布。簡(jiǎn)單的說,就是考慮了上一次參數(shù)的信息,從而更好的調(diào)整當(dāng)前的參數(shù)。
貝葉斯優(yōu)化與常規(guī)的網(wǎng)格搜索或者隨機(jī)搜索的區(qū)別是:
-
貝葉斯調(diào)參采用高斯過程,考慮之前的參數(shù)信息,不斷地更新先驗(yàn);網(wǎng)格搜索未考慮之前的參數(shù)信息
-
貝葉斯調(diào)參迭代次數(shù)少,速度快;網(wǎng)格搜索速度慢,參數(shù)多時(shí)易導(dǎo)致維度爆炸
-
貝葉斯調(diào)參針對(duì)非凸問題依然穩(wěn)?。痪W(wǎng)格搜索針對(duì)非凸問題易得到局部最優(yōu)
-
貝葉斯優(yōu)化提供了一個(gè)優(yōu)雅的框架來盡可能少的步驟中找到全局最小值。
讓我們構(gòu)造一個(gè)函數(shù)c(x)或者一個(gè)接收輸入x的模型,如下圖所示為c(x)的形狀。當(dāng)然,優(yōu)化器并不知道該函數(shù),稱之為“目標(biāo)函數(shù)”。
貝葉斯優(yōu)化通過代理優(yōu)化的方式來完成任務(wù)。代理函數(shù)通過采樣點(diǎn)模擬構(gòu)造(見下圖)。
根據(jù)代理函數(shù),我們大致可以確定哪些點(diǎn)是可能的最小值。然后再這些點(diǎn)附近做更多的采樣,并隨之更新代理函數(shù)。
每一次迭代,我們都會(huì)繼續(xù)觀察當(dāng)前的代用函數(shù),通過采樣了解更多感興趣的區(qū)域,并更新函數(shù)。需要注意的是,代用函數(shù)在數(shù)學(xué)上的表達(dá)方式將大大降低評(píng)估成本。經(jīng)過一定的迭代次數(shù)后,我們注定要到達(dá)一個(gè)全局最小值,除非函數(shù)的形狀非常詭異。
讓我們仔細(xì)看看代用函數(shù),通常用高斯過程來表示,它可以被認(rèn)為是擲骰子,返回與給定數(shù)據(jù)點(diǎn)(如sin、log)擬合的函數(shù),而不是1到6的數(shù)字。這個(gè)過程會(huì)返回幾個(gè)函數(shù),這些函數(shù)都附有概率。為什么用高斯過程,而不是其他的曲線擬合方法來模擬代用函數(shù),有一個(gè)很好的理由:它是貝葉斯性質(zhì)的。代用函數(shù)–表示為概率分布,即先驗(yàn)–被更新為 “獲取函數(shù)”。這個(gè)函數(shù)負(fù)責(zé)在勘探和開發(fā)的權(quán)衡中提出新的測(cè)試點(diǎn)。
-
“開發(fā)”力求在代用模型預(yù)測(cè)的目標(biāo)好的地方采樣。這就是利用已知的有希望的點(diǎn)。但是,如果我們已經(jīng)對(duì)某一區(qū)域進(jìn)行了足夠的探索,那么不斷地利用已知的信息就不會(huì)有什么收獲。
-
“探索”力求在不確定性較高的地點(diǎn)進(jìn)行采樣。這就確保了空間的任何主要區(qū)域都不會(huì)未被探索–全局最小值可能恰好就在那里。
一個(gè)鼓勵(lì)過多的開發(fā)和過少探索的獲取函數(shù)將導(dǎo)致模型只停留在它首先發(fā)現(xiàn)的最小值(通常是局部的–“只去有光的地方”)。一個(gè)鼓勵(lì)相反的獲取函數(shù)將不會(huì)首先停留在一個(gè)最小值,本地或全球。在微妙的平衡中產(chǎn)生良好的結(jié)果。acquisition 函數(shù),我們將其表示為a(x),必須同時(shí)考慮開發(fā)和探索。常見的獲取函數(shù)包括預(yù)期改進(jìn)和最大改進(jìn)概率,所有這些函數(shù)都是在給定先驗(yàn)信息(高斯過程)的情況下,衡量特定投入在未來可能得到回報(bào)的概率。
讓我們把這些東西整合起來。貝葉斯優(yōu)化可以這樣進(jìn)行。
-
初始化一個(gè)高斯過程 “代用函數(shù) “的先驗(yàn)分布。
-
選擇幾個(gè)數(shù)據(jù)點(diǎn)x,使在當(dāng)前先驗(yàn)分布上運(yùn)行的獲取函數(shù)a(x)最大化。
-
評(píng)估目標(biāo)成本函數(shù)c(x)中的數(shù)據(jù)點(diǎn)x,得到結(jié)果,y。
-
用新的數(shù)據(jù)更新高斯過程先驗(yàn)分布,以產(chǎn)生一個(gè)后驗(yàn)(它將成為下一步的先驗(yàn))。
-
重復(fù)步驟2-5進(jìn)行多次迭代。
-
解釋當(dāng)前的高斯過程分布(這是非常便宜的),以找到全局最小值。
貝葉斯優(yōu)化就是把概率論的思想放在代入優(yōu)化的思想后面。綜上所述:
-
代用優(yōu)化利用代用函數(shù)或近似函數(shù)通過抽樣來估計(jì)目標(biāo)函數(shù)。
-
貝葉斯優(yōu)化將代用優(yōu)化置于概率框架中,將代用函數(shù)表示為概率分布,可以根據(jù)新的信息進(jìn)行更新。
-
獲取函數(shù)用于評(píng)估在當(dāng)前已知的先驗(yàn)條件下,探索空間中某一點(diǎn)會(huì)產(chǎn)生 “好 “收益的概率,平衡探索與開發(fā)
-
主要在目標(biāo)函數(shù)評(píng)估成本很高的時(shí)候使用貝葉斯優(yōu)化,常用于超參數(shù)調(diào)整。
Hyperopt
Hyperopt是一個(gè)強(qiáng)大的Python庫,用于超參數(shù)優(yōu)化,由jamesbergstra開發(fā)。Hyperopt使用貝葉斯優(yōu)化的形式進(jìn)行參數(shù)調(diào)整,允許你為給定模型獲得最佳參數(shù)。它可以在大范圍內(nèi)優(yōu)化具有數(shù)百個(gè)參數(shù)的模型。
Hyperopt包含4個(gè)重要的特性
1、搜索空間
hyperopt有不同的函數(shù)來指定輸入?yún)?shù)的范圍,這些是隨機(jī)搜索空間。選擇最常用的搜索選項(xiàng):
-
choice(label, options)-這可用于分類參數(shù),它返回其中一個(gè)選項(xiàng),它應(yīng)該是一個(gè)列表或元組。示例:hp.choice(“criterion”,[“gini”,”entropy”,])
-
randint(label, upper)-可用于整數(shù)參數(shù),它返回范圍(0,upper)內(nèi)的隨機(jī)整數(shù)。示例:hp.randint(“max_features”,50)
-
uniform(label, low, high)-它返回一個(gè)介于low和high之間的值。示例:hp.uniform(“max_leaf_nodes”,1,10)
你可以使用的其他選項(xiàng)包括:
-
normal(label, mu, sigma)-這將返回一個(gè)實(shí)際值,該值服從均值為mu和標(biāo)準(zhǔn)差為sigma的正態(tài)分布
-
qnormal(label, mu, sigma, q)-返回一個(gè)類似round(normal(mu, sigma) / q) * q的值
-
lognormal(label, mu, sigma)-返回exp(normal(mu, sigma))
-
qlognormal(label, mu, sigma, q) -返回一個(gè)類似round(exp(normal(mu, sigma)) / q) * q的值
2、目標(biāo)函數(shù)
這是一個(gè)最小化函數(shù),它從搜索空間接收超參數(shù)值作為輸入并返回?fù)p失。這意味著在優(yōu)化過程中,我們使用選定的超參數(shù)值訓(xùn)練模型并預(yù)測(cè)目標(biāo)特征,然后評(píng)估預(yù)測(cè)誤差并將其返回給優(yōu)化器。優(yōu)化器將決定要檢查哪些值并再次迭代。你將在一個(gè)實(shí)際例子中學(xué)習(xí)如何創(chuàng)建一個(gè)目標(biāo)函數(shù)。
3、fmin
-
fmin函數(shù)是對(duì)不同的算法集及其超參數(shù)進(jìn)行迭代,然后使目標(biāo)函數(shù)最小化的優(yōu)化函數(shù)。fmin有5個(gè)輸入是:
-
最小化的目標(biāo)函數(shù)
-
定義的搜索空間
-
使用的搜索算法有隨機(jī)搜索、TPE(Tree-Parzen估計(jì)器)和自適應(yīng)TPE。注意:rand.suggest以及hyperopt.tpe.suggest為超參數(shù)空間的順序搜索提供邏輯。
-
最大評(píng)估數(shù)
-
trials對(duì)象(可選)
4、試驗(yàn)對(duì)象
Trials對(duì)象用于保存所有超參數(shù)、損失和其他信息,這意味著你可以在運(yùn)行優(yōu)化后訪問它們。此外,trials 可以幫助你保存和加載重要信息,然后繼續(xù)優(yōu)化過程。
Hyperopt的使用
在理解了Hyperopt的重要特性之后,下面將介紹Hyperopt的使用方法。
-
初始化要搜索的空間
-
定義目標(biāo)函數(shù)
-
選擇要使用的搜索算法
-
運(yùn)行hyperopt函數(shù)
-
分析測(cè)試對(duì)象中存儲(chǔ)的評(píng)估輸出
- from sklearn import datasets
- from hyperopt import fmin, tpe, hp, STATUS_OK, Trials
- from sklearn.neighbors import KNeighborsClassifier
- from sklearn.model_selection import cross_val_score
- iris = datasets.load_iris()
- X = iris.data
- y = iris.target
- def hyperopt_train_test(params):
- clf = KNeighborsClassifier(**params)
- return cross_val_score(clf, X, y).mean()
- # 定義參數(shù)空間
- space_knn = {
- 'n_neighbors': hp.choice('n_neighbors', range(1, 100))
- }
- # 定義最小化函數(shù)(目標(biāo)函數(shù))
- def fn_knn(params):
- acc = hyperopt_train_test(params)
- return {'loss': -acc, 'status': STATUS_OK} # hyperopt最小化函數(shù),所以在acc中添加了負(fù)號(hào)
- # 實(shí)例化Trial 對(duì)象,對(duì)模型進(jìn)行微調(diào),然后用其超參數(shù)值打印出最佳損失
- trials = Trials()
- best = fmin(fn_knn, space_knn, algo=tpe.suggest, max_evals=100, trials=trials)
- print("Best: {}".format(best))
- print(trials.results) # 搜索期間“objective”返回的詞典列表。
algo指定搜索算法,目前支持以下算法:
-
隨機(jī)搜索(hyperopt.rand.suggest)
-
模擬退火(hyperopt.anneal.suggest)
-
TPE算法(tpe.suggest,算法全稱為Tree-structured Parzen Estimator Approach)
除了Hyperopt外,貝葉斯優(yōu)化方法的Python包還有:
-
https://github.com/optuna/optuna
-
https://github.com/fmfn/BayesianOptimization
-
https://github.com/HIPS/Spearmint
遺傳算法(Genetic Algorithms)
遺傳算法試圖將自然選擇機(jī)制應(yīng)用于機(jī)器學(xué)習(xí)環(huán)境。它受到達(dá)爾文自然選擇過程的啟發(fā),因此通常也稱為進(jìn)化算法。假設(shè)我們創(chuàng)建了具有一些預(yù)定義超參數(shù)的N個(gè)機(jī)器學(xué)習(xí)模型。然后,我們可以計(jì)算每個(gè)模型的準(zhǔn)確性,并決定只保留一半模型(性能最好的模型)?,F(xiàn)在,我們可以生成具有與最佳模型相似的超參數(shù)的后代,以便再次獲得N個(gè)模型的種群。在這一點(diǎn)上,我們可以再次計(jì)算每個(gè)模型的準(zhǔn)確性,并在定義的世代中重復(fù)該循環(huán)。這樣,只有最佳模型才能在流程結(jié)束時(shí)生存下來。
TPOT是一種基于遺傳算法優(yōu)化機(jī)器學(xué)習(xí)管道(pipeline)的Python自動(dòng)機(jī)器學(xué)習(xí)工具。簡(jiǎn)單來說,就是TPOT可以智能地探索數(shù)千個(gè)可能的pipeline,為數(shù)據(jù)集找到最好的pipeline,從而實(shí)現(xiàn)機(jī)器學(xué)習(xí)中最乏味的部分。
更重要地是,一旦TPOT完成搜索,TPOT同時(shí)也提供了Python代碼。通過這個(gè)代碼,我們可以具體地知道TPOT獲得最優(yōu)性能時(shí)的具體pipeline的內(nèi)容,這對(duì)于后續(xù)修改是十分方便的!
TPOT是在sklearn的基礎(chǔ)之上做的封裝庫。其主要封裝了sklearn的模型相關(guān)模塊、processesing模塊和feature_selection模塊,所以TPOT的主要功能是集中在使用pipeline的方式完成模型的數(shù)據(jù)預(yù)處理、特征選擇和模型選擇方面。此外,我們還發(fā)現(xiàn)了TPOT已經(jīng)對(duì)xgboost進(jìn)行了支持。
雖然TPOT使用遺傳算法代替了傳統(tǒng)的網(wǎng)格搜索進(jìn)行超參數(shù)選擇,但由于默認(rèn)初始值的隨機(jī)性,在少量的進(jìn)化(迭代)次數(shù)下,TPOT最終選擇的模型往往并不相同。
計(jì)算效率問題。作者在代碼中寫道:進(jìn)化(迭代)次數(shù)和每一代保留的個(gè)體數(shù)量值越多,最終得模型得分會(huì)越高。但這同樣也會(huì)導(dǎo)致耗時(shí)很長(zhǎng)。如果使用相當(dāng)復(fù)雜的數(shù)據(jù)集或運(yùn)行TPOT短時(shí)間,不同的TPOT運(yùn)行可能會(huì)導(dǎo)致不同的流水線推薦。TPOT的優(yōu)化算法本質(zhì)上是隨機(jī)的,這意味著它使用隨機(jī)性(部分地)來搜索可能的流水線空間。當(dāng)兩個(gè)TPOT運(yùn)行推薦不同的管道時(shí),這意味著TPOT運(yùn)行由于時(shí)間不夠而不收斂,或者多個(gè)管道在數(shù)據(jù)集上執(zhí)行的次數(shù)大致相同。這實(shí)際上是一個(gè)優(yōu)于固定網(wǎng)格搜索技術(shù)的優(yōu)點(diǎn):TPOT是一個(gè)助手,它通過探索您可能從未考慮過的流水線配置來提供解決如何解決特定機(jī)器學(xué)習(xí)問題的想法,然后將微調(diào)留給更受約束的參數(shù)調(diào)整技術(shù),例如網(wǎng)格搜索。
使用TPOT(版本0.9.5)開發(fā)模型需要把握以下幾點(diǎn):
-
在使用TPOT進(jìn)行建模前需要對(duì)數(shù)據(jù)進(jìn)行必要的清洗和特征工程操作。
-
TPOT目前只能做有監(jiān)督學(xué)習(xí)。
-
TPOT目前支持的分類器主要有貝葉斯、決策樹、集成樹、SVM、KNN、線性模型、xgboost。
-
TPOT目前支持的回歸器主要有決策樹、集成樹、線性模型、xgboost。
-
TPOT會(huì)對(duì)輸入的數(shù)據(jù)做進(jìn)一步處理操作,例如二值化、聚類、降維、標(biāo)準(zhǔn)化、正則化、獨(dú)熱編碼操作等。
-
根據(jù)模型效果,TPOT會(huì)對(duì)輸入特征做特征選擇操作,包括基于樹模型、基于方差、基于F-值的百分比。
-
可以通過export()方法把訓(xùn)練過程導(dǎo)出為形式為sklearn pipeline的.py文件
示例代碼:
- from tpot import TPOTClassifier
- from sklearn.datasets import load_iris
- from sklearn.model_selection import train_test_split
- iris = load_iris()
- X = iris.data
- y = iris.target
- X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
- tpot = TPOTClassifier(generations=5, population_size=50, verbosity=2, n_jobs=-1)
- tpot.fit(X_train, y_train)
- print(tpot.score(X_test, y_test))
TPOT的主要參數(shù):
-
generations – 確定創(chuàng)建子代(新個(gè)體)的迭代次數(shù)
-
population_size – 創(chuàng)建個(gè)體的初始數(shù)量(這些用于創(chuàng)建后代)
-
offspring_size – 每一代所需創(chuàng)造的新個(gè)體數(shù)
-
mutation_rate – 出現(xiàn)屬性值隨機(jī)更改的概率(包括新參數(shù)的方法,在初始群體中可能不可用)
-
crossover_rate –用于創(chuàng)造后代的個(gè)體所占的百分比
使用這個(gè)迭代過程,我們選出最佳配置。準(zhǔn)備遺傳算法的結(jié)果一般取決于初始狀態(tài)。因此,它隨機(jī)產(chǎn)生的初始種群影響輸出,重新運(yùn)行相同的設(shè)置可能會(huì)輸出不同的結(jié)果。