機器學習——超參數搜索

基礎概念

超參數是在開始學習過程之前設置值的參數,而不是通過訓練得到的參數數據。通常情況下,在機器學習過程中需要對超參數進行優化,給學習器選擇一組最優超參數,以提高學習的性能和效果。比如,樹的數量或樹的深度,學習率(多種模式)以及k均值聚類中的簇數等都是超參數。

與超參數區別的概念是參數,它是模型訓練過程中學習到的一部分,比如迴歸係數,神經網絡權重等。簡單的描述參數是模型訓練獲得的,超參數是人工配置參數(本質上是參數的參數,每次改變超參數,模型都要重新訓練)。

超參數調優

在模型訓練過程中的參數最優化,一般都是對參數的可能值進行有效搜索,然後用評價函數選取出最優參數,比如梯度下降法。

同理,人工的超參數選擇過程,我們也可以採取類似參數搜索的辦法,來提高效率,如果進行人工試錯的方式,會非常浪費時間。

超參數搜索過程:
•將數據集分爲訓練集,驗證集及測試集。
•選擇模型性能評價指標
•用訓練集對模型進行訓練
•在驗證集上對模型進行參數進行搜索,用性能指標評價參數好壞
•選出最優參數

常見超參數搜索算法:
•網格搜索
•隨機搜索
•啓發式搜索

網格搜索

網格搜索是在所有候選的參數選擇中,通過循環遍歷,嘗試每一種可能性,表現最好的參數就是最終的結果(暴力搜索)。

原理:在一定的區間內,通過循環遍歷,嘗試每一種可能性,並計算其約束函數和目標函數的值,對滿足約束條件的點,逐個比較其目標函數的值,將壞的點拋棄,保留好的點,最後便得到最優解的近似解。

爲了評價每次選出的參數的好壞,我們需要選擇評價指標,評價指標可以根據自己的需要選擇accuracy、f1-score、f-beta、percision、recall等。

同時,爲了避免初始數據的劃分對結果的影響,我們需要採用交叉驗證的方式來減少偶然性,一般情況下網格搜索需要和交叉驗證相結合使用。

python的sklearn包中網格搜索函數GridSearchCV:
GridSearchCV(
estimator,param_grid, scoring=None, fit_params=None, n_jobs=1, iid=True,
refit=True,cv=None, verbose=0, pre_dispatch='2*n_jobs',
error_score='raise',return_train_score=True) •estimator:所使用的分類器
•param_grid:值爲字典或者列表,需要最優化的參數的取值範圍,如paramters = {'n_estimators':range(10,100,10)}。
•scoring :準確度評價指標,默認None,這時需要使用score函數;或者如scoring='roc_auc'。
•fit_params:字典類型數據,主要用於給fit方法傳遞參數。
•n_jobs: 並行數,int:個數,-1:跟CPU核數一致, 1:默認值。
•pre_dispatch:指定總共分發的並行任務數。當n_jobs大於1時,數據將在每個運行點進行復制,這可能導致OOM,而設置pre_dispatch參數,則可以預先劃分總共的job數量,使數據最多被複制pre_dispatch次。
•iid:默認True,爲True時,默認爲各個樣本fold概率分佈一致,誤差估計爲所有樣本之和,而非各個fold的平均。
•cv :交叉驗證參數,默認None,使用三折交叉驗證。指定fold數量,默認爲3,也可以是yield訓練/測試數據的生成器。
•refit :默認爲True,程序將會以交叉驗證訓練集得到的最佳參數,重新對所有可用的訓練集與驗證集進行訓練,作爲最終用於性能評估的最佳模型參數。即在搜索參數結束後,用最佳參數結果再次fit一遍全部數據集。
•verbose:日誌冗長度,int:冗長度,0:不輸出訓練過程,1:偶爾輸出,>1:對每個子模型都輸出。
•error_score: 默認爲raise,可選擇參數numeric,在模型擬合過程中如果產生誤差,在raise情況下,誤差分數將會提高,如果選擇numeric,則fitfailedwarning會提高。
•return_train_score:布爾類型數據,默認爲Ture ,爲False時交叉驗證的結果不包含訓練得分。

網格搜索python簡單實現
import pandas as pd
from sklearn import datasets
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import classification_report
from xgboost.sklearn import XGBClassifier

iris = datasets.load_iris()
parameters = {'n_estimators':range(100,150,10),'max_depth':range(3,5,1)}
xgc=XGBClassifier()
clf = GridSearchCV(xgc, parameters)
clf.fit(iris.data, iris.target)
cv_result = pd.DataFrame.from_dict(clf.cvresults)

best_param=clf.bestparams
best_score=clf.bestscore

y_pred = clf.predict(iris.data)
print(classification_report(y_true=iris.target, y_pred=y_pred))

隨機搜索

隨機搜索(random search)是利用隨機數去求函數近似的最優解的方法,區別於網格搜索的暴力搜索方式。

原理:在一定的區間內,不斷隨機地而不是有傾向性產生隨機點,並計算其約束函數和目標函數的值,對滿足約束條件的點,逐個比較其目標函數的值,將壞的點拋棄,保留好的點,最後便得到最優解的近似解。

這種方法是建立在概率論的基礎上,所取隨機點越多,則得到最優解的概率也就越大。這種方法存在精度較差的問題,找到近似最優解的效率高於網格搜索。隨機搜索一般用於粗選或普查。

python的sklearn包中隨機搜索函數RandomizedSearchCV:
RandomizedSearchCV(estimator, param_distributions, n_iter=10, scoring=None,
fit_params=None, n_jobs=1, iid=True, refit=True, cv=None, verbose=0,
pre_dispatch=‘2*n_jobs’, random_state=None, error_score=’raise’) •estimator:所使用的分類器
•param_distributions:值爲字典或者列表,需要最優化的參數的取值範圍,同時需要選擇一種rvs方法來進行抽樣,比如scipy.stats.distributions
•n_iter : 抽樣參數,默認爲10,具體的值選擇需要根據模型的相應效果進行評估。
•scoring :準確度評價指標,默認None,這時需要使用score函數;或者如scoring='roc_auc'。
•fit_params:字典類型數據,主要用於給fit方法傳遞參數。
•n_jobs: 並行數,int:個數,-1:跟CPU核數一致, 1:默認值。
•pre_dispatch:指定總共分發的並行任務數。當n_jobs大於1時,數據將在每個運行點進行復制,這可能導致OOM,而設置pre_dispatch參數,則可以預先劃分總共的job數量,使數據最多被複制pre_dispatch次。
•iid:默認True,爲True時,默認爲各個樣本fold概率分佈一致,誤差估計爲所有樣本之和,而非各個fold的平均。
•cv :交叉驗證參數,默認None,使用三折交叉驗證。指定fold數量,默認爲3,也可以是yield訓練/測試數據的生成器。
•refit :默認爲True,程序將會以交叉驗證訓練集得到的最佳參數,重新對所有可用的訓練集與驗證集進行訓練,作爲最終用於性能評估的最佳模型參數。即在搜索參數結束後,用最佳參數結果再次fit一遍全部數據集。
•verbose:日誌冗長度,int:冗長度,0:不輸出訓練過程,1:偶爾輸出,>1:對每個子模型都輸出。
•random_state:隨機種子,默認爲None,int類型或者隨機狀態實例,僞隨機數生成器狀態用於從可能的值列表而不是scipy中隨機抽樣。統計分佈。如果int,隨機狀態是隨機數生成器所使用的種子;如果隨機狀態實例,隨機狀態是隨機數生成器;如果沒有,隨機數生成器是np.random所使用的隨機狀態實例。
•error_score: 默認爲raise,可選擇參數numeric,在模型擬合過程中如果產生誤差,在raise情況下,誤差分數將會提高,如果選擇numeric,則fitfailedwarning會提高。

隨機搜索python簡單實現
import pandas as pd
from sklearn import datasets
from sklearn.model_selection import GridSearchCV,RandomizedSearchCV
from sklearn.metrics import classification_report
from xgboost.sklearn import XGBClassifier

iris = datasets.load_iris()
parameters = {'n_estimators':range(100,150,10),'max_depth':range(3,5,1)}
xgc=XGBClassifier()
clf = RandomizedSearchCV(xgc, parameters,cv=5)
clf.fit(iris.data, iris.target)
cv_result = pd.DataFrame.from_dict(clf.cvresults)

best_param=clf.bestparams
best_score=clf.bestscore

y_pred = clf.predict(iris.data)
print(classification_report(y_true=iris.target, y_pred=y_pred))

啓發式搜索

啓發式搜索(Heuristically Search)又稱爲有信息搜索(Informed Search),它是利用問題擁有的啓發信息來引導搜索,達到減少搜索範圍、降低問題複雜度的目的,這種利用啓發信息的搜索過程稱爲啓發式搜索。

原理:在狀態空間中的搜索對每一個搜索的位置進行評估,得到最好的位置,再從這個位置進行搜索直到目標。這樣可以省略大量無謂的搜索路徑,提高了效率。在啓發式搜索中,對位置的估價是十分重要的。採用了不同的估價可以有不同的效果。

啓發式搜索有模擬退火算法(SA)、遺傳算法(GA)、列表搜索算法(ST)、進化規劃(EP)、進化策略(ES)、蟻羣算法(ACA)、人工神經網絡(ANN)...等。

啓發式搜索非常多樣化,而且在sklearn包中並沒有現成的函數,如果有需要我們可以針對某一種啓發式算法的實現過程進行了解,然後用python手動實現。

這裏我們着手對遺傳算法的實現過程做些瞭解。

遺傳算法

遺傳算法(Genetic Algorithm)是一種通過模擬自然進化過程搜索最優解的方法,它的思想來自於進化論,生物種羣具有自我進化的能力,能夠不斷適應環境,優勢劣汰之後得到最優的種羣個體。進化的行爲主要有選擇,遺傳,變異,遺傳算法希望能夠通過將初始解空間進化到一個較好的解空間。

原理:遺傳算法是從代表問題可能潛在的解集的一個種羣(population)開始的,而一個種羣則由經過基因(gene)編碼的一定數目的個體(individual)組成。每個個體實際上是染色體(chromosome)帶有特徵的實體。染色體作爲遺傳物質的主要載體,即多個基因的集合,其內部表現(即基因型)是某種基因組合,它決定了個體的形狀的外部表現,如黑頭髮的特徵是由染色體中控制這一特徵的某種基因組合決定的。因此,在一開始需要實現從表現型到基因型的映射即編碼工作。由於仿照基因編碼的工作很複雜,我們往往進行簡化,如二進制編碼,初代種羣產生之後,按照適者生存和優勝劣汰的原理,逐代(generation)演化產生出越來越好的近似解,在每一代,根據問題域中個體的適應度(fitness)大小選擇(selection)個體,並藉助於自然遺傳學的遺傳算子(genetic operators)進行組合交叉(crossover)和變異(mutation),產生出代表新的解集的種羣。這個過程將導致種羣像自然進化一樣的後生代種羣比前代更加適應於環境,末代種羣中的最優個體經過解碼(decoding),可以作爲問題近似最優解。

遺傳算法的實現步驟:
•初始化候選參數集,並編碼爲基因序列(初始化種羣,一組參數編碼爲一個種羣個體,共n個種羣個體 ),即對參數進行編碼,同時設定進化代數m。
•個體評估,計算各個種羣個體的適應度(適應度描述了該個體對自然環境的適應能力,表徵了其個體存活能力和生殖機會),用適應度函數表示。
•選擇運算,選擇是模擬自然選擇,把優秀的個體選擇出來(基於適應度),以進行後續的遺傳和變異。
•交叉運算,交叉是模擬繁殖後代的基因重組。
•變異運算,變異是模擬基因突變。
•經過選擇,交叉,變異,生產下一代羣體,重複此過程,直到停止條件。

從上面的實現步驟可以知道,遺傳算法包含以下幾個主要部分:
•基因編碼
•適應度函數
•遺傳算子,包含選擇,交叉,變異

有了基本遺傳算法的實現過程,後續就是對每個算法實現過程的細節尋找合適的方法進行處理。換到機器學習參數最優化的問題上,就是使用遺傳算法搜索參數空間獲得最優的模型性能評價指標的過程。

啓發式搜索先到這裏,後續有時間可以嘗試python代碼實現參數最優化的過程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章