日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

超参数的调优(lightgbm)

發布時間:2023/12/14 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 超参数的调优(lightgbm) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

參考
原文
Automated Hyperparameter Optimization

超參數的優化過程:通過自動化
目的:使用帶有策略的啟發式搜索(informed search)在更短的時間內找到最優超參數,除了初始設置之外,并不需要額外的手動操作。

實踐部分

貝葉斯優化問題有四個組成部分:

  • 目標函數:我們想要最小化的對象,這里指帶超參數的機器學習模型的驗證誤差

  • 域空間:待搜索的超參數值

  • 優化算法:構造代理模型和選擇接下來要評估的超參數值的方法

  • 結果的歷史數據:存儲下來的目標函數評估結果,包含超參數和驗證損失

  • 通過以上四個步驟,我們可以對任意實值函數進行優化(找到最小值)。這是一個強大的抽象過程,除了機器學習超參數的調優,它還能幫我們解決其他許多問題。

    代碼示例

    數據集:https://www.jiqizhixin.com/articles/2018-08-08-2
    目標:預測客戶是否會購買一份保險產品
    監督分類問題
    觀測值:5800
    測試點:4000
    不平衡的分類問題,本文使用的評價性能的指標是受試者工作特征曲線下的面積(ROC AUC),ROC AUC 的值越高越好,其值為 1 代表模型是完美的。

    什么是不平衡的分類問題?
    如何處理數據中的「類別不平衡」?
    極端類別不平衡數據下的分類問題S01:困難與挑戰

    hyperropt1125.py

    - 導入庫

    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

    觀察數據,數據集已經用ORIGIN把數據自動分為train和test集。

    print(data.ORIGIN.value_counts())train 5822 test 4000 Name: ORIGIN, dtype: int64

    復習一下,隨意畫個圖

    sns.countplot(x='ORIGIN',data=data) plt.show()


    CARAVAN: target

    - 處理數據集

    一定要細心啊,不然BUG真的莫名其妙。

    #導入后先劃分訓練集和測試集 train = data[data['ORIGIN'] == 'train'] test = data[data['ORIGIN'] == 'test']#抽取標簽 train_labels = np.array(train['CARAVAN'].astype(np.int32)).reshape((-1,)) test_labels = np.array(test['CARAVAN'].astype(np.int32)).reshape((-1,))去掉標簽們,留下特征 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()#運行結果 Train shape: (5822, 85) Test shape :(4000, 85)

    Python中reshape函數參數-1的意思
    不分行列,改成1串

    - 標簽分布

    plt.hist(labels, edgecolor = 'k') plt.xlabel('Label') plt.ylabel('Count') plt.title('Counts of Labels')plt.show()

    hist函數1


    可以看出,這是個不平衡的分類問題。
    因此,選用梯度提升模型,驗證方法采用ROC AUC。(具體見原文了)
    本文采用的是LightGBM。

    -模型與其默認值

    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)

    將模型與訓練集擬合,采用roc_auc驗證。

    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 seconds

    Due 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中計時工具timeit模塊的基本用法
    測試代碼運行時間

    Random Search

    import random

    隨機搜索也有四個部分:

    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

    讓我們來康康哪些參數要Tuning

    - Domain for Random Search

    Random search and Bayesian optimization 都是從domain搜索hyperparameters,對于random (or grid search),這種domain被稱為hyperparameter grid,并且對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)

    基于默認值,以下可構建hyperparameter grid。在此之前選值怎么工作得更好并不好說,因此對于大部分參數我們均采用默認值或以默認值為中心上下浮動的值。
    **注意:**subsample_dist是subsample的參數,但boosting_type=goss不支持隨機的 subsampling。
    假如boosting_type選擇其他值,那么這個subsample_dist可以放到param_grid里讓我們隨機搜索。

    param_grid = {'class_weight': [None, 'balanced'],'boosting_type': ['gbdt', 'goss', 'dart'],'num_leaves': list(range(30, 150)),'learning_rate': list(np.logspace(np.log(0.005), np.log(0.2), base = np.exp(1), num = 1000)),'subsample_for_bin': list(range(20000, 300000, 20000)),'min_child_samples': list(range(20, 500, 5)),'reg_alpha': list(np.linspace(0, 1)),'reg_lambda': list(np.linspace(0, 1)),'colsample_bytree': list(np.linspace(0.6, 1, 10)) }# Subsampling (only applicable with 'goss') subsample_dist = list(np.linspace(0.5, 1, 100))

    讓我們來康康 learning_ratethe num_leaves的分布,學習率是典型的對數分布,參見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之間的值較多。建議在這個范圍里選值。

    再來看看num_leaves的表現

    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()


    沒什么波動。

    -Sampling from Hyperparameter Domain

    查看我們采樣的結果:

    params = {key:random.sample(value,1)[0] for key,value in param_grid.items()} print(params)#運行結果 {'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}

    其他:
    生成隨機系數

    import random a = dict(....) # a is some dictionary random_key = random.sample(a, 1)[0]

    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類型時,對subsample也能采取隨機采樣。

    params['subsample'] = random.sample(subsample_dist, 1)[0] if params['boosting_type'] != 'goss' else 1.0 print(params)#運行結果 {'class_weight': 'balanced', 'boosting_type': 'gbdt', 'num_leaves': 47, 'learning_rate': 0.008572448761425775, 'subsample_for_bin': 20000, 'min_child_samples': 420, 'reg_alpha': 0.6122448979591836, 'reg_lambda': 0.7142857142857142, 'colsample_bytree': 0.7333333333333333, 'subsample': 0.8282828282828283}

    -Cross Validation with Early Stopping in LightGBM

    使用LightGBM的cross validation function,采用100 early stopping rounds。
    建立數據集,懶得改了,但是我的習慣是,features用X_train表達,labels用y_train = labels表達

    train_set = lgb.Dataset(features,labels) cv_results = lgb.cv(params,train_set,num_boost_round=10000,nfold=10,metrics='auc',early_stopping_rounds=100,verbose_eval=False,seed=50) #最高分 cv_results_best = np.max(cv_results['auc-mean']) #最高分的標準差 cv_results_std = cv_results['auc-stdv'][np.argmax(['auc-mean'])]print("the maximum ROC AUC on the validation set was{:.5f} with std of {:.5f}.".format(cv_results_best,cv_results_std)) print('The ideal number of iteractions was {}.'.format(np.argmax(cv_results['auc-mean'])+1))#運行結果 the maximum ROC AUC on the validation set was0.75260 with std of 0.03831. The ideal number of iteractions was 5.

    詳解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()))#運行結果 best n_estimator is 7 best cv score is 0.7568251976593624

    -Results Dataframe

    從前面的運算,我們已經獲取了:

    • 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 將通過一個dataframe完成,每行對目標函數進行評估。

    random_results = pd.DataFrame(columns=['loss','params','iteration','estimator','time'],index=list(range(MAX_EVALIS)))#index行標簽

    -目標函數

    我們試圖最小化目標函數。其輸入為一組值——在本例中為 GBM 的超參數,輸出為需要最小化的實值——交叉驗證損失。Hyperopt
    將目標函數作為黑盒處理,因為這個庫只關心輸入和輸出是什么。為了找到使損失最小的輸入值,該算法不需要知道目標函數的內部細節!

    與從訓練數據中提取驗證集(從而限制我們擁有的訓練數據的數量)相比,更好的方法是KFold交叉驗證。

    對于此示例,我們將使用10倍交叉驗證,這意味著測試和訓練每組模型超參數10次,每次使用不同的訓練數據子集作為驗證集。

    在隨機搜索的情況下,下一個選擇的值不是基于過去的評估結果,但顯然仍應對運算保持跟蹤,以便我們知道哪個值最有效。 這也將使我們能夠將隨機搜索與明智的貝葉斯優化進行對比。

    -Random Search Implementation隨機搜索的實現

    目的:寫一個循環遍歷評估次數,每次選擇一組不同的超參數進行評估。
    每次運行該函數,結果都會保存到dataframe中。

    關于亂序(shuffle)與隨機采樣(sample)的一點探究

    random.seed(50) #用前面設置好的值來作為遍歷的次數: for i in range(MAX_EVALIS):params = {key:random.sample(value,1)[0] for key,value in param_grid.items() }#隨機取樣gbm的參數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)#將結果添加到數據下一行random_results.loc[i, :] = results_list#對分析結果進行排序 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()
    語法:

    Syntax: Series.reset_index(level=None, drop=False, name=None, inplace=False)#Parameter : level : For a Series with a MultiIndex drop : Just reset the index, without inserting it as a column in the new DataFrame. name : The name to use for the column containing the original Series values. inplace : Modify the Series in placeReturns : result : Series

    500次實在太慢了,估計能找到明天,所以用原文里運行的結果吧。

    -Random Search Performance

    根據運算結果選擇參數,用測試集評估它們。
    選擇最好表現的一組。
    因為電腦實在太慢,以下都是抄的我自己沒跑……

    random_results.loc[0, 'params']#運行 {'boosting_type': 'gbdt','class_weight': None,'colsample_bytree': 0.6444444444444444,'learning_rate': 0.006945380919765311,'metric': 'auc','min_child_samples': 255,'num_leaves': 41,'reg_alpha': 0.5918367346938775,'reg_lambda': 0.5102040816326531,'subsample': 0.803030303030303,'subsample_for_bin': 120000,'verbose': 1}

    用隨機搜索的參數訓練模型并進行評估

    # 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']))

    結果

    The best model from random search scores 0.7232 on the test data. This was achieved using 146 search iterations.

    開始貝葉斯調優

    1.目標函數
    我們試圖最小化目標函數。其輸入為一組值——在本例中為 GBM 的超參數,輸出為需要最小化的實值——交叉驗證損失。Hyperopt 將目標函數作為黑盒處理,因為這個庫只關心輸入和輸出是什么。為了找到使損失最小的輸入值,該算法不需要知道目標函數的內部細節!從一個高度抽象的層次上說(以偽代碼的形式),我們的目標函數可以表示為:

    from hyperopt import STATUS_OKdef objective(params,n_folds = N_FLODS):cv_results = lgb.cv(params,train_set,nfold=n_folds,num_boost_round=10000,early_stopping_rounds=100,metrics='auc',seed=50)best_score = max(cv_results['auc-mean'])loss = 1 - best_scorereturn {'loss':loss,'params':params,'status':STATUS_OK}

    核心的代碼為「cv_results = lgb.cv(…)」。為了實現帶早停止的交叉驗證,我們使用了 LightGBM 的函數「cv」,向該函數傳入的參數包含超參數、一個訓練集、交叉驗證中使用的許多折,以及一些其它的參數。我們將評估器的數量(num_boost_round)設置為 10000,但是由于我們使用了「early_stopping_rounds」,當 100 個評估器的驗證得分沒有提高時訓練會被停止,所以實際上使用的評估器不會達到這個數量。早停止是一種有效的選擇評估器數量的方法,而不是將其設置為另一個需要調優的超參數!

    當交叉驗證完成后,我們將得到最高得分(ROC AUC)。之后,由于我們想要得到的是最小值,我們將采用「1-最高得分」。該值將在返回的字典數據結構中作為「loss」關鍵字返回。

    這個目標函數實際上比它所需的結構復雜一些,因為我們將返回一個值的字典。對于 Hyperopt 中的目標函數,我們可以返回一個單一的值(即損失),或者返回一個帶有最小值的關鍵字「loss」和「status」的字典。返回超參數的值使我們能夠查看每組超參數得到的損失。
    2.域空間(domain)
    域空間表示我們想要對每個超參數進行評估的值的范圍。在每一輪搜索迭代中,貝葉斯優化算法將從域空間中為每個超參數選定一個值。當我們進行隨機搜索或網格搜索時,域空間就是一個網格。貝葉斯優化中也是如此,只是這個域空間對每個超參數來說是一個概率分布而不是離散的值。

    然而,在貝葉斯優化問題中,確定域空間是最難的部分。如果有機器學習方法的相關經驗,我們可以將更大的概率賦予我們認為最佳值可能存在的點,以此來啟發對超參數分布的選擇。但是,不同的數據集之間的最佳模型設定是不同的,并且具有高維度的問題(大量的超參數),這會使我們很難弄清超參數之間的相互作用。在不確定最佳值的情況下,我們可以使用更大范圍的概率分布,通過貝葉斯算法進行推理。

    lgb的超參數的值上面寫過了這里就不再弄。
    雖然我也不想用機翻,但為了不浪費時間就好好用我的復制粘貼大法了:

    我不確定世界上是否真有人知道所有的這些超參數是如何相互作用的!而其中有一些超參數是不需要調優(如「objective」和「random_state」)。我們將使用早停止方法找到最佳的評估器數量「n_estimators」。盡管如此,我們仍然需要優化 10 個超參數!當我們第一次對一個模型進行調優時,我通常創建一個以缺省值為中心的大范圍域空間,然后在接下來的搜索中對其進行優化。

    舉個例子,我們不妨在 Hyperopt 中定義一個簡單的域——一個離散均勻分布,其中離散點的數量為 GBM 中每棵決策樹的葉子結點數:

    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()


    這里使用的是一個離散均勻分布,因為葉子結點的數量必須是一個整數(離散的)并且域中的每個值出現的概率是均等的(均勻)。

    概率分布的另一種選項是對數均勻分布,在對數尺度上其值的分布是均勻的。我們將對學習率使用一個對數均勻分布(域空間從 0.005 到 0.2),因為它的值往往在不同的數量級之間變化:

    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()

    -現在開始定義整個域

    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) }

    此處我們使用許多不同種類的域分布:

    • choice:類別變量

    • quniform:離散均勻分布(在整數空間上均勻分布)

    • uniform:連續均勻分布(在浮點數空間上均勻分布)

    • loguniform:連續對數均勻分布(在浮點數空間中的對數尺度上均勻分布)

    前面提到過,boosting_type的選擇會影響到subsample的取值,因此,我們需要使用一個條件域,它意味著一個超參數的值依賴于另一個超參數的值。對于「goss」類型的提升算法,GBM 不能使用下采樣技術(選擇一個訓練觀測數據的子樣本部分用于每輪迭代)。因此,如果提升的類型為「goss」,則下采樣率設置為 1.0(不使用下采樣),否則將其設置為 0.5-1.0。這個過程是使用嵌套域實現的。

    當我們使用參數完全不同的機器學習模型時,條件嵌套往往是很有用的。條件嵌套讓我們能根據「choice」的不同值使用不同的超參數集。

    現在已經定義了域空間,我們可以從中提取一個樣本來查看典型樣本的形式。當我們進行采樣時,因為子樣本最初是嵌套的,所以我們需要將它分配給頂層的關鍵字。這個操作是通過 Python 字典的「get」方法實現的,缺省值為 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)#運行結果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}#再運行一次 {'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}

    -優化算法:

    盡管從概念上來說,這是貝葉斯優化最難的一部分,但在 Hyperopt 中創建優化算法只需一行代碼。使用樹形 Parzen 評估器(Tree Parzen Estimation,以下簡稱 TPE)的代碼如下:

    from hyperopt import tpe # Algorithm tpe_algorithm = tpe.suggest

    這就是優化算法的所有代碼!Hyperopt 目前只支持 TPE 和隨機搜索,盡管其 GitHub 主頁聲稱將會開發其它方法。在優化過程中,TPE 算法從過去的搜索結果中構建出概率模型,并通過最大化預期提升(EI)來決定下一組目標函數中待評估的超參數。

    - 結果歷史數據

    跟蹤這些結果并不是絕對必要的,因為 Hyperopt 會在內部為算法執行此操作。然而,如果我們想要知道這背后發生了什么,我們可以使用「Trials」對象,它將存儲基本的訓練信息,還可以使用目標函數返回的字典(包含損失「loss」和參數「params」)。創建一個「Trials」對象也僅需一行代碼:

    from hyperopt import Trials # Trials object to track progress bayes_trials = Trials()

    作為參考,500 輪隨機搜索返回一個在測試集上 ROC AUC 得分為 0.7232、在交叉驗證中得分為 0.76850 的模型。一個沒有經過優化的缺省模型在測試集上的 ROC AUC 得分則為 0.7143.

    當我們查看結果時,需要將以下幾點重要事項牢記于心:

    最優的超參數在交叉驗證中表現最好,但并不一定在測試數據上表現最好。當我們使用交叉驗證時,我們希望這些結果能夠泛化至測試數據上。

    即使使用 10 折交叉驗證,超參數調優還是會對訓練數據過度擬合。交叉驗證取得的最佳得分遠遠高于在測試數據上的得分。

    隨機搜索可能由于運氣好而返回更好的超參數(重新運行 notebook 就可能改變搜索結果)。貝葉斯優化不能保證找到更好的超參數,并且可能陷入目標函數的局部最小值。

    貝葉斯優化雖然十分有效,但它并不能解決我們所有的調優問題。隨著搜索的進行,該算法將從探索——嘗試新的超參數值,轉向開發——利用使目標函數損失最低的 超參數值。如果算法找到了目標函數的一個局部最小值,它可能會專注于搜索局部最小值附近的超參數值,而不會嘗試域空間中相對于局部最小值較遠的其他值。隨機搜索則不會受到這個問題的影響,因為它不會專注于搜索任何值。

    總結

    以上是生活随笔為你收集整理的超参数的调优(lightgbm)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。