算法模型自動超參數(shù)優(yōu)化方法
什么是超參數(shù)?
學(xué)習(xí)器模型中一般有兩類參數(shù),一類是可以從數(shù)據(jù)中學(xué)習(xí)估計得到,我們稱為參數(shù)(Parameter)。還有一類參數(shù)時無法從數(shù)據(jù)中估計,只能靠人的經(jīng)驗進(jìn)行設(shè)計指定,我們稱為超參數(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)練不同的模型和選擇更好的測試值來決定 參數(shù)空間的搜索一般由以下幾個部分構(gòu)成:
- 
    
一個estimator(回歸器 or 分類器)
 - 
    
一個參數(shù)空間
 - 
    
一個搜索或采樣方法來獲得候選參數(shù)集合
 - 
    
一個交叉驗證機(jī)制
 - 
    
一個評分函數(shù)
 
Scikit-Learn中的超參數(shù)優(yōu)化方法
在機(jī)器學(xué)習(xí)模型中,比如隨機(jī)森林中決策樹的個數(shù),人工神經(jīng)網(wǎng)絡(luò)模型中的隱藏層層數(shù)和每層的節(jié)點個數(shù),正則項中常數(shù)大小等等,它們都需要事先指定。超參數(shù)選擇不恰當(dāng),就會出現(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ī)搜索。

交叉驗證 (Cross-Validation)- CV 簡介
在機(jī)器學(xué)習(xí)里,通常來說我們不能將全部用于數(shù)據(jù)訓(xùn)練模型,否則我們將沒有數(shù)據(jù)集對該模型進(jìn)行驗證,從而評估我們的模型的預(yù)測效果。為了解決這一問題,有如下常用的方法:
The Validation Set Approach(驗證集方案)
這種是方法最簡單的,也是很容易就想到的。我們可以把整個數(shù)據(jù)集分成兩部分,一部分用于訓(xùn)練,一部分用于驗證,這也就是我們經(jīng)常提到的訓(xùn)練集(training set)和測試集(test set)。
不過,這個簡單的方法存在兩個弊端:
- 
    
最終模型與參數(shù)的選取將極大程度依賴于你對訓(xùn)練集和測試集的劃分方法。在不同的劃分方法下,test MSE的變動是很大的,而且對應(yīng)的最優(yōu)degree也不一樣。所以如果我們的訓(xùn)練集和測試集的劃分方法不夠好,很有可能無法選擇到最好的模型與參數(shù)。
 

- 
    
該方法只用了部分?jǐn)?shù)據(jù)進(jìn)行模型的訓(xùn)練。當(dāng)用于模型訓(xùn)練的數(shù)據(jù)量越大時,訓(xùn)練出來的模型通常效果會越好。所以訓(xùn)練集和測試集的劃分意味著我們無法充分利用我們手頭已有的數(shù)據(jù),所以得到的模型效果也會受到一定的影響。
 
基于這樣的背景,有人就提出了Cross-Validation方法,也就是交叉驗證。
Cross-Validation
LOOCV(留一法)
LOOCV即(Leave-one-out cross-validation)。像Test set approach一樣,LOOCV方法也包含將數(shù)據(jù)集分為訓(xùn)練集和測試集這一步驟。但是不同的是,我們只用一個數(shù)據(jù)作為測試集,其他的數(shù)據(jù)都作為訓(xùn)練集,并將此步驟重復(fù)N次(N為數(shù)據(jù)集的數(shù)據(jù)數(shù)量)。
假設(shè)我們現(xiàn)在有n個數(shù)據(jù)組成的數(shù)據(jù)集,那么LOOCV的方法就是每次取出一個數(shù)據(jù)作為測試集的唯一元素,而其他n-1個數(shù)據(jù)都作為訓(xùn)練集用于訓(xùn)練模型和調(diào)參。結(jié)果就是我們最終訓(xùn)練了n個模型,每次都能得到一個MSE。而計算最終test MSE則就是將這n個MSE取平均。

比起test set approach,LOOCV有很多優(yōu)點。首先它不受測試集合訓(xùn)練集劃分方法的影響,因為每一個數(shù)據(jù)都單獨的做過測試集。同時,其用了n-1個數(shù)據(jù)訓(xùn)練模型,也幾乎用到了所有的數(shù)據(jù),保證了模型的bias更小。不過LOOCV的缺點也很明顯,那就是計算量過于大,是test set approach耗時的n-1倍。
K-fold Cross Validation(k 折交叉驗證)
K折交叉驗證,和LOOCV的不同在于,我們每次的測試集將不再只包含一個數(shù)據(jù),而是多個,具體數(shù)目將根據(jù)K的選取決定。比如,如果K=5,那么我們利用五折交叉驗證的步驟就是:
- 
    
將所有數(shù)據(jù)集分成5份
 - 
    
不重復(fù)地每次取其中一份做測試集,用其他四份做訓(xùn)練集訓(xùn)練模型,之后計算該模型在測試集上的MSE
 - 
    
將5次的MSE取平均作為最后而得到MSE
 

不難理解,其實LOOCV是一種特殊的K-fold Cross Validation(K=N)。最后K的選取是一個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)性會導(dǎo)致最終的test error具有更大的Variance。一般K值選擇5或10。
網(wǎng)格搜索 GridSearchCV
我們在選擇超參數(shù)有兩個途徑:1)憑經(jīng)驗;2)選擇不同大小的參數(shù),帶入到模型中,挑選表現(xiàn)最好的參數(shù)。通過途徑2選擇超參數(shù)時,人力手動調(diào)節(jié)注意力成本太高,非常不值得。For循環(huán)或類似于for循環(huán)的方法受限于太過分明的層次,不夠簡潔與靈活,注意力成本高,易出錯。GridSearchCV 稱為網(wǎng)格搜索交叉驗證調(diào)參,它通過遍歷傳入的參數(shù)的所有排列組合,通過交叉驗證的方式,返回所有參數(shù)組合下的評價指標(biāo)得分。
GridSearchCV聽起來很高大上,其實就是暴力搜索。注意的是,該方法在小數(shù)據(jù)集上很有用,數(shù)據(jù)集大了就不太適用了。數(shù)據(jù)量比較大的時候可以使用一個快速調(diào)優(yōu)的方法——坐標(biāo)下降。它其實是一種貪心算法:拿當(dāng)前對模型影響最大的參數(shù)調(diào)優(yōu),直到最優(yōu)化;再拿下一個影響最大的參數(shù)調(diào)優(yōu),如此下去,直到所有的參數(shù)調(diào)整完畢。這個方法的缺點就是可能會調(diào)到局部最優(yōu)而不是全局最優(yōu),但是省時間省力。
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ù)。模型都需要一個score方法,或傳入scoring參數(shù)。
 - 
    
param_grid:需要搜索調(diào)參的參數(shù)字典,參數(shù)值類型為字典(dict)或由字典組成的列表(list)。用于設(shè)置待評測參數(shù)和對應(yīng)的參數(shù)值。
 - 
    
scoring:模型評價標(biāo)準(zhǔn),默認(rèn)None,這時需要使用score函數(shù);或者如scoring=’roc_auc’,根據(jù)所選模型不同,評價準(zhǔn)則不同。字符串(函數(shù)名),或是可調(diào)用對象,需要其函數(shù)簽名形如:scorer(estimator, X, y);如果是None,則使用estimator的誤差估計函數(shù)。下文表格中詳細(xì)指定了score可取的值和函數(shù)形式。
 

- 
    
n_jobs:并行計算線程個數(shù),1:默認(rèn)值,可以設(shè)置為 -1(跟CPU核數(shù)一致),這樣可以充分使用機(jī)器的所有處理器。
 - 
    
refit:默認(rèn)為True,程序?qū)越徊骝炞C訓(xùn)練集得到的最佳參數(shù)。即在搜索參數(shù)結(jié)束后,用最佳參數(shù)結(jié)果再次fit一遍全部數(shù)據(jù)集。
 - 
    
cv:交叉驗證參數(shù),可接受的參數(shù):
- 
        
默認(rèn)None,使用3折交叉驗證。
 - 
        
指定fold數(shù)量
 - 
        
CV splitter
 - 
        
yield訓(xùn)練、測試數(shù)據(jù)的生成器。
 
 - 
        
 - 
    
verbose:日志冗長度
- 
        
0:不輸出訓(xùn)練過程
 - 
        
1:偶爾輸出
 - 
        
dayda'y'd1:對每個子模型都輸出
 
 - 
        
 - 
    
pre_dispatch:指定總共分發(fā)的并行任務(wù)數(shù)。當(dāng)n_jobs大于1時,數(shù)據(jù)將在每個運(yùn)行點進(jìn)行復(fù)制,這可能導(dǎo)致內(nèi)存問題,而設(shè)置pre_dispatch參數(shù),則可以預(yù)先劃分總共的job數(shù)量,使數(shù)據(jù)最多被復(fù)制pre_dispatch次。
 - 
    
error_score:擬合中發(fā)生錯誤時分配的值,如果設(shè)置為’raise’則會引發(fā)錯誤。如果設(shè)置的是一個數(shù)字,則為引發(fā)FitFailedWarning的警告信息,默認(rèn)值將在22版本其由原先的’raise’ 更改為np.nan。
 - 
    
return_train_score:如果“False”,cv_results_屬性將不包括訓(xùn)練分?jǐn)?shù)。
 
GridSearchCV對象
- 
    
cv_results_:用來輸出cv結(jié)果的,可以是字典形式也可以是numpy形式,還可以轉(zhuǎn)換成DataFrame格式
 - 
    
best_estimator_:通過搜索參數(shù)得到的最好的估計器,當(dāng)參數(shù)refit=False時該對象不可用
 - 
    
best_score_:float類型,輸出最好的成績
 - 
    
best_params_:通過網(wǎng)格搜索得到的score最好對應(yīng)的參數(shù)
 - 
    
best_index_:對應(yīng)于最佳候選參數(shù)設(shè)置的索引(cv_results_數(shù)組)。cv_results _ [‘params’] [search.best_index_]中的dict給出了最佳模型的參數(shù)設(shè)置,給出了最高的平均分?jǐn)?shù)(best_score_)。
 - 
    
scorer_:評分函數(shù)
 - 
    
n_splits_:交叉驗證的數(shù)量
 - 
    
refit_time_:refit所用的時間,當(dāng)參數(shù)refit=False時該對象不可用
 
GridSearchCV方法
- 
    
decision_function(X):返回決策函數(shù)值(比如svm中的決策距離)
 - 
    
fit(X,y=None,groups=None,fit_params):在數(shù)據(jù)集上運(yùn)行所有的參數(shù)組合
 - 
    
get_params(deep=True):返回估計器的參數(shù)
 - 
    
inverse_transform(Xt):Call inverse_transform on the estimator with the best found params.
 - 
    
predict(X):返回預(yù)測結(jié)果值(0/1)
 - 
    
predict_log_proba(X):Call predict_log_proba on the estimator with the best found parameters.
 - 
    
predict_proba(X):返回每個類別的概率值(有幾類就返回幾列值)
 - 
    
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
我們在搜索超參數(shù)的時候,如果超參數(shù)個數(shù)較少(三四個或者更少),那么我們可以采用網(wǎng)格搜索,一種窮盡式的搜索方法。但是當(dāng)超參數(shù)個數(shù)比較多的時候,我們?nèi)匀徊捎镁W(wǎng)格搜索,那么搜索所需時間將會指數(shù)級上升。所以有人就提出了隨機(jī)搜索的方法,隨機(jī)在超參數(shù)空間中搜索幾十幾百個點,其中就有可能有比較小的值。這種做法比上面稀疏化網(wǎng)格的做法快,而且實驗證明,隨機(jī)搜索法結(jié)果比稀疏網(wǎng)格法稍好。
RandomizedSearchCV使用方法和類GridSearchCV 很相似,但他不是嘗試所有可能的組合,而是通過選擇每一個超參數(shù)的一個隨機(jī)值的特定數(shù)量的隨機(jī)組合,這個方法有兩個優(yōu)點:
相比于整體參數(shù)空間,可以選擇相對較少的參數(shù)組合數(shù)量。如果讓隨機(jī)搜索運(yùn)行,它會探索每個超參數(shù)的不同的值 可以方便的通過設(shè)定搜索次數(shù),控制超參數(shù)搜索的計算量。添加參數(shù)節(jié)點不會影響性能,不會降低效率。RandomizedSearchCV的使用方法其實是和GridSearchCV一致的,但它以隨機(jī)在參數(shù)空間中采樣的方式代替了GridSearchCV對于參數(shù)的網(wǎng)格搜索,在對于有連續(xù)變量的參數(shù)時,RandomizedSearchCV會將其當(dāng)做一個分布進(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ù)組合為一個字典。其搜索策略如下:
- 
        
對于搜索范圍是distribution的超參數(shù),根據(jù)給定的distribution隨機(jī)采樣
 - 
        
對于搜索范圍是list的超參數(shù),在給定的list中等概率采樣
 
 - 
        
 - 
    
n_iter:訓(xùn)練300次,數(shù)值越大,獲得的參數(shù)精度越大,但是搜索時間越長 使用示例:
 
- 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
 - # 建立一個分類器或者回歸器
 - 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_)
 
自動超參數(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ì)),通過不斷地添加樣本點來更新目標(biāo)函數(shù)的后驗分布(高斯過程,直到后驗分布基本貼合于真實分布。簡單的說,就是考慮了上一次參數(shù)的信息,從而更好的調(diào)整當(dāng)前的參數(shù)。
貝葉斯優(yōu)化與常規(guī)的網(wǎng)格搜索或者隨機(jī)搜索的區(qū)別是:
- 
    
貝葉斯調(diào)參采用高斯過程,考慮之前的參數(shù)信息,不斷地更新先驗;網(wǎng)格搜索未考慮之前的參數(shù)信息
 - 
    
貝葉斯調(diào)參迭代次數(shù)少,速度快;網(wǎng)格搜索速度慢,參數(shù)多時易導(dǎo)致維度爆炸
 - 
    
貝葉斯調(diào)參針對非凸問題依然穩(wěn)?。痪W(wǎng)格搜索針對非凸問題易得到局部最優(yōu)
 - 
    
貝葉斯優(yōu)化提供了一個優(yōu)雅的框架來盡可能少的步驟中找到全局最小值。
 
讓我們構(gòu)造一個函數(shù)c(x)或者一個接收輸入x的模型,如下圖所示為c(x)的形狀。當(dāng)然,優(yōu)化器并不知道該函數(shù),稱之為“目標(biāo)函數(shù)”。

貝葉斯優(yōu)化通過代理優(yōu)化的方式來完成任務(wù)。代理函數(shù)通過采樣點模擬構(gòu)造(見下圖)。

根據(jù)代理函數(shù),我們大致可以確定哪些點是可能的最小值。然后再這些點附近做更多的采樣,并隨之更新代理函數(shù)。

每一次迭代,我們都會繼續(xù)觀察當(dāng)前的代用函數(shù),通過采樣了解更多感興趣的區(qū)域,并更新函數(shù)。需要注意的是,代用函數(shù)在數(shù)學(xué)上的表達(dá)方式將大大降低評估成本。經(jīng)過一定的迭代次數(shù)后,我們注定要到達(dá)一個全局最小值,除非函數(shù)的形狀非常詭異。
讓我們仔細(xì)看看代用函數(shù),通常用高斯過程來表示,它可以被認(rèn)為是擲骰子,返回與給定數(shù)據(jù)點(如sin、log)擬合的函數(shù),而不是1到6的數(shù)字。這個過程會返回幾個函數(shù),這些函數(shù)都附有概率。為什么用高斯過程,而不是其他的曲線擬合方法來模擬代用函數(shù),有一個很好的理由:它是貝葉斯性質(zhì)的。代用函數(shù)–表示為概率分布,即先驗–被更新為 “獲取函數(shù)”。這個函數(shù)負(fù)責(zé)在勘探和開發(fā)的權(quán)衡中提出新的測試點。
- 
    
“開發(fā)”力求在代用模型預(yù)測的目標(biāo)好的地方采樣。這就是利用已知的有希望的點。但是,如果我們已經(jīng)對某一區(qū)域進(jìn)行了足夠的探索,那么不斷地利用已知的信息就不會有什么收獲。
 - 
    
“探索”力求在不確定性較高的地點進(jìn)行采樣。這就確保了空間的任何主要區(qū)域都不會未被探索–全局最小值可能恰好就在那里。
 
一個鼓勵過多的開發(fā)和過少探索的獲取函數(shù)將導(dǎo)致模型只停留在它首先發(fā)現(xiàn)的最小值(通常是局部的–“只去有光的地方”)。一個鼓勵相反的獲取函數(shù)將不會首先停留在一個最小值,本地或全球。在微妙的平衡中產(chǎn)生良好的結(jié)果。acquisition 函數(shù),我們將其表示為a(x),必須同時考慮開發(fā)和探索。常見的獲取函數(shù)包括預(yù)期改進(jìn)和最大改進(jìn)概率,所有這些函數(shù)都是在給定先驗信息(高斯過程)的情況下,衡量特定投入在未來可能得到回報的概率。
讓我們把這些東西整合起來。貝葉斯優(yōu)化可以這樣進(jìn)行。
- 
    
初始化一個高斯過程 “代用函數(shù) “的先驗分布。
 - 
    
選擇幾個數(shù)據(jù)點x,使在當(dāng)前先驗分布上運(yùn)行的獲取函數(shù)a(x)最大化。
 - 
    
評估目標(biāo)成本函數(shù)c(x)中的數(shù)據(jù)點x,得到結(jié)果,y。
 - 
    
用新的數(shù)據(jù)更新高斯過程先驗分布,以產(chǎn)生一個后驗(它將成為下一步的先驗)。
 - 
    
重復(fù)步驟2-5進(jìn)行多次迭代。
 - 
    
解釋當(dāng)前的高斯過程分布(這是非常便宜的),以找到全局最小值。
 
貝葉斯優(yōu)化就是把概率論的思想放在代入優(yōu)化的思想后面。綜上所述:
- 
    
代用優(yōu)化利用代用函數(shù)或近似函數(shù)通過抽樣來估計目標(biāo)函數(shù)。
 - 
    
貝葉斯優(yōu)化將代用優(yōu)化置于概率框架中,將代用函數(shù)表示為概率分布,可以根據(jù)新的信息進(jìn)行更新。
 - 
    
獲取函數(shù)用于評估在當(dāng)前已知的先驗條件下,探索空間中某一點會產(chǎn)生 “好 “收益的概率,平衡探索與開發(fā)
 - 
    
主要在目標(biāo)函數(shù)評估成本很高的時候使用貝葉斯優(yōu)化,常用于超參數(shù)調(diào)整。
 
Hyperopt
Hyperopt是一個強(qiáng)大的Python庫,用于超參數(shù)優(yōu)化,由jamesbergstra開發(fā)。Hyperopt使用貝葉斯優(yōu)化的形式進(jìn)行參數(shù)調(diào)整,允許你為給定模型獲得最佳參數(shù)。它可以在大范圍內(nèi)優(yōu)化具有數(shù)百個參數(shù)的模型。
Hyperopt包含4個重要的特性
1、搜索空間
hyperopt有不同的函數(shù)來指定輸入?yún)?shù)的范圍,這些是隨機(jī)搜索空間。選擇最常用的搜索選項:
- 
    
choice(label, options)-這可用于分類參數(shù),它返回其中一個選項,它應(yīng)該是一個列表或元組。示例: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)-它返回一個介于low和high之間的值。示例:hp.uniform(“max_leaf_nodes”,1,10)
 
你可以使用的其他選項包括:
- 
    
normal(label, mu, sigma)-這將返回一個實際值,該值服從均值為mu和標(biāo)準(zhǔn)差為sigma的正態(tài)分布
 - 
    
qnormal(label, mu, sigma, q)-返回一個類似round(normal(mu, sigma) / q) * q的值
 - 
    
lognormal(label, mu, sigma)-返回exp(normal(mu, sigma))
 - 
    
qlognormal(label, mu, sigma, q) -返回一個類似round(exp(normal(mu, sigma)) / q) * q的值
 
2、目標(biāo)函數(shù)
這是一個最小化函數(shù),它從搜索空間接收超參數(shù)值作為輸入并返回?fù)p失。這意味著在優(yōu)化過程中,我們使用選定的超參數(shù)值訓(xùn)練模型并預(yù)測目標(biāo)特征,然后評估預(yù)測誤差并將其返回給優(yōu)化器。優(yōu)化器將決定要檢查哪些值并再次迭代。你將在一個實際例子中學(xué)習(xí)如何創(chuàng)建一個目標(biāo)函數(shù)。
3、fmin
- 
    
fmin函數(shù)是對不同的算法集及其超參數(shù)進(jìn)行迭代,然后使目標(biāo)函數(shù)最小化的優(yōu)化函數(shù)。fmin有5個輸入是:
 - 
    
最小化的目標(biāo)函數(shù)
 - 
    
定義的搜索空間
 - 
    
使用的搜索算法有隨機(jī)搜索、TPE(Tree-Parzen估計器)和自適應(yīng)TPE。注意:rand.suggest以及hyperopt.tpe.suggest為超參數(shù)空間的順序搜索提供邏輯。
 - 
    
最大評估數(shù)
 - 
    
trials對象(可選)
 
4、試驗對象
Trials對象用于保存所有超參數(shù)、損失和其他信息,這意味著你可以在運(yùn)行優(yōu)化后訪問它們。此外,trials 可以幫助你保存和加載重要信息,然后繼續(xù)優(yōu)化過程。
Hyperopt的使用
在理解了Hyperopt的重要特性之后,下面將介紹Hyperopt的使用方法。
- 
    
初始化要搜索的空間
 - 
    
定義目標(biāo)函數(shù)
 - 
    
選擇要使用的搜索算法
 - 
    
運(yùn)行hyperopt函數(shù)
 - 
    
分析測試對象中存儲的評估輸出
 
- 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ù)號
 - # 實例化Trial 對象,對模型進(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個機(jī)器學(xué)習(xí)模型。然后,我們可以計算每個模型的準(zhǔn)確性,并決定只保留一半模型(性能最好的模型)?,F(xiàn)在,我們可以生成具有與最佳模型相似的超參數(shù)的后代,以便再次獲得N個模型的種群。在這一點上,我們可以再次計算每個模型的準(zhǔn)確性,并在定義的世代中重復(fù)該循環(huán)。這樣,只有最佳模型才能在流程結(jié)束時生存下來。
TPOT是一種基于遺傳算法優(yōu)化機(jī)器學(xué)習(xí)管道(pipeline)的Python自動機(jī)器學(xué)習(xí)工具。簡單來說,就是TPOT可以智能地探索數(shù)千個可能的pipeline,為數(shù)據(jù)集找到最好的pipeline,從而實現(xiàn)機(jī)器學(xué)習(xí)中最乏味的部分。

更重要地是,一旦TPOT完成搜索,TPOT同時也提供了Python代碼。通過這個代碼,我們可以具體地知道TPOT獲得最優(yōu)性能時的具體pipeline的內(nèi)容,這對于后續(xù)修改是十分方便的!

TPOT是在sklearn的基礎(chǔ)之上做的封裝庫。其主要封裝了sklearn的模型相關(guān)模塊、processesing模塊和feature_selection模塊,所以TPOT的主要功能是集中在使用pipeline的方式完成模型的數(shù)據(jù)預(yù)處理、特征選擇和模型選擇方面。此外,我們還發(fā)現(xiàn)了TPOT已經(jīng)對xgboost進(jìn)行了支持。
雖然TPOT使用遺傳算法代替了傳統(tǒng)的網(wǎng)格搜索進(jìn)行超參數(shù)選擇,但由于默認(rèn)初始值的隨機(jī)性,在少量的進(jìn)化(迭代)次數(shù)下,TPOT最終選擇的模型往往并不相同。
計算效率問題。作者在代碼中寫道:進(jìn)化(迭代)次數(shù)和每一代保留的個體數(shù)量值越多,最終得模型得分會越高。但這同樣也會導(dǎo)致耗時很長。如果使用相當(dāng)復(fù)雜的數(shù)據(jù)集或運(yùn)行TPOT短時間,不同的TPOT運(yùn)行可能會導(dǎo)致不同的流水線推薦。TPOT的優(yōu)化算法本質(zhì)上是隨機(jī)的,這意味著它使用隨機(jī)性(部分地)來搜索可能的流水線空間。當(dāng)兩個TPOT運(yùn)行推薦不同的管道時,這意味著TPOT運(yùn)行由于時間不夠而不收斂,或者多個管道在數(shù)據(jù)集上執(zhí)行的次數(shù)大致相同。這實際上是一個優(yōu)于固定網(wǎng)格搜索技術(shù)的優(yōu)點:TPOT是一個助手,它通過探索您可能從未考慮過的流水線配置來提供解決如何解決特定機(jī)器學(xué)習(xí)問題的想法,然后將微調(diào)留給更受約束的參數(shù)調(diào)整技術(shù),例如網(wǎng)格搜索。
使用TPOT(版本0.9.5)開發(fā)模型需要把握以下幾點:
- 
    
在使用TPOT進(jìn)行建模前需要對數(shù)據(jù)進(jìn)行必要的清洗和特征工程操作。
 - 
    
TPOT目前只能做有監(jiān)督學(xué)習(xí)。
 - 
    
TPOT目前支持的分類器主要有貝葉斯、決策樹、集成樹、SVM、KNN、線性模型、xgboost。
 - 
    
TPOT目前支持的回歸器主要有決策樹、集成樹、線性模型、xgboost。
 - 
    
TPOT會對輸入的數(shù)據(jù)做進(jìn)一步處理操作,例如二值化、聚類、降維、標(biāo)準(zhǔn)化、正則化、獨熱編碼操作等。
 - 
    
根據(jù)模型效果,TPOT會對輸入特征做特征選擇操作,包括基于樹模型、基于方差、基于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)建子代(新個體)的迭代次數(shù)
 - 
    
population_size – 創(chuàng)建個體的初始數(shù)量(這些用于創(chuàng)建后代)
 - 
    
offspring_size – 每一代所需創(chuàng)造的新個體數(shù)
 - 
    
mutation_rate – 出現(xiàn)屬性值隨機(jī)更改的概率(包括新參數(shù)的方法,在初始群體中可能不可用)
 - 
    
crossover_rate –用于創(chuàng)造后代的個體所占的百分比
 
使用這個迭代過程,我們選出最佳配置。準(zhǔn)備遺傳算法的結(jié)果一般取決于初始狀態(tài)。因此,它隨機(jī)產(chǎn)生的初始種群影響輸出,重新運(yùn)行相同的設(shè)置可能會輸出不同的結(jié)果。















 
 
 














 
 
 
 