超参数的调优(lightgbm)
參考
 原文
 Automated Hyperparameter Optimization
超參數(shù)的優(yōu)化過(guò)程:通過(guò)自動(dòng)化
 目的:使用帶有策略的啟發(fā)式搜索(informed search)在更短的時(shí)間內(nèi)找到最優(yōu)超參數(shù),除了初始設(shè)置之外,并不需要額外的手動(dòng)操作。
實(shí)踐部分
貝葉斯優(yōu)化問(wèn)題有四個(gè)組成部分:
目標(biāo)函數(shù):我們想要最小化的對(duì)象,這里指帶超參數(shù)的機(jī)器學(xué)習(xí)模型的驗(yàn)證誤差
域空間:待搜索的超參數(shù)值
優(yōu)化算法:構(gòu)造代理模型和選擇接下來(lái)要評(píng)估的超參數(shù)值的方法
結(jié)果的歷史數(shù)據(jù):存儲(chǔ)下來(lái)的目標(biāo)函數(shù)評(píng)估結(jié)果,包含超參數(shù)和驗(yàn)證損失
通過(guò)以上四個(gè)步驟,我們可以對(duì)任意實(shí)值函數(shù)進(jìn)行優(yōu)化(找到最小值)。這是一個(gè)強(qiáng)大的抽象過(guò)程,除了機(jī)器學(xué)習(xí)超參數(shù)的調(diào)優(yōu),它還能幫我們解決其他許多問(wèn)題。
代碼示例
數(shù)據(jù)集:https://www.jiqizhixin.com/articles/2018-08-08-2
 目標(biāo):預(yù)測(cè)客戶(hù)是否會(huì)購(gòu)買(mǎi)一份保險(xiǎn)產(chǎn)品
 監(jiān)督分類(lèi)問(wèn)題
 觀測(cè)值:5800
 測(cè)試點(diǎn):4000
 不平衡的分類(lèi)問(wèn)題,本文使用的評(píng)價(jià)性能的指標(biāo)是受試者工作特征曲線(xiàn)下的面積(ROC AUC),ROC AUC 的值越高越好,其值為 1 代表模型是完美的。
什么是不平衡的分類(lèi)問(wèn)題?
 如何處理數(shù)據(jù)中的「類(lèi)別不平衡」?
 極端類(lèi)別不平衡數(shù)據(jù)下的分類(lèi)問(wèn)題S01:困難與挑戰(zhàn)
hyperropt1125.py
- 導(dǎo)入庫(kù)
import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns import lightgbm as lgb from sklearn.model_selection import KFoldMAX_EVALIS = 500 N_FLODS = 10觀察數(shù)據(jù),數(shù)據(jù)集已經(jīng)用ORIGIN把數(shù)據(jù)自動(dòng)分為train和test集。
print(data.ORIGIN.value_counts())train 5822 test 4000 Name: ORIGIN, dtype: int64復(fù)習(xí)一下,隨意畫(huà)個(gè)圖
sns.countplot(x='ORIGIN',data=data) plt.show()
 CARAVAN: target
- 處理數(shù)據(jù)集
一定要細(xì)心啊,不然BUG真的莫名其妙。
#導(dǎo)入后先劃分訓(xùn)練集和測(cè)試集 train = data[data['ORIGIN'] == 'train'] test = data[data['ORIGIN'] == 'test']#抽取標(biāo)簽 train_labels = np.array(train['CARAVAN'].astype(np.int32)).reshape((-1,)) test_labels = np.array(test['CARAVAN'].astype(np.int32)).reshape((-1,))去掉標(biāo)簽們,留下特征 train = train.drop(columns = ['ORIGIN','CARAVAN']) test = test.drop(columns = ['ORIGIN','CARAVAN'])features = np.array(train) test_features = np.array(test) labels = train_labels[:]print('Train shape: {}'.format(train.shape)) print("Test shape :{}".format(test.shape)) train.head()#運(yùn)行結(jié)果 Train shape: (5822, 85) Test shape :(4000, 85)Python中reshape函數(shù)參數(shù)-1的意思
 不分行列,改成1串
- 標(biāo)簽分布
plt.hist(labels, edgecolor = 'k') plt.xlabel('Label') plt.ylabel('Count') plt.title('Counts of Labels')plt.show()hist函數(shù)1
 可以看出,這是個(gè)不平衡的分類(lèi)問(wèn)題。
 因此,選用梯度提升模型,驗(yàn)證方法采用ROC AUC。(具體見(jiàn)原文了)
 本文采用的是LightGBM。
-模型與其默認(rèn)值
from lightgbm import LGBMClassifier model = LGBMClassifier()#Model with default hyperparameters print(model)LGBMClassifier(boosting_type='gbdt', class_weight=None, colsample_bytree=1.0,importance_type='split', learning_rate=0.1, max_depth=-1,min_child_samples=20, min_child_weight=0.001, min_split_gain=0.0,n_estimators=100, n_jobs=-1, num_leaves=31, objective=None,random_state=None, reg_alpha=0.0, reg_lambda=0.0, silent=True,subsample=1.0, subsample_for_bin=200000, subsample_freq=0)將模型與訓(xùn)練集擬合,采用roc_auc驗(yàn)證。
from sklearn.metrics import roc_auc_score from timeit import default_timer as timerstart = timer() model.fit(features,labels) train_time = timer() - startpredictions = model.predict_proba(test_features)[:,1] auc = roc_auc_score(test_labels,predictions)print('The baseline score on the test set is {:.4f}.'.format(auc)) print('The baseline training time is {:.4f} seconds'.format(train_time))#results The baseline score on the test set is 0.7092. The baseline training time is 0.1888 secondsDue to the small size of the dataset (less than 6000 observations), hyperparameter tuning will have a modest but noticeable effect on the performance (a better investment of time might be to gather more data!)
python中計(jì)時(shí)工具timeit模塊的基本用法
 測(cè)試代碼運(yùn)行時(shí)間
Random Search
import random隨機(jī)搜索也有四個(gè)部分:
Domain: values over which to search
 Optimization algorithm: pick the next values at random! (yes this qualifies as an algorithm)
 Objective function to minimize: in this case our metric is cross validation ROC AUC
 Results history that tracks the hyperparameters tried and the cross validation metric
讓我們來(lái)康康哪些參數(shù)要Tuning
- Domain for Random Search
Random search and Bayesian optimization 都是從domain搜索hyperparameters,對(duì)于random (or grid search),這種domain被稱(chēng)為hyperparameter grid,并且對(duì)hyperparameter使用離散值。
print(LGBMClassifier())#Results LGBMClassifier(boosting_type='gbdt', class_weight=None, colsample_bytree=1.0,importance_type='split', learning_rate=0.1, max_depth=-1,min_child_samples=20, min_child_weight=0.001, min_split_gain=0.0,n_estimators=100, n_jobs=-1, num_leaves=31, objective=None,random_state=None, reg_alpha=0.0, reg_lambda=0.0, silent=True,subsample=1.0, subsample_for_bin=200000, subsample_freq=0)基于默認(rèn)值,以下可構(gòu)建hyperparameter grid。在此之前選值怎么工作得更好并不好說(shuō),因此對(duì)于大部分參數(shù)我們均采用默認(rèn)值或以默認(rèn)值為中心上下浮動(dòng)的值。
 **注意:**subsample_dist是subsample的參數(shù),但boosting_type=goss不支持隨機(jī)的 subsampling。
 假如boosting_type選擇其他值,那么這個(gè)subsample_dist可以放到param_grid里讓我們隨機(jī)搜索。
讓我們來(lái)康康 learning_rate 和 the num_leaves的分布,學(xué)習(xí)率是典型的對(duì)數(shù)分布,參見(jiàn)Quora這篇Why does one sample the log-space when searching for good Hyper Parameters for Machine Learning
because it can vary over several orders of magnitude
因此,可以采用np.logspace 搜索。
np.logspace returns values evenly spaced over a log-scale (so if we take the log of the resulting values, the distribution will be uniform
plt.hist(param_grid['learning_rate'],color='g',edgecolor = 'k') plt.xlabel('Learning Rate', size = 14) plt.ylabel('Count', size = 14) plt.title('Learning Rate Distribution', size = 18) plt.show()
 在0,005與0.2之間的值較多。建議在這個(gè)范圍里選值。
再來(lái)看看num_leaves的表現(xiàn)
plt.hist(param_grid['num_leaves'], color = 'b', edgecolor = 'k') plt.xlabel('Learning Number of Leaves', size = 14) plt.ylabel('Count', size = 14) plt.title('Number of Leaves Distribution', size = 18) plt.show()
 沒(méi)什么波動(dòng)。
 
-Sampling from Hyperparameter Domain
查看我們采樣的結(jié)果:
params = {key:random.sample(value,1)[0] for key,value in param_grid.items()} print(params)#運(yùn)行結(jié)果 {'class_weight': 'balanced', 'boosting_type': 'gbdt', 'num_leaves': 49, 'learning_rate': 0.006450936939768325, 'subsample_for_bin': 140000, 'min_child_samples': 145, 'reg_alpha': 0.16326530612244897, 'reg_lambda': 0.9387755102040816, 'colsample_bytree': 0.6444444444444444}其他:
 生成隨機(jī)系數(shù)
python 字典操作提取key,value
#!/usr/bin/env python3 # -*- coding: utf-8 -*-dict_ori = {'A':1, 'B':2, 'C':3} dict_new = {key:value for key,value in dict_ori.items()} print(dict_new)注意這句
 ‘boosting_type’: [‘gbdt’, ‘goss’, ‘dart’],
 在 boosting_type 選擇非 goss類(lèi)型時(shí),對(duì)subsample也能采取隨機(jī)采樣。
-Cross Validation with Early Stopping in LightGBM
使用LightGBM的cross validation function,采用100 early stopping rounds。
 建立數(shù)據(jù)集,懶得改了,但是我的習(xí)慣是,features用X_train表達(dá),labels用y_train = labels表達(dá)
詳解numpy的argmax
 找出最大值的索引。即最好迭代步
之前的方法
print('best n_estimator is {}'.format(len(cv_results['auc-mean']))) print('best cv score is {}'.format(pd.Series(cv_results['auc-mean']).max()))#運(yùn)行結(jié)果 best n_estimator is 7 best cv score is 0.7568251976593624-Results Dataframe
從前面的運(yùn)算,我們已經(jīng)獲取了:
- domain
- algorithm(還記得嗎?選值的)
 另外還需要
 Objective function to minimize: in this case our metric is cross validation ROC AUC
 Results history that tracks the hyperparameters tried and the cross validation metric
Tracking the results 將通過(guò)一個(gè)dataframe完成,每行對(duì)目標(biāo)函數(shù)進(jìn)行評(píng)估。
random_results = pd.DataFrame(columns=['loss','params','iteration','estimator','time'],index=list(range(MAX_EVALIS)))#index行標(biāo)簽-目標(biāo)函數(shù)
我們?cè)噲D最小化目標(biāo)函數(shù)。其輸入為一組值——在本例中為 GBM 的超參數(shù),輸出為需要最小化的實(shí)值——交叉驗(yàn)證損失。Hyperopt
 將目標(biāo)函數(shù)作為黑盒處理,因?yàn)檫@個(gè)庫(kù)只關(guān)心輸入和輸出是什么。為了找到使損失最小的輸入值,該算法不需要知道目標(biāo)函數(shù)的內(nèi)部細(xì)節(jié)!
與從訓(xùn)練數(shù)據(jù)中提取驗(yàn)證集(從而限制我們擁有的訓(xùn)練數(shù)據(jù)的數(shù)量)相比,更好的方法是KFold交叉驗(yàn)證。
對(duì)于此示例,我們將使用10倍交叉驗(yàn)證,這意味著測(cè)試和訓(xùn)練每組模型超參數(shù)10次,每次使用不同的訓(xùn)練數(shù)據(jù)子集作為驗(yàn)證集。
在隨機(jī)搜索的情況下,下一個(gè)選擇的值不是基于過(guò)去的評(píng)估結(jié)果,但顯然仍應(yīng)對(duì)運(yùn)算保持跟蹤,以便我們知道哪個(gè)值最有效。 這也將使我們能夠?qū)㈦S機(jī)搜索與明智的貝葉斯優(yōu)化進(jìn)行對(duì)比。
-Random Search Implementation隨機(jī)搜索的實(shí)現(xiàn)
目的:寫(xiě)一個(gè)循環(huán)遍歷評(píng)估次數(shù),每次選擇一組不同的超參數(shù)進(jìn)行評(píng)估。
 每次運(yùn)行該函數(shù),結(jié)果都會(huì)保存到dataframe中。
關(guān)于亂序(shuffle)與隨機(jī)采樣(sample)的一點(diǎn)探究
random.seed(50) #用前面設(shè)置好的值來(lái)作為遍歷的次數(shù): for i in range(MAX_EVALIS):params = {key:random.sample(value,1)[0] for key,value in param_grid.items() }#隨機(jī)取樣gbm的參數(shù)print(params)if params['boosting_type'] == 'goss':params['subsample'] = 1.0else:params['subsample'] = random.sample(subsample_dist,1)[0]results_list = random_objective(params,i)#將結(jié)果添加到數(shù)據(jù)下一行random_results.loc[i, :] = results_list#對(duì)分析結(jié)果進(jìn)行排序 random_results.sort_values('loss',ascending=True,inplace=True) random_results.reset_index(inplace=True,drop=True) print(random_results.head())Pandas Series.reset_index()
 語(yǔ)法:
500次實(shí)在太慢了,估計(jì)能找到明天,所以用原文里運(yùn)行的結(jié)果吧。
 
-Random Search Performance
根據(jù)運(yùn)算結(jié)果選擇參數(shù),用測(cè)試集評(píng)估它們。
 選擇最好表現(xiàn)的一組。
 因?yàn)殡娔X實(shí)在太慢,以下都是抄的我自己沒(méi)跑……
用隨機(jī)搜索的參數(shù)訓(xùn)練模型并進(jìn)行評(píng)估
# Find the best parameters and number of estimators best_random_params = random_results.loc[0, 'params'].copy() best_random_estimators = int(random_results.loc[0, 'estimators']) best_random_model = lgb.LGBMClassifier(n_estimators=best_random_estimators, n_jobs = -1, objective = 'binary', **best_random_params, random_state = 50)# Fit on the training data best_random_model.fit(features, labels)# Make test predictions predictions = best_random_model.predict_proba(test_features)[:, 1]print('The best model from random search scores {:.4f} on the test data.'.format(roc_auc_score(test_labels, predictions))) print('This was achieved using {} search iterations.'.format(random_results.loc[0, 'iteration']))結(jié)果
The best model from random search scores 0.7232 on the test data. This was achieved using 146 search iterations.開(kāi)始貝葉斯調(diào)優(yōu)
1.目標(biāo)函數(shù)
 我們?cè)噲D最小化目標(biāo)函數(shù)。其輸入為一組值——在本例中為 GBM 的超參數(shù),輸出為需要最小化的實(shí)值——交叉驗(yàn)證損失。Hyperopt 將目標(biāo)函數(shù)作為黑盒處理,因?yàn)檫@個(gè)庫(kù)只關(guān)心輸入和輸出是什么。為了找到使損失最小的輸入值,該算法不需要知道目標(biāo)函數(shù)的內(nèi)部細(xì)節(jié)!從一個(gè)高度抽象的層次上說(shuō)(以偽代碼的形式),我們的目標(biāo)函數(shù)可以表示為:
核心的代碼為「cv_results = lgb.cv(…)」。為了實(shí)現(xiàn)帶早停止的交叉驗(yàn)證,我們使用了 LightGBM 的函數(shù)「cv」,向該函數(shù)傳入的參數(shù)包含超參數(shù)、一個(gè)訓(xùn)練集、交叉驗(yàn)證中使用的許多折,以及一些其它的參數(shù)。我們將評(píng)估器的數(shù)量(num_boost_round)設(shè)置為 10000,但是由于我們使用了「early_stopping_rounds」,當(dāng) 100 個(gè)評(píng)估器的驗(yàn)證得分沒(méi)有提高時(shí)訓(xùn)練會(huì)被停止,所以實(shí)際上使用的評(píng)估器不會(huì)達(dá)到這個(gè)數(shù)量。早停止是一種有效的選擇評(píng)估器數(shù)量的方法,而不是將其設(shè)置為另一個(gè)需要調(diào)優(yōu)的超參數(shù)!
當(dāng)交叉驗(yàn)證完成后,我們將得到最高得分(ROC AUC)。之后,由于我們想要得到的是最小值,我們將采用「1-最高得分」。該值將在返回的字典數(shù)據(jù)結(jié)構(gòu)中作為「loss」關(guān)鍵字返回。
這個(gè)目標(biāo)函數(shù)實(shí)際上比它所需的結(jié)構(gòu)復(fù)雜一些,因?yàn)槲覀儗⒎祷匾粋€(gè)值的字典。對(duì)于 Hyperopt 中的目標(biāo)函數(shù),我們可以返回一個(gè)單一的值(即損失),或者返回一個(gè)帶有最小值的關(guān)鍵字「loss」和「status」的字典。返回超參數(shù)的值使我們能夠查看每組超參數(shù)得到的損失。
 2.域空間(domain)
 域空間表示我們想要對(duì)每個(gè)超參數(shù)進(jìn)行評(píng)估的值的范圍。在每一輪搜索迭代中,貝葉斯優(yōu)化算法將從域空間中為每個(gè)超參數(shù)選定一個(gè)值。當(dāng)我們進(jìn)行隨機(jī)搜索或網(wǎng)格搜索時(shí),域空間就是一個(gè)網(wǎng)格。貝葉斯優(yōu)化中也是如此,只是這個(gè)域空間對(duì)每個(gè)超參數(shù)來(lái)說(shuō)是一個(gè)概率分布而不是離散的值。
然而,在貝葉斯優(yōu)化問(wèn)題中,確定域空間是最難的部分。如果有機(jī)器學(xué)習(xí)方法的相關(guān)經(jīng)驗(yàn),我們可以將更大的概率賦予我們認(rèn)為最佳值可能存在的點(diǎn),以此來(lái)啟發(fā)對(duì)超參數(shù)分布的選擇。但是,不同的數(shù)據(jù)集之間的最佳模型設(shè)定是不同的,并且具有高維度的問(wèn)題(大量的超參數(shù)),這會(huì)使我們很難弄清超參數(shù)之間的相互作用。在不確定最佳值的情況下,我們可以使用更大范圍的概率分布,通過(guò)貝葉斯算法進(jìn)行推理。
lgb的超參數(shù)的值上面寫(xiě)過(guò)了這里就不再弄。
 雖然我也不想用機(jī)翻,但為了不浪費(fèi)時(shí)間就好好用我的復(fù)制粘貼大法了:
我不確定世界上是否真有人知道所有的這些超參數(shù)是如何相互作用的!而其中有一些超參數(shù)是不需要調(diào)優(yōu)(如「objective」和「random_state」)。我們將使用早停止方法找到最佳的評(píng)估器數(shù)量「n_estimators」。盡管如此,我們?nèi)匀恍枰獌?yōu)化 10 個(gè)超參數(shù)!當(dāng)我們第一次對(duì)一個(gè)模型進(jìn)行調(diào)優(yōu)時(shí),我通常創(chuàng)建一個(gè)以缺省值為中心的大范圍域空間,然后在接下來(lái)的搜索中對(duì)其進(jìn)行優(yōu)化。
舉個(gè)例子,我們不妨在 Hyperopt 中定義一個(gè)簡(jiǎn)單的域——一個(gè)離散均勻分布,其中離散點(diǎn)的數(shù)量為 GBM 中每棵決策樹(shù)的葉子結(jié)點(diǎn)數(shù):
from hyperopt import hp from hyperopt.pyll.stochastic import sample # Discrete uniform distribution num_leaves = {'num_leaves': hp.quniform('num_leaves', 30, 150, 1)} num_leaves_dist = []for _ in range(10000):num_leaves_dist.append(sample(num_leaves)['num_leaves'])plt.figure(figsize=(8,6)) sns.kdeplot(num_leaves_dist,linewidth=2,shade=True) plt.title('Number of Leaves Distribution',size=18) plt.title('Number of Leaves Distribution', size = 18) plt.xlabel('Number of Leaves', size = 16) plt.ylabel('Density', size = 16) plt.show()
 這里使用的是一個(gè)離散均勻分布,因?yàn)槿~子結(jié)點(diǎn)的數(shù)量必須是一個(gè)整數(shù)(離散的)并且域中的每個(gè)值出現(xiàn)的概率是均等的(均勻)。
概率分布的另一種選項(xiàng)是對(duì)數(shù)均勻分布,在對(duì)數(shù)尺度上其值的分布是均勻的。我們將對(duì)學(xué)習(xí)率使用一個(gè)對(duì)數(shù)均勻分布(域空間從 0.005 到 0.2),因?yàn)樗闹低诓煌臄?shù)量級(jí)之間變化:
from hyperopt import hp from hyperopt.pyll.stochastic import sample # Discrete uniform distribution num_leaves = {'num_leaves': hp.quniform('num_leaves', 30, 150, 1)}# Learning rate log uniform distribution learning_rate = {'learning_rate': hp.loguniform('learning_rate',np.log(0.005),np.log(0.2))} learning_rate_dist = []for i in range(10000):learning_rate_dist.append(sample(learning_rate)['learning_rate'])plt.figure(figsize=(8, 6)) sns.kdeplot(learning_rate_dist, color='red', linewidth=2, shade=True) plt.title('Learning Rate Distribution', size=18) plt.xlabel('Learning Rate', size=16) plt.ylabel('Density', size=16) plt.show()-現(xiàn)在開(kāi)始定義整個(gè)域
from hyperopt import hp from hyperopt.pyll.stochastic import sample # Define the search space space = {'class_weight': hp.choice('class_weight', [None, 'balanced']),'boosting_type': hp.choice('boosting_type', [{'boosting_type': 'gbdt', 'subsample': hp.uniform('gdbt_subsample', 0.5, 1)}, {'boosting_type': 'dart', 'subsample': hp.uniform('dart_subsample', 0.5, 1)},{'boosting_type': 'goss'}]),'num_leaves': hp.quniform('num_leaves', 30, 150, 1),'learning_rate': hp.loguniform('learning_rate', np.log(0.01), np.log(0.2)),'subsample_for_bin': hp.quniform('subsample_for_bin', 20000, 300000, 20000),'min_child_samples': hp.quniform('min_child_samples', 20, 500, 5),'reg_alpha': hp.uniform('reg_alpha', 0.0, 1.0),'reg_lambda': hp.uniform('reg_lambda', 0.0, 1.0),'colsample_bytree': hp.uniform('colsample_by_tree', 0.6, 1.0) }此處我們使用許多不同種類(lèi)的域分布:
-  choice:類(lèi)別變量 
-  quniform:離散均勻分布(在整數(shù)空間上均勻分布) 
-  uniform:連續(xù)均勻分布(在浮點(diǎn)數(shù)空間上均勻分布) 
-  loguniform:連續(xù)對(duì)數(shù)均勻分布(在浮點(diǎn)數(shù)空間中的對(duì)數(shù)尺度上均勻分布) 
前面提到過(guò),boosting_type的選擇會(huì)影響到subsample的取值,因此,我們需要使用一個(gè)條件域,它意味著一個(gè)超參數(shù)的值依賴(lài)于另一個(gè)超參數(shù)的值。對(duì)于「goss」類(lèi)型的提升算法,GBM 不能使用下采樣技術(shù)(選擇一個(gè)訓(xùn)練觀測(cè)數(shù)據(jù)的子樣本部分用于每輪迭代)。因此,如果提升的類(lèi)型為「goss」,則下采樣率設(shè)置為 1.0(不使用下采樣),否則將其設(shè)置為 0.5-1.0。這個(gè)過(guò)程是使用嵌套域?qū)崿F(xiàn)的。
當(dāng)我們使用參數(shù)完全不同的機(jī)器學(xué)習(xí)模型時(shí),條件嵌套往往是很有用的。條件嵌套讓我們能根據(jù)「choice」的不同值使用不同的超參數(shù)集。
現(xiàn)在已經(jīng)定義了域空間,我們可以從中提取一個(gè)樣本來(lái)查看典型樣本的形式。當(dāng)我們進(jìn)行采樣時(shí),因?yàn)樽訕颖咀畛跏乔短椎?#xff0c;所以我們需要將它分配給頂層的關(guān)鍵字。這個(gè)操作是通過(guò) Python 字典的「get」方法實(shí)現(xiàn)的,缺省值為 1.0。
# boosting type domain boosting_type = {'boosting_type': hp.choice('boosting_type', [{'boosting_type': 'gbdt', 'subsample': hp.uniform('subsample', 0.5, 1)}, {'boosting_type': 'dart', 'subsample': hp.uniform('subsample', 0.5, 1)},{'boosting_type': 'goss', 'subsample': 1.0}])}# Draw a sample params = sample(boosting_type) params從Domain中采樣
# Sample from the full space x = sample(space)# Conditional logic to assign top-level keys subsample = x['boosting_type'].get('subsample', 1.0) x['boosting_type'] = x['boosting_type']['boosting_type'] x['subsample'] = subsample print(x)#運(yùn)行結(jié)果1 {'boosting_type': 'goss', 'class_weight': None, 'colsample_bytree': 0.7366231307966129, 'learning_rate': 0.1398679010119344, 'min_child_samples': 380.0, 'num_leaves': 73.0, 'reg_alpha': 0.5266573540445147, 'reg_lambda': 0.889404989776478, 'subsample_for_bin': 20000.0, 'subsample': 1.0}#再運(yùn)行一次 {'boosting_type': 'goss', 'class_weight': None, 'colsample_bytree': 0.895519861622759, 'learning_rate': 0.02470781377355416, 'min_child_samples': 50.0, 'num_leaves': 112.0, 'reg_alpha': 0.30733406661439966, 'reg_lambda': 0.4114311595001603, 'subsample_for_bin': 200000.0, 'subsample': 1.0}-優(yōu)化算法:
盡管從概念上來(lái)說(shuō),這是貝葉斯優(yōu)化最難的一部分,但在 Hyperopt 中創(chuàng)建優(yōu)化算法只需一行代碼。使用樹(shù)形 Parzen 評(píng)估器(Tree Parzen Estimation,以下簡(jiǎn)稱(chēng) TPE)的代碼如下:
from hyperopt import tpe # Algorithm tpe_algorithm = tpe.suggest這就是優(yōu)化算法的所有代碼!Hyperopt 目前只支持 TPE 和隨機(jī)搜索,盡管其 GitHub 主頁(yè)聲稱(chēng)將會(huì)開(kāi)發(fā)其它方法。在優(yōu)化過(guò)程中,TPE 算法從過(guò)去的搜索結(jié)果中構(gòu)建出概率模型,并通過(guò)最大化預(yù)期提升(EI)來(lái)決定下一組目標(biāo)函數(shù)中待評(píng)估的超參數(shù)。
- 結(jié)果歷史數(shù)據(jù)
跟蹤這些結(jié)果并不是絕對(duì)必要的,因?yàn)?Hyperopt 會(huì)在內(nèi)部為算法執(zhí)行此操作。然而,如果我們想要知道這背后發(fā)生了什么,我們可以使用「Trials」對(duì)象,它將存儲(chǔ)基本的訓(xùn)練信息,還可以使用目標(biāo)函數(shù)返回的字典(包含損失「loss」和參數(shù)「params」)。創(chuàng)建一個(gè)「Trials」對(duì)象也僅需一行代碼:
from hyperopt import Trials # Trials object to track progress bayes_trials = Trials()作為參考,500 輪隨機(jī)搜索返回一個(gè)在測(cè)試集上 ROC AUC 得分為 0.7232、在交叉驗(yàn)證中得分為 0.76850 的模型。一個(gè)沒(méi)有經(jīng)過(guò)優(yōu)化的缺省模型在測(cè)試集上的 ROC AUC 得分則為 0.7143.
當(dāng)我們查看結(jié)果時(shí),需要將以下幾點(diǎn)重要事項(xiàng)牢記于心:
最優(yōu)的超參數(shù)在交叉驗(yàn)證中表現(xiàn)最好,但并不一定在測(cè)試數(shù)據(jù)上表現(xiàn)最好。當(dāng)我們使用交叉驗(yàn)證時(shí),我們希望這些結(jié)果能夠泛化至測(cè)試數(shù)據(jù)上。
即使使用 10 折交叉驗(yàn)證,超參數(shù)調(diào)優(yōu)還是會(huì)對(duì)訓(xùn)練數(shù)據(jù)過(guò)度擬合。交叉驗(yàn)證取得的最佳得分遠(yuǎn)遠(yuǎn)高于在測(cè)試數(shù)據(jù)上的得分。
隨機(jī)搜索可能由于運(yùn)氣好而返回更好的超參數(shù)(重新運(yùn)行 notebook 就可能改變搜索結(jié)果)。貝葉斯優(yōu)化不能保證找到更好的超參數(shù),并且可能陷入目標(biāo)函數(shù)的局部最小值。
貝葉斯優(yōu)化雖然十分有效,但它并不能解決我們所有的調(diào)優(yōu)問(wèn)題。隨著搜索的進(jìn)行,該算法將從探索——嘗試新的超參數(shù)值,轉(zhuǎn)向開(kāi)發(fā)——利用使目標(biāo)函數(shù)損失最低的 超參數(shù)值。如果算法找到了目標(biāo)函數(shù)的一個(gè)局部最小值,它可能會(huì)專(zhuān)注于搜索局部最小值附近的超參數(shù)值,而不會(huì)嘗試域空間中相對(duì)于局部最小值較遠(yuǎn)的其他值。隨機(jī)搜索則不會(huì)受到這個(gè)問(wèn)題的影響,因?yàn)樗粫?huì)專(zhuān)注于搜索任何值。
總結(jié)
以上是生活随笔為你收集整理的超参数的调优(lightgbm)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: php在线查毒,linux clamav
- 下一篇: 白话机器学习算法理论+实战番外篇之Lig
