當前位置:
首頁 > 知識 > 自定義損失函數Gradient Boosting

自定義損失函數Gradient Boosting

本文為 AI 研習社編譯的技術博客,原標題 :Custom Loss Functions for Gradient Boosting

翻譯 | 就2 校對| Lamaric 整理 | 菠蘿妹


用於梯度提升的自定義損失函數

優化最重要

作者: Prince Grover and Sourav Dey


簡介

梯度提升技術在工業上得到了廣泛的應用,並贏得了多項Kaggle比賽。

互聯網上有很多關於梯度提升的很好的解釋(我們在參考資料中分享了一些選擇的鏈接),但是我們注意到很少有人提起自定義損失函數的信息:為什麼要自定義損失函數,何時需要自定義損失函數,以及如何自定義損失函數。

這篇文章中我們將總結自定義損失函數在很多現實問題中的重要性,以及如何使用 LightGBM gradient boosting(LightGBM漸變增強包) 實現它們。

優化機器學習演算法通常是最小化訓練數據的損失函數。

在一般的ML庫中有許多常用的損失函數。如果你想了解更多這方面的知識,請閱讀普林斯在攻讀數據科學碩士學位時寫的這篇文章。在現實世界中,這些「現成的」損失函數通常不能很好地適應我們試圖解決的業務問題。所以我們引入自定義損失函數。


自定義損失函數

一個使用自定義損失函數的例子是機場準時的不對稱風險。問題是:你要決定什麼時候從家裡出發,這樣你才能在按時到達機場。我們不想太早走,在機場等上幾個小時。同時,我們不想錯過我們的航班。任何一方的損失都是不同的: 如果我們提前到達機場,情況真的沒有那麼糟;如果我們到得太晚而錯過了航班,那真是糟透了。

如果我們使用機器學習來決定什麼時候離開,我們可能想要在我們的模型中直接處理這種風險不對稱,通過使用一個自定義損失函數來懲罰延遲錯誤而不是提早到達錯誤。

另一個常見的例子出現在分類問題中。例如,在疾病檢測方面,我們可能會認為假陰性比假陽性嚴重得多,因為給健康人用藥通常比不給病人用藥危害小。在這種情況下,我們可能想要優化F-beta 分數,其中取決於我們想給假陽性的權重大小。這有時被稱為內曼-皮爾遜準則(Neyman-Pearson criterion)。

在Manifold公司,我們最近遇到了一個問題,需要一個自定義損失函數。我們的客戶之一Cortex Building Intelligence提供的一個應用程序,可以幫助工程師更精確地操作一棟建築的供暖、通風和空調系統。大部分商業樓宇有「房東義務」,在辦公時間內,例如在上午九時至下午六時的工作時間,把樓宇的室內溫度調至「舒適」的溫度範圍,例如在70至74華氏度之間。同時,這種HVAC溫控是建築最大的運營成本。高效的HVAC運行的關鍵是在不需要的時候關閉系統,比如在晚上,然後在清晨再次打開,以履行「房東義務」。為了達到這個目的,Manifold幫助Cortex建立了一個預測模型,以推薦在建築物中打開HVAC系統的確切時間。

然而,錯誤預測的懲罰不是對稱的。 如果我們預測的開始時間早於實際所需的開始時間,那麼建築物將過早地達到舒適的溫度並且會浪費一些能量。 但是如果預測的時間晚於實際所需的開始時間,那麼建築物將會來得太晚,租戶也不會感到高興——沒有人想在寒冷/悶熱的建築物中工作,購物或學習。 因此,遲到比早期更糟糕,因為我們不希望租戶(畢竟真金白銀交了租金)不開心。 我們通過創建自定義非對稱Huber損失函數在我們的模型中編碼了這種業務知識,當殘差為正與負時,該函數具有更高的誤差。 有關此問題的更多詳細信息,請參閱此文章。

忽略恢復時間錯誤的含義

另外: 找到一個與你的商業目標緊密匹配的損失函數。通常,這些損失函數在流行的機器學習庫中並沒有默認的實現。但是沒關係: 定義自己的損失函數並使用它來解決問題並不難。


自定義訓練損失函數並驗證

在進一步深入之前,讓我們明確一下我們的定義。ML文獻中使用了許多術語來指代不同的事物。我們將選擇一組我們認為最清楚的定義:

1、訓練損失。這是對訓練數據進行優化的函數。例如,在神經網路二進位分類器中,這通常是二進位交叉熵。對於隨機森林分類器,這是基尼指數。訓練損失也常被稱為「目標函數」。

2、驗證損失。這是我們用來評估我們的訓練模型在看不見的數據上的性能的函數。這通常與訓練損失不同。例如,在分類器的情況下,這通常是接收器工作特性曲線下的面積(ROC) -雖然這從來沒有直接優化,因為它是不可微的。這通常被稱為「性能或評估度量」。

在許多情況下,定製這些損失可以真正有效地構建更好的模型。這對於梯度增強特別簡單,如下所示。


訓練損失

在訓練過程中,訓練損失得到優化。對於某些演算法來說很難定製,比如隨機森林(見這裡),但是對於其他演算法來說相對容易,比如梯度提升和神經網路。由於梯度下降的某些變體通常是優化方法,訓練損失通常需要一個具有凸梯度(一階導數)和海森(二階導數)的函數。最好是連續的,有限的,非零的。最後一個很重要,因為函數為0的部分可以凍結梯度下降。

在梯度提升的背景下,訓練損失是利用梯度下降法進行優化的函數,如梯度提升模型的「梯度」部分。具體來說,使用訓練損失的梯度來改變每個連續樹的目標變數。(如果你對更多細節感興趣,請看這篇文章。)請注意,即使訓練損失定義了「梯度」,每個樹仍然需要使用貪婪分割演算法來生長,而不是綁定到這個自定義損失函數。

定義一個定製的訓練損失通常需要我們做一些微積分來找到梯度和海森(矩陣 Hessian matrix)。正如我們接下來將看到的,首先更改驗證損失通常更容易,因為它不需要太多的開銷。

驗證損失

驗證損失用於優化超參數。它通常更容易定製,因為它不像訓練損失那樣有很多功能需求。驗證損失可以是非凸的、不可微分的和不連續的。因此,從定製開始通常更容易。

例如,在LightGBM中,一個重要的超參數是增加輪數。驗證損失可用於找到最佳數量的助推輪次。這種LightGBM中的驗證損失稱為

eval_metric

我們可以使用庫中可用的驗證損失之一,或者定義我們自己的自定義函數。因為它非常簡單,如果它對您的業務問題很重要,那麼您一定要自定義。

具體來說,我們通常使用early_stopping_rounds變數,而不是直接優化num boosting rounds。當給定數量的早期停止輪次的驗證損失開始增加時,它會停止提升。實際上,它通過監視樣本外驗證集的驗證損失來防止過擬合。如下圖所示,設置更高的停止輪次會導致模型運行以進行更多提升輪次。

藍色:訓練的損失。橙色:驗證損失。訓練和驗證都使用相同的自定義損失函數

k-fold交叉驗證。每個測試評分與驗證損失

記住,驗證策略也非常重要。上面的訓練/驗證分離是許多可能的驗證策略之一。它可能不適合你的問題。其他的包括k-fold交叉驗證和嵌套交叉驗證,這是我們在HVAC開始時間建模問題上使用的。

如果適合於業務問題,我們希望對我們的訓練和驗證損失使用自定義函數。在某些情況下,由於自定義損失的功能形式,可能無法使用它作為訓練損失。在這種情況下,只需更新驗證損失並使用默認的訓練損失(如MSE)就可以了。您仍然會得到好處,因為超參數將使用所需的自定義損耗進行調優。

在LightGBM中實現自定義損失函數

讓我們看看實際情況,並在模擬數據上做一些實驗。首先,我們假設高估比低估更糟糕。此外, 讓我們假設平方損失是一個很好的誤差模型為我們提供兩個方向上的誤差損失。為了對其進行編碼,我們定義了一個自定義MSE函數,它對正殘差的懲罰是負殘差的10倍。下圖展示了我們的自定義損失函數與標準MSE損失函數的對比。

正如定義的那樣,非對稱MSE很好,因為它很容易計算梯度和hessian,如下圖所示。注意,hessian在兩個不同的值上是常量,左邊是2,右邊是20,儘管在下面的圖中很難看到這一點。

LightGBM提供了一種直接實現定製訓練和驗證損失的方法。其他的梯度提升包,包括XGBoost和Catboost,也提供了這個選項。這裡是一個Jupyter筆記本,展示了如何實現自定義培訓和驗證損失函數。細節在筆記本上,但在高層次上,實現略有不同。

1、訓練損失:在LightGBM中定製訓練損失需要定義一個包含兩個梯度數組的函數,目標和它們的預測。反過來,該函數應該返回梯度的兩個梯度和每個觀測值的hessian數組。如上所述,我們需要使用微積分來派生gradient和hessian,然後在Python中實現它。

2、驗證丟失:在LightGBM中定製驗證丟失需要定義一個函數,該函數接受相同的兩個數組,但返回三個值: 要列印的名稱為metric的字元串、損失本身以及關於是否更高更好的布爾值。


用於在LightGBM中實現自定義丟失的代碼

defcustom_asymmetric_train(y_true, y_pred):

residual = (y_true - y_pred).astype("float")

grad = np.where(residual

hess = np.where(residual

returngrad, hess

defcustom_asymmetric_valid(y_true, y_pred):

residual = (y_true - y_pred).astype("float")

loss = np.where(residual

return"custom_asymmetric_eval", np.mean(loss), False

定義自定義驗證和訓練損失函數

importlightgbm

********* Sklearn API **********

# default lightgbm modelwithsklearn api

gbm = lightgbm.LGBMRegressor()

# updating objective function to custom

# default is"regression"

# also adding metrics to check different scores

gbm.set_params(**{"objective": custom_asymmetric_train}, metrics = ["mse","mae"])

# fitting model

gbm.fit(

X_train,

y_train,

eval_set=[(X_valid, y_valid)],

eval_metric=custom_asymmetric_valid,

verbose=False,

)

y_pred = gbm.predict(X_valid)

********* Python API **********

# create dataset for lightgbm

#ifyou want to re-use data, remember to set free_raw_data=False

lgb_train = lgb.Dataset(X_train, y_train, free_raw_data=False)

lgb_eval = lgb.Dataset(X_valid, y_valid, reference=lgb_train, free_raw_data=False)

# specify your configurationsasa dict

params = {

"objective":"regression",

"verbose":

}

gbm = lgb.train(params,

lgb_train,

num_boost_round=10,

init_model=gbm,

fobj=custom_asymmetric_train,

feval=custom_asymmetric_valid,

valid_sets=lgb_eval)

y_pred = gbm.predict(X_valid)

在LightGBM中結合訓練和驗證損失(包括Python和scikit-learn API示例)


自定義損失函數的實驗

Jupyter 筆記本 的代碼還對默認隨機森林,默認LightGBM和MSE以及LightGBM與自定義訓練和驗證丟失功能進行了深入比較。

我們使用Friedman 1合成數據集,進行了8,000次訓練觀察,2,000次驗證觀察和5,000次測試觀察。 驗證集用於找到優化驗證損失的最佳超參數集。下面報告的分數在測試觀察結果上進行評估,以評估我們模型的普遍性。

我們做了一系列實驗,總結如下表。 請注意,我們關心的最重要的分數是非對稱MSE,因為它明確定義了我們的不對稱懲罰問題。

實驗和結果

讓我們詳細比較。

隨機森林LightGBM

使用默認設置,LightGBM在此數據集上的性能優於Random Forest 隨機森林。 隨著讓更多樹木充份生長和超參數的更好組合,隨機森林也可能會給出好的結果,但這不是重點。

LightGBMLightGBM,具有定製的訓練損失

這表明我們可以使我們的模型優化我們關心的內容。 默認的LightGBM正在優化MSE(均方誤差),因此它可以降低MSE損失(0.24對0.33)。 具有自定義訓練損失的LightGBM優化了非對稱MSE,因此對於非對稱MSE(1.31 vs. 0.81)表現更好。

LightGBMLightGBM使用MSE調整提前停止輪次

兩種LightGBM模型都在優化MSE。 我們看到默認的MSE分數有了很大改善,只需稍微調整一下使用提前停止輪次(MSE:0.24 vs 0.14)。 因此,我們應該讓模型使用提前停止超參數來確定最佳提升次數,而不是將提升次數限制為默認值( 即 100)。 超參數優化很重要!

LightGBM使用MSELightGBM調整提前停止輪次,並使用自定義MSE進行早期停止調整

這兩個模型的得分非常接近,沒有實質性差異。 這是因為驗證損失僅用於決定何時停止提升。 梯度是在兩種情況下優化默認MSE。 每個後續樹為兩個模型生成相同的輸出。 唯一的區別是具有自定義驗證損失的模型在742次增強迭代時停止,而另一次運行多次。

LightGBM使用自定義MSELightGBM通過定製丟失進行調整,並使用MSE進行早期停止調整

僅在不改變驗證損失的情況下定製訓練損失會損害模型性能。 只有自定義訓練損失的模型比其他情況增加了更多輪次(1848)。 如果我們仔細觀察,這個模型的訓練損失非常低(0.013)並且在訓練集上非常過度擬合。 每個梯度增強迭代使用訓練誤差作為目標變數來創建新樹,但僅當驗證數據的損失開始增加時,增強停止。 當模型開始過度擬合時,驗證損失通常開始增加,這是停止構建更多樹木的信號。 在這種情況下,由於驗證和培訓損失彼此不一致,因此模型似乎沒有「得到消息」而導致過度擬合。 這個配置只是為了完整而包含在內,並不是人們在實踐中應該使用的。

LightGBM具有經過調整的提前停止輪次,MSELightGBM訓練定製訓練損失,並通過定製驗證損失調整提前停止輪次

最終模型使用自定義訓練和驗證損失。 它通過相對較少的增強迭代次數給出最佳的非對稱MSE分數。 損失與我們關心的一致!

讓我們仔細看看剩餘直方圖以獲得更多細節。

不同模型預測的殘差直方圖。

注意,使用LightGBM(即使有默認的超參數),與隨機森林模型相比,預測性能得到了改善。帶有自定義驗證損失的最終模型似乎在直方圖的右側做出了更多的預測,即實際值大於預測值。這是由於非對稱自定義損失函數的緣故。使用殘差的核密度圖可以更好地顯示殘差的右移。

LightGBM模型與對稱評價和非對稱評價的比較


總結

所有的模型都有誤差,但是許多業務問題並不能平等地對待低估和高估。有時,我們有意地希望我們的模型將誤差偏向某個方向,這取決於哪些誤差代價更高。因此,我們不應該局限於普通ML庫中的「現成的」對稱損失函數。

LightGBM提供了一個簡單的界面來合併自定義的訓練和驗證丟失功能。在適當的時候,我們應該利用這個功能來做出更好的預測。同時,您不應該立即直接使用自定義損失函數。最好採用精益的、迭代的方法,首先從一個簡單的基線模型開始,比如一個隨機森林。在下一次迭代中,您可以採用像LightGBM這樣更複雜的模型,並進行超參數優化。只有在這些基線穩定下來之後,才有必要繼續定製驗證和訓練損失函數。

希望這有用!


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 AI研習社 的精彩文章:

如何理解 NVIDIA新GPU 架構 Turing的Tensor Core?
你下周該看的人工智慧視頻全在這了,AI研習社下周直播預告

TAG:AI研習社 |