九、機(jī)器學(xué)習(xí)基礎(chǔ)Ⅳ:過(guò)擬合和欠擬合


文章代碼來(lái)源:《deep learning on keras》,非常好的一本書,大家如果英語(yǔ)好,推薦直接閱讀該書,如果時(shí)間不夠,可以看看此系列文章,文章為我自己翻譯的內(nèi)容加上自己的一些思考,水平有限,多有不足,請(qǐng)多指正,翻譯版權(quán)所有,若有轉(zhuǎn)載,請(qǐng)先聯(lián)系本人。
個(gè)人方向?yàn)閿?shù)值計(jì)算,日后會(huì)向深度學(xué)習(xí)和計(jì)算問(wèn)題的融合方面靠近,若有相近專業(yè)人士,歡迎聯(lián)系。


系列文章:
一、搭建屬于你的第一個(gè)神經(jīng)網(wǎng)絡(luò)
二、訓(xùn)練完的網(wǎng)絡(luò)去哪里找
三、【keras實(shí)戰(zhàn)】波士頓房?jī)r(jià)預(yù)測(cè)
四、keras的function API
五、keras callbacks使用
六、機(jī)器學(xué)習(xí)基礎(chǔ)Ⅰ:機(jī)器學(xué)習(xí)的四個(gè)標(biāo)簽
七、機(jī)器學(xué)習(xí)基礎(chǔ)Ⅱ:評(píng)估機(jī)器學(xué)習(xí)模型
八、機(jī)器學(xué)習(xí)基礎(chǔ)Ⅲ:數(shù)據(jù)預(yù)處理、特征工程和特征學(xué)習(xí)
九、機(jī)器學(xué)習(xí)基礎(chǔ)Ⅳ:過(guò)擬合和欠擬合
十、機(jī)器學(xué)習(xí)基礎(chǔ)Ⅴ:機(jī)器學(xué)習(xí)的一般流程十一、計(jì)算機(jī)視覺(jué)中的深度學(xué)習(xí):卷積神經(jīng)網(wǎng)絡(luò)介紹
十二、計(jì)算機(jī)視覺(jué)中的深度學(xué)習(xí):從零開始訓(xùn)練卷積網(wǎng)絡(luò)
十三、計(jì)算機(jī)視覺(jué)中的深度學(xué)習(xí):使用預(yù)訓(xùn)練網(wǎng)絡(luò)
十四、計(jì)算機(jī)視覺(jué)中的神經(jīng)網(wǎng)絡(luò):可視化卷積網(wǎng)絡(luò)所學(xué)到的東西


在之前的例子中,我們注意到我們模型的表現(xiàn)都會(huì)在極少的訓(xùn)練批次后達(dá)到峰值,此后開始下降,即我們的模型會(huì)很快過(guò)擬合到訓(xùn)練數(shù)據(jù)。過(guò)擬合發(fā)生在每一個(gè)單獨(dú)的機(jī)器學(xué)習(xí)問(wèn)題中。學(xué)會(huì)如何解決過(guò)擬合問(wèn)題對(duì)于掌控機(jī)器學(xué)習(xí)尤為重要。

在機(jī)器學(xué)習(xí)中最基礎(chǔ)的主題就是優(yōu)化和泛化的張力?!皟?yōu)化”代表著通過(guò)調(diào)整模型來(lái)在訓(xùn)練數(shù)據(jù)上表現(xiàn)最好,“泛化”則代表模型在未見過(guò)的數(shù)據(jù)上的表現(xiàn)。這場(chǎng)游戲的目標(biāo)就是取得好的泛化,當(dāng)然,你控制不了泛化,你只能基于訓(xùn)練數(shù)據(jù)調(diào)節(jié)模型。

在訓(xùn)練的一開始,優(yōu)化和泛化是相關(guān)的:你在訓(xùn)練數(shù)據(jù)中的損失越低,你在測(cè)試函數(shù)中的損失也就越低。當(dāng)這種情況發(fā)生時(shí),你的模型就叫做欠擬合:這里還有可進(jìn)步的空間;網(wǎng)絡(luò)還沒(méi)有將訓(xùn)練數(shù)據(jù)中的相關(guān)的數(shù)據(jù)建模完全。但是在訓(xùn)練數(shù)據(jù)進(jìn)行相當(dāng)次數(shù)的迭代以后,泛化就停止上升了,驗(yàn)證指標(biāo)就停滯并開始下降:模型開始過(guò)擬合,比如說(shuō),它可能會(huì)開始學(xué)習(xí)一些對(duì)于訓(xùn)練數(shù)據(jù)很特別的特征,但是對(duì)于新來(lái)的數(shù)據(jù)可能完全不相關(guān)。

為了防止模型被訓(xùn)練數(shù)據(jù)中不相關(guān)的特征誤導(dǎo),最好地方法當(dāng)然是弄更多的訓(xùn)練數(shù)據(jù)。一個(gè)模型用更多的數(shù)據(jù)去喂理所當(dāng)然會(huì)有更好的泛化性。當(dāng)增加數(shù)據(jù)行不通的時(shí)候,最好地方法是調(diào)節(jié)你模型存儲(chǔ)的信息的質(zhì)量,或者對(duì)于什么樣的信息是允許被存儲(chǔ)的加以限制。如果一個(gè)網(wǎng)絡(luò)只能記住很少的特征,這個(gè)優(yōu)化進(jìn)程則主要集中于最突出的特征,這將會(huì)對(duì)于提高泛化性有很大的幫助。

用來(lái)解決過(guò)擬合的方法我們叫做正則化,讓我們回顧一下一些常用的正則化方法并應(yīng)用這些方法來(lái)提高之前章節(jié)提的電影分類模型的性能。

狙擊過(guò)擬合

減少網(wǎng)絡(luò)大小

最簡(jiǎn)單的預(yù)防過(guò)擬合的方法就是減少模型的大小,例如模型中可學(xué)習(xí)的參數(shù)數(shù)量(這有層數(shù)數(shù)量和每一層的單元數(shù)所決定)在深度學(xué)習(xí)中,模型中可學(xué)習(xí)參數(shù)的數(shù)量被稱為模型的“容量”。直觀來(lái)講,一個(gè)有更多參數(shù)的模型將會(huì)有更多的“記憶容量”,因此這就很容易學(xué)習(xí)到一個(gè)像字典一樣的映射關(guān)系,這樣的映射關(guān)系沒(méi)有任何的泛化能力。例如,一個(gè)有500000二進(jìn)制參數(shù)的模型能夠很容易的學(xué)習(xí)到MNIST訓(xùn)練集每一個(gè)數(shù)字的類別:我們對(duì)于每一個(gè)數(shù)字只需要一個(gè)二進(jìn)制參數(shù)。這樣一個(gè)模型對(duì)于分類i性能的數(shù)字樣本沒(méi)什么用。永遠(yuǎn)記住:深度學(xué)習(xí)模型趨向于擬合訓(xùn)練集,但是真正的挑戰(zhàn)在于泛化,而不是擬合。

換句話來(lái)說(shuō),如果網(wǎng)絡(luò)被記憶資源所限制,它就無(wú)法學(xué)習(xí)到那樣的映射了,因此為了最小化損失,它就必須專注于學(xué)習(xí)壓縮表示,預(yù)測(cè)的效果就取決于我們的目標(biāo)了。同時(shí),記住你應(yīng)該使用有足夠參數(shù)的模型使得它不會(huì)欠擬合:你的模型不應(yīng)渴望記憶資源,在容量太大和容量不足之間需要尋找平衡。

不幸的是,沒(méi)有什么有魔力的公式能夠決定層所需的正確數(shù)量,以及每一層的正確大小。你必須評(píng)估一系列不同的結(jié)構(gòu)(在你的驗(yàn)證集上而不是測(cè)試集上)來(lái)找出你的數(shù)據(jù)的正確模型大小。一般的找到合適大小的流程是從一些相關(guān)的比較少的層數(shù)和參數(shù)開始,然后開始提高層的大小并增加新的層知道你看到驗(yàn)證集的損失開始下降為止。
讓我們來(lái)在電影評(píng)論分類網(wǎng)絡(luò)中試一下。我們?cè)季W(wǎng)絡(luò)如下所示:

from keras import models
from keras import layers
model = models.Sequential()
model.add(layers.Dense(16, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(16, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))

讓我們用一個(gè)更小的網(wǎng)絡(luò)來(lái)替換它

model = models.Sequential()
model.add(layers.Dense(4, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(4, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))

這里比較了原始網(wǎng)絡(luò)和更小網(wǎng)絡(luò)中驗(yàn)證集的損失。


smaller

可以觀察到小的網(wǎng)絡(luò)過(guò)擬合遲于原始的,且其在過(guò)擬合后表現(xiàn)變差的比較慢。
接下來(lái)我們給模型加很多容量使得超過(guò)問(wèn)題所需:

model = models.Sequential()
model.add(layers.Dense(512, activation='relu', input_shape=(10000,)))
model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
bigger

這個(gè)大一點(diǎn)的網(wǎng)絡(luò)幾乎是在一開始就已經(jīng)過(guò)擬合了,在一個(gè)批次以后過(guò)擬合就很嚴(yán)重了。其驗(yàn)證集的損失也充滿了噪聲。同時(shí),給出兩種網(wǎng)絡(luò)的訓(xùn)練誤差:


bigger train loss

如你所見,大一點(diǎn)的網(wǎng)絡(luò)訓(xùn)練損失很快就到了0.網(wǎng)絡(luò)的容量越大,對(duì)訓(xùn)練數(shù)據(jù)建模就越快,但它就越容易過(guò)擬合。

增加正則化權(quán)重

或許你很熟悉奧卡姆剃刀原則:對(duì)一個(gè)事情給定兩個(gè)解釋,“簡(jiǎn)單的”那個(gè)看上去更像是對(duì)的,其做了最少的假設(shè)。這也被應(yīng)用到了神經(jīng)網(wǎng)絡(luò)上了:給定一些訓(xùn)練數(shù)據(jù)和網(wǎng)絡(luò)結(jié)構(gòu),有大量的權(quán)重值可以解釋數(shù)據(jù),簡(jiǎn)單的模型會(huì)有更小的概率過(guò)擬合。
一個(gè)“簡(jiǎn)單的模型”在這里就是一個(gè)參數(shù)值有更少的熵的模型,(或者說(shuō)是參數(shù)總數(shù)更少的)。因此一個(gè)常用減輕過(guò)擬合的方法是采取小的值,讓權(quán)重值更加正則。這就叫做權(quán)重正則化,這通過(guò)在損失函數(shù)加一個(gè)花費(fèi)來(lái)做到的,這花費(fèi)可以有以下兩種類型:

  • L1正則化,花費(fèi)取決于權(quán)重系數(shù)的絕對(duì)值。
  • L2正則化,花費(fèi)取決于權(quán)重系數(shù)的平方。L2正則化在神經(jīng)網(wǎng)絡(luò)中也稱為權(quán)重衰減。不要讓不同的名字迷惑到你:權(quán)重衰減在數(shù)學(xué)形式上和L2正則化是一回事。

在keras里面,權(quán)重正則化通過(guò)權(quán)重正則化實(shí)例加進(jìn)來(lái)作為關(guān)鍵詞參數(shù)。讓我們?cè)陔娪霸u(píng)論分類網(wǎng)絡(luò)中加入L2去那種正則化。

from keras import regularizers
model = models.Sequential()
model.add(layers.Dense(16, kernel_regularizer=regularizers.l2(0.001),
 activation='relu', input_shape=(10000,)))
model.add(layers.Dense(16, kernel_regularizer=regularizers.l2(0.001),
 activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))

其中l(wèi)2(0.001)意味著圖層的權(quán)重矩陣將會(huì)乘以0.001加入到最終網(wǎng)絡(luò)的損失中。注意乘法只在訓(xùn)練的時(shí)候加進(jìn)去,也就是說(shuō)網(wǎng)絡(luò)的損失在訓(xùn)練的時(shí)候要比測(cè)試的時(shí)候高很多。
這里給出了L2正則化的懲罰:


Effect of L2 weight regularization on validation loss

如你所見,L2正則化以后模型更加耐過(guò)擬合了,盡管每一個(gè)模型都有相同數(shù)量的參數(shù)。
作為l2的替代,你可以看到如下的keras權(quán)重正則化:

from keras import regularizers
# L1 regularization
regularizers.l1(0.001)
# L1 and L2 regularization at the same time
regularizers.l1_l2(l1=0.001, l2=0.001)

添加drop out

dropout在是為了里面是一項(xiàng)最常用的正則化方法,由Hinton和他的學(xué)生在Toronto大學(xué)提出。dropout應(yīng)用到“層”里面,由隨機(jī)"dropping out"層在訓(xùn)練中學(xué)習(xí)到的要輸出的特征。在測(cè)試的時(shí)候,沒(méi)有單元被dropped out,層的輸出值會(huì)按照dropout rate來(lái)縮放,以平衡在測(cè)試時(shí)和訓(xùn)練的時(shí)比有更多的單元。
給定layer_out的shape為(batch_size,features)
在訓(xùn)練的時(shí)候:

# At training time: we drop out 50% of the units in the output
layer_output *= np.randint(0, high=2, size=layer_output.shape)

在測(cè)試時(shí):

# At test time:
layer_output *= 0.5

還有一種方法是在訓(xùn)練的時(shí)候兩個(gè)操作都弄,然后在test 的時(shí)候output就不用變了。

# At training time:
layer_output *= np.randint(0, high=2, size=layer_output.shape)
# Note that we are scaling *up* rather scaling *down* in this case
layer_output /= 0.5

處理過(guò)程如圖所示:


常用dropout法

這樣的方法看起來(lái)似乎有點(diǎn)奇怪和任意。為什么這樣子可以幫助減少過(guò)擬合呢?hinton說(shuō)他是被其它的事情激發(fā)的靈感,通過(guò)銀行里的防欺詐機(jī)器,用他的話來(lái)說(shuō):“我去了我的銀行。出納員不斷地變化, 我問(wèn)他們中的一個(gè)為什么。他說(shuō)他不知道, 但他們經(jīng)常被轉(zhuǎn)移。我想這一定是因?yàn)檫@需要員工之間的合作才能成功詐騙銀行。這讓我意識(shí)到, 在每個(gè)例子上隨機(jī)刪除不同的神經(jīng)元子集, 可以防止陰謀, 從而減少過(guò)度擬合?!?br> 其中的核心思想就是在輸出值引入噪聲來(lái)打破當(dāng)噪聲不存在時(shí)網(wǎng)絡(luò)會(huì)記住的一些不重要的偶然模式。
在keras里面,你能使用dropout層來(lái)直接引入dropout。

model.add(layers.Dropout(0.5))

在之前的IMDB網(wǎng)絡(luò)中加入兩個(gè)dropout層,去看他們對(duì)于減少過(guò)擬合的效果有多好。

model = models.Sequential()
model.add(layers.Dense(16, activation='relu', input_shape=(10000,)))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(16, activation='relu'))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(1, activation='sigmoid'))

畫出結(jié)果:


Effect of dropout on validation loss

我們又一次得到了網(wǎng)絡(luò)的提升。
總結(jié)一下在神經(jīng)網(wǎng)絡(luò)里面防止過(guò)擬合的常用的方法:

  • 更多的訓(xùn)練數(shù)據(jù)
  • 減少網(wǎng)絡(luò)的容量
  • 增加權(quán)重正則化
  • 增加dropout
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容