2
| 本文作者: AI研習(xí)社-譯站 | 2018-06-04 10:19 |
雷鋒網(wǎng)按:本文為雷鋒字幕組編譯的技術(shù)博客,原文 Custom Loss functions for Deep Learning: Predicting Home Values with Keras for R ,作者 Ben Weber 。
翻譯 | 宥佑 林驍 整理 | 凡江

我最近在讀「深度學(xué)習(xí)與 R」,R 對于深度學(xué)習(xí)的支持著實(shí)讓我驚艷!
書中其中一個(gè)應(yīng)用例子就是用于預(yù)測波士頓的房價(jià),這是一個(gè)有趣的問題,因?yàn)榉课莸膬r(jià)值變化非常大。這是一個(gè)機(jī)器學(xué)習(xí)的問題,可能最適用于經(jīng)典方法,如 XGBoost,因?yàn)閿?shù)據(jù)集是結(jié)構(gòu)化的而不是感知的。然而,這也是一個(gè)數(shù)據(jù)集,深度學(xué)習(xí)提供了一個(gè)非常有用的功能,就是編寫一個(gè)新的損失函數(shù),有可能提高預(yù)測模型的性能。這篇文章的目的是來展示深度學(xué)習(xí)如何通過使用自定義損失函數(shù)來改善淺層學(xué)習(xí)問題。
我在處理財(cái)務(wù)數(shù)據(jù)時(shí)遇到過幾次的問題之一是,經(jīng)常需要構(gòu)建預(yù)測模型,其中輸出可以具有各種不同的值,且在不同的數(shù)量級上。例如,預(yù)測房價(jià)時(shí)可能會(huì)發(fā)生這種情況,其中一些住房的價(jià)值為 10 萬美元,其他房屋的價(jià)值為 1000 萬美元。如果您在這些問題(如線性回歸或隨機(jī)森林)中使用標(biāo)準(zhǔn)機(jī)器學(xué)習(xí)方法,那么通常該模型會(huì)過擬合具有最高值的樣本,以便減少諸如平均絕對誤差等度量。然而,你可能真正想要的是用相似的權(quán)重來處理樣本,并使用錯(cuò)誤度量如相對誤差來降低擬合具有最大值的樣本的重要性。

實(shí)際上,你可以在 R 中使用非線性最小二乘法(nls)等軟件包明確地做到這一點(diǎn)。上面的代碼示例演示了如何使用內(nèi)置優(yōu)化器來構(gòu)建線性回歸模型,該優(yōu)化器將使用大標(biāo)簽值對樣本進(jìn)行超重,并介紹如何對預(yù)測值和標(biāo)簽執(zhí)行對數(shù)轉(zhuǎn)換的 nls 方法,這將會(huì)給樣品比較相等的重量。第二種方法的問題是,你必須明確說明如何使用模型中的特征,從而產(chǎn)生特征工程問題。這種方法的另一個(gè)問題是,它不能直接應(yīng)用于其他算法,如隨機(jī)森林,而無需編寫自己的似然函數(shù)和優(yōu)化器。這是針對特定的場景,您希望將錯(cuò)誤術(shù)語放在日志轉(zhuǎn)換之外,而不是只需將日志轉(zhuǎn)換應(yīng)用于標(biāo)簽和所有輸入變量的場景。
深度學(xué)習(xí)提供了一個(gè)優(yōu)雅的解決方案來處理這類問題,替代了編寫自定義似然函數(shù)和優(yōu)化器,您可以探索不同的內(nèi)置和自定義損失函數(shù),這些函數(shù)可以與提供的不同優(yōu)化器一起使用。本文將展示如何在使用 Keras 時(shí)編寫 R 中的自定義損失函數(shù),并展示如何使用不同的方法對不同類型的數(shù)據(jù)集有利。
下面的圖片是我將要用做文章預(yù)覽封面的,它顯示了根據(jù)波士頓房價(jià)數(shù)據(jù)集訓(xùn)練的四種不同 Keras 模型的培訓(xùn)歷史。每個(gè)模型使用不同的損失函數(shù),但是在相同的性能指標(biāo)上評估,即平均絕對誤差。對于原始數(shù)據(jù)集,自定義損失函數(shù)不會(huì)提高模型的性能,但基于修改后的數(shù)據(jù)集,結(jié)果更喜人。

對原始房價(jià)數(shù)據(jù)集執(zhí)行 4 項(xiàng)損失函數(shù)。所有模型均使用 MAE 作為性能指標(biāo)。
用深度學(xué)習(xí)改進(jìn)淺層問題
深度學(xué)習(xí)的一個(gè)重要特征是它可以應(yīng)用于感知數(shù)據(jù)的深層問題,(如音頻和視頻)以及結(jié)構(gòu)化數(shù)據(jù)的淺層問題。對于淺層學(xué)習(xí)(經(jīng)典 ML)問題,你通常可以通過使用自定義損耗函數(shù)來查看淺層方法的改進(jìn),從而提供有用的信號。
然而,并非所有淺層問題都可以從深度學(xué)習(xí)中受益。我發(fā)現(xiàn)自定義損失函數(shù)在建立需要為不同數(shù)量級的數(shù)據(jù)創(chuàng)建預(yù)測的回歸模型時(shí)非常有用。例如,在一個(gè)價(jià)值可以顯著變化的地區(qū)預(yù)測房價(jià)。為了說明實(shí)踐中是如何工作的,我們將使用由 Keras 提供的波士頓房屋數(shù)據(jù)集:
數(shù)據(jù)集-Keras 文件
數(shù)據(jù)集來自 IMDB 的 25000 條電影評論,用標(biāo)簽(正面或負(fù)面)對其進(jìn)行標(biāo)記。評論已經(jīng)被處理過。
該數(shù)據(jù)集包括 20 世紀(jì) 70 年代波士頓郊區(qū)的房價(jià)。每個(gè)記錄有 13 個(gè)屬性對家庭進(jìn)行描述,訓(xùn)練數(shù)據(jù)集中有 404 條記錄,測試數(shù)據(jù)集中有 102 條記錄。在 R 中,可以按如下方式加載數(shù)據(jù)集: dataset_boston_housing()。價(jià)格分布直方圖顯示在下面的左邊,其中價(jià)格分布從 5 千美元到五萬美元不等。原始數(shù)據(jù)集中不同的價(jià)格區(qū)間有相似的需求,因此自定義損失函數(shù)可能對擬合該數(shù)據(jù)太大用處。右側(cè)的直方圖顯示有受益于使用自定義丟失的標(biāo)簽轉(zhuǎn)換。右側(cè)的直方圖展示了經(jīng)過標(biāo)簽轉(zhuǎn)換之后的直方圖,將損失函數(shù)運(yùn)用到這些標(biāo)簽上將會(huì)獲得更好地效果。

波士頓數(shù)據(jù)集包括原始價(jià)格和轉(zhuǎn)換后的價(jià)格
對于如何將價(jià)格進(jìn)行轉(zhuǎn)換,我將標(biāo)簽轉(zhuǎn)換成絕對價(jià)格,將結(jié)果平方,然后除以大的因子。這產(chǎn)生了一個(gè)數(shù)據(jù)集,其中最高價(jià)格和最低價(jià)格之間的差異不是 10 倍而是 100 倍。我們現(xiàn)在有一個(gè)可以從使用自定義損失函數(shù)中獲益的預(yù)測問題。生成這些圖的 R 代碼如下所示。

Keras 中的損失函數(shù)
Keras中包含許多用于訓(xùn)練深度學(xué)習(xí)模型的有用損失函數(shù)。例如: mean_absolute_error() 就適用于數(shù)值在某種程度上相等的數(shù)據(jù)集。還有一些函數(shù)可能更適合轉(zhuǎn)換后的住房數(shù)據(jù),例如:mean_squared_logarithmic_error() 。 下面是由R為Keras提供的損失函數(shù)接口:

損失函數(shù)。R 是指 Python 當(dāng)中的函數(shù),為了真正理解這些函數(shù)是如何工作的,我們需要先了解到 Python 的損失函數(shù)代碼。我們要研究的第一個(gè)損失函數(shù)是下面定義的均方誤差。該函數(shù)計(jì)算預(yù)測值與實(shí)際值之間的差值,然后將結(jié)果平方 (使所有的值均為正),最后計(jì)算平均值。注意,該函數(shù)使用張量進(jìn)行計(jì)算,而不是 Python 原語。當(dāng)在 R 中定義自定義損失函數(shù)時(shí)將使用相同的方法。

我們將探討的下一個(gè)內(nèi)置損失函數(shù)是根據(jù)預(yù)測值與目標(biāo)值的之間自然對數(shù)的差來計(jì)算誤差。它在此處定義并在下面寫出。該函數(shù)使用 clip 操作來確保負(fù)值不會(huì)傳遞到日志函數(shù),并且向 clip 后的結(jié)果+1,這可確保所有對數(shù)轉(zhuǎn)換的輸入都具有非負(fù)數(shù)結(jié)果。這個(gè)函數(shù)與我們在 R 中定義的函數(shù)類似。

我們將探討的兩個(gè)自定義損失函數(shù)在下面的 R 代碼段中定義。第一個(gè)函數(shù),mean log absolute error(MLAE),計(jì)算預(yù)測值和實(shí)際值的對數(shù)變換之間的差值,然后對計(jì)算結(jié)果進(jìn)行平均。與上面的內(nèi)置函數(shù)不同,這種方法不能糾正錯(cuò)誤。與上述對數(shù)函數(shù)的另一個(gè)區(qū)別是,該函數(shù)將顯式比例的因子應(yīng)用到數(shù)據(jù)當(dāng)中,將房屋價(jià)格轉(zhuǎn)換回原始值(5,000 至 50,0000)而不是(5,50)。這是有用的,因?yàn)樗鼫p少了+1 對預(yù)測值和實(shí)際值的影響。

像 Python 函數(shù)一樣,R 的自定義損失函數(shù)需要對張量(而不是 R 原語)進(jìn)行操作。為了執(zhí)行這些操作,需要使用 backend() 獲取對后端的引用。在我的系統(tǒng)配置中,這返回了對 Tensorflow 的引用。
第二個(gè)函數(shù)計(jì)算日志錯(cuò)誤的平方,與內(nèi)置函數(shù)類似。主要區(qū)別在于我使用的是激活函數(shù) relu 而不是 clip,并且對于特定的住房數(shù)據(jù)集,我進(jìn)行價(jià)格縮放操作。
評估損失函數(shù)
我們現(xiàn)在有四種不同的損失函數(shù),我們要用原始數(shù)據(jù)集和經(jīng)過改造的住房數(shù)據(jù)集來對四種不同的損失函數(shù)的性能進(jìn)行評估。本節(jié)將介紹如何設(shè)置 Keras,加載數(shù)據(jù),編譯模型,擬合模型和評估性能。本節(jié)的完整代碼可在 Github 上找到。
首先,我們需要建立我們的深度學(xué)習(xí)環(huán)境。這可以通過 Keras 包和 install_keras 函數(shù)完成。

安裝完成后,我們將加載數(shù)據(jù)集并應(yīng)用我們的轉(zhuǎn)換來改變住房價(jià)格。最后兩項(xiàng)操作可以注釋掉,使用原來的房價(jià)。

接下來,我們將創(chuàng)建一個(gè) Keras 模型來預(yù)測房價(jià)。我使用了「Deep Learning with R」中示例的網(wǎng)絡(luò)結(jié)構(gòu)。該網(wǎng)絡(luò)包括兩層全連接層及其激勵(lì)函數(shù) relu,以及一個(gè)沒有變換的輸出層。

為了編譯模型,我們需要指定優(yōu)化器,損失函數(shù)和度量。我們將對所有不同的損失函數(shù)使用相同的度量和優(yōu)化器。下面的代碼定義了損失函數(shù)列表,對于第一次迭代,模型使用均方誤差。

最后一步是擬合模型,然后評估性能。我使用了 100 個(gè)批次并且每個(gè)批次大小為 5,按照 20%的比例將分割出來的數(shù)據(jù)作為驗(yàn)證集。在模型訓(xùn)練完訓(xùn)練集之后,模型的性能通過測試數(shù)據(jù)集上的平均絕對誤差來評估。

我用不同的損失函數(shù)訓(xùn)練了四種不同的模型,并將這種方法應(yīng)用于原始房價(jià)和轉(zhuǎn)換后的房價(jià)當(dāng)中。以下顯示了所有這些不同組合的結(jié)果。

房價(jià)數(shù)據(jù)集損失函數(shù)的表現(xiàn)
在原始數(shù)據(jù)集上,在損失函數(shù)中應(yīng)用對數(shù)變換實(shí)際上增加了模型的誤差。由于數(shù)據(jù)在一個(gè)數(shù)量級內(nèi)存在一定的正態(tài)分布,這并不令人驚訝。對于變換的數(shù)據(jù)集,平方對數(shù)誤差方法優(yōu)于均方誤差損失函數(shù)。這表明如果您的數(shù)據(jù)集不適合內(nèi)置的損失函數(shù),自定義損失函數(shù)可能值得探索。
下面顯示了轉(zhuǎn)換數(shù)據(jù)集上四種不同損失函數(shù)的模型訓(xùn)練歷史。每個(gè)模型使用相同的錯(cuò)誤度量(MAE),但是具有不同的損失函數(shù)。一個(gè)令人驚訝的結(jié)果是,對于所有的損失函數(shù)來說,應(yīng)用日志轉(zhuǎn)換的方法驗(yàn)證錯(cuò)誤率要高得多。

在轉(zhuǎn)換后的房價(jià)數(shù)據(jù)集上對 4 種損失函數(shù)測試各自的性能。所有模型都使用 MAE 作為性能指標(biāo)。
深度學(xué)習(xí)可以成為淺層學(xué)習(xí)問題的有用工具,因?yàn)槟梢远x自定義的損失函數(shù),這些函數(shù)可能會(huì)顯著提高模型的性能。這不適用于所有問題,但如果預(yù)測問題不能很好地映射到標(biāo)準(zhǔn)損失函數(shù),則可能會(huì)有用。

雷鋒網(wǎng)雷鋒網(wǎng)
雷峰網(wǎng)原創(chuàng)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。