本文爲轉載,做者:Microstrong0305 來源:CSDN 原文:https://blog.csdn.net/program_developer/article/details/80737724git
1. Dropout簡介github
1.1 Dropout出現的緣由算法
在機器學習的模型中,若是模型的參數太多,而訓練樣本又太少,訓練出來的模型很容易產生過擬合的現象。在訓練神經網絡的時候常常會遇到過擬合的問題,過擬合具體表如今:模型在訓練數據上損失函數較小,預測準確率較高;可是在測試數據上損失函數比較大,預測準確率較低。網絡
過擬合是不少機器學習的通病。若是模型過擬合,那麼獲得的模型幾乎不能用。爲了解決過擬合問題,通常會採用模型集成的方法,即訓練多個模型進行組合。此時,訓練模型費時就成爲一個很大的問題,不只訓練多個模型費時,測試多個模型也是很費時。dom
綜上所述,訓練深度神經網絡的時候,老是會遇到兩大缺點:機器學習
(1)容易過擬合函數
(2)費時源碼分析
Dropout能夠比較有效的緩解過擬合的發生,在必定程度上達到正則化的效果。性能
1.2 什麼是Dropout學習
在2012年,Hinton在其論文《Improving neural networks by preventing co-adaptation of feature detectors》中提出Dropout。當一個複雜的前饋神經網絡被訓練在小的數據集時,容易形成過擬合。爲了防止過擬合,能夠經過阻止特徵檢測器的共同做用來提升神經網絡的性能。
在2012年,Alex、Hinton在其論文《ImageNet Classification with Deep Convolutional Neural Networks》中用到了Dropout算法,用於防止過擬合。而且,這篇論文提到的AlexNet網絡模型引爆了神經網絡應用熱潮,並贏得了2012年圖像識別大賽冠軍,使得CNN成爲圖像分類上的核心算法模型。
隨後,又有一些關於Dropout的文章《Dropout:A Simple Way to Prevent Neural Networks from Overfitting》、《Improving Neural Networks with Dropout》、《Dropout as data augmentation》。
從上面的論文中,咱們能感覺到Dropout在深度學習中的重要性。那麼,到底什麼是Dropout呢?
Dropout能夠做爲訓練深度神經網絡的一種trick供選擇。在每一個訓練批次中,經過忽略一半的特徵檢測器(讓一半的隱層節點值爲0),能夠明顯地減小過擬合現象。這種方式能夠減小特徵檢測器(隱層節點)間的相互做用,檢測器相互做用是指某些檢測器依賴其餘檢測器才能發揮做用。
Dropout說的簡單一點就是:咱們在前向傳播的時候,讓某個神經元的激活值以必定的機率p中止工做,這樣可使模型泛化性更強,由於它不會太依賴某些局部的特徵,如圖1所示。
圖1:使用Dropout的神經網絡模型 2. Dropout工做流程及使用
2.1 Dropout具體工做流程
假設咱們要訓練這樣一個神經網絡,如圖2所示。
圖2:標準的神經網絡
輸入是x輸出是y,正常的流程是:咱們首先把x經過網絡前向傳播,而後把偏差反向傳播以決定如何更新參數讓網絡進行學習。使用Dropout以後,過程變成以下:
(1)首先隨機(臨時)刪掉網絡中一半的隱藏神經元,輸入輸出神經元保持不變(圖3中虛線爲部分臨時被刪除的神經元)
圖3:部分臨時被刪除的神經元
(2) 而後把輸入x經過修改後的網絡前向傳播,而後把獲得的損失結果經過修改的網絡反向傳播。一小批訓練樣本執行完這個過程後,在沒有被刪除的神經元上按照隨機梯度降低法更新對應的參數(w,b)。
(3)而後繼續重複這一過程:
. 恢復被刪掉的神經元(此時被刪除的神經元保持原樣,而沒有被刪除的神經元已經有所更新) . 從隱藏層神經元中隨機選擇一個一半大小的子集臨時刪除掉(備份被刪除神經元的參數)。 . 對一小批訓練樣本,先前向傳播而後反向傳播損失並根據隨機梯度降低法更新參數(w,b) (沒有被刪除的那一部分參數獲得更新,刪除的神經元參數保持被刪除前的結果)。 不斷重複這一過程。
2.2 Dropout在神經網絡中的使用
Dropout的具體工做流程上面已經詳細的介紹過了,可是具體怎麼讓某些神經元以必定的機率中止工做(就是被刪除掉)?代碼層面如何實現呢?
下面,咱們具體講解一下Dropout代碼層面的一些公式推導及代碼實現思路。
(1)在訓練模型階段
無可避免的,在訓練網絡的每一個單元都要添加一道機率流程。
圖4:標準網絡和帶有Dropout網絡的比較
對應的公式變化以下:
. 沒有Dropout的網絡計算公式: . 採用Dropout的網絡計算公式:
上面公式中Bernoulli函數是爲了生成機率r向量,也就是隨機生成一個0、1的向量。
代碼層面實現讓某個神經元以機率p中止工做,其實就是讓它的激活函數值以機率p變爲0。好比咱們某一層網絡神經元的個數爲1000個,其激活函數輸出值爲y一、y二、y三、......、y1000,咱們dropout比率選擇0.4,那麼這一層神經元通過dropout後,1000個神經元中會有大約400個的值被置爲0。
注意: 通過上面屏蔽掉某些神經元,使其激活值爲0之後,咱們還須要對向量y1……y1000進行縮放,也就是乘以1/(1-p)。若是你在訓練的時候,通過置0後,沒有對y1……y1000進行縮放(rescale),那麼在測試的時候,就須要對權重進行縮放,操做以下。
(2)在測試模型階段
預測模型的時候,每個神經單元的權重參數要乘以機率p。
圖5:預測模型時Dropout的操做 測試階段Dropout公式:
3. 爲何說Dropout能夠解決過擬合?
(1)取平均的做用: 先回到標準的模型即沒有dropout,咱們用相同的訓練數據去訓練5個不一樣的神經網絡,通常會獲得5個不一樣的結果,此時咱們能夠採用 「5個結果取均值」或者「多數取勝的投票策略」去決定最終結果。例如3個網絡判斷結果爲數字9,那麼頗有可能真正的結果就是數字9,其它兩個網絡給出了錯誤結果。這種「綜合起來取平均」的策略一般能夠有效防止過擬合問題。由於不一樣的網絡可能產生不一樣的過擬合,取平均則有可能讓一些「相反的」擬合互相抵消。dropout掉不一樣的隱藏神經元就相似在訓練不一樣的網絡,隨機刪掉一半隱藏神經元致使網絡結構已經不一樣,整個dropout過程就至關於對不少個不一樣的神經網絡取平均。而不一樣的網絡產生不一樣的過擬合,一些互爲「反向」的擬合相互抵消就能夠達到總體上減小過擬合。
(2)減小神經元之間複雜的共適應關係: 由於dropout程序致使兩個神經元不必定每次都在一個dropout網絡中出現。這樣權值的更新再也不依賴於有固定關係的隱含節點的共同做用,阻止了某些特徵僅僅在其它特定特徵下才有效果的狀況 。迫使網絡去學習更加魯棒的特徵 ,這些特徵在其它的神經元的隨機子集中也存在。換句話說假如咱們的神經網絡是在作出某種預測,它不該該對一些特定的線索片斷太過敏感,即便丟失特定的線索,它也應該能夠從衆多其它線索中學習一些共同的特徵。從這個角度看dropout就有點像L1,L2正則,減小權重使得網絡對丟失特定神經元鏈接的魯棒性提升。
(3)Dropout相似於性別在生物進化中的角色:物種爲了生存每每會傾向於適應這種環境,環境突變則會致使物種難以作出及時反應,性別的出現能夠繁衍出適應新環境的變種,有效的阻止過擬合,即避免環境改變時物種可能面臨的滅絕。
4. Dropout在Keras中的源碼分析
下面,咱們來分析Keras中Dropout實現源碼。
Keras開源項目GitHub地址爲:
https://github.com/fchollet/keras/tree/master/keras
其中Dropout函數代碼實現所在的文件地址:
https://github.com/fchollet/keras/blob/master/keras/backend/theano_backend.py
Dropout實現函數以下:
圖6:Keras中實現Dropout功能
咱們對keras中Dropout實現函數作一些修改,讓dropout函數能夠單獨運行。
# coding:utf-8 import numpy as np # dropout函數的實現 def dropout(x, level): if level < 0. or level >= 1: #level是機率值,必須在0~1之間 raise ValueError('Dropout level must be in interval [0, 1[.') retain_prob = 1. - level # 咱們經過binomial函數,生成與x同樣的維數向量。binomial函數就像拋硬幣同樣,咱們能夠把每一個神經元當作拋硬幣同樣 # 硬幣 正面的機率爲p,n表示每一個神經元試驗的次數 # 由於咱們每一個神經元只須要拋一次就能夠了因此n=1,size參數是咱們有多少個硬幣。 random_tensor = np.random.binomial(n=1, p=retain_prob, size=x.shape) #即將生成一個0、1分佈的向量,0表示這個神經元被屏蔽,不工做了,也就是dropout了 print(random_tensor) x *= random_tensor print(x) x /= retain_prob return x #對dropout的測試,你們能夠跑一下上面的函數,瞭解一個輸入x向量,通過dropout的結果 x=np.asarray([1,2,3,4,5,6,7,8,9,10],dtype=np.float32) dropout(x,0.4) 函數中,x是本層網絡的激活值。Level就是dropout就是每一個神經元要被丟棄的機率。
注意: Keras中Dropout的實現,是屏蔽掉某些神經元,使其激活值爲0之後,對激活值向量x1……x1000進行放大,也就是乘以1/(1-p)。
思考:上面咱們介紹了兩種方法進行Dropout的縮放,那麼Dropout爲何須要進行縮放呢?
由於咱們訓練的時候會隨機的丟棄一些神經元,可是預測的時候就沒辦法隨機丟棄了。若是丟棄一些神經元,這會帶來結果不穩定的問題,也就是給定一個測試數據,有時候輸出a有時候輸出b,結果不穩定,這是實際系統不能接受的,用戶可能認爲模型預測不許。那麼一種」補償「的方案就是每一個神經元的權重都乘以一個p,這樣在「整體上」使得測試數據和訓練數據是大體同樣的。好比一個神經元的輸出是x,那麼在訓練的時候它有p的機率參與訓練,(1-p)的機率丟棄,那麼它輸出的指望是px+(1-p)0=px。所以測試的時候把這個神經元的權重乘以p能夠獲得一樣的指望。
總結:
當前Dropout被大量利用於全鏈接網絡,並且通常認爲設置爲0.5或者0.3,而在卷積網絡隱藏層中因爲卷積自身的稀疏化以及稀疏化的ReLu函數的大量使用等緣由,Dropout策略在卷積網絡隱藏層中使用較少。整體而言,Dropout是一個超參,須要根據具體的網絡、具體的應用領域進行嘗試。