1. 程式人生 > >深度學習中的dropout

深度學習中的dropout

看過很多關於dropout方面的部落格,但是感覺寫太一般,不能達到我想要的水平,所以決定自己寫一下。

1.dropout解決的問題

深度神經網路的訓練是一件非常困難的事,涉及到很多因素,比如損失函式的非凸性導致的區域性最優值、計算過程中的數值穩定性、訓練過程中的過擬合等。其中,過擬合是很容易發生的現象,也是在訓練DNN中必須要解決的問題。

過擬合

我們先來講一下什麼事“過擬合”。過擬合是指模型訓練到一定程度後,在訓練集上得到的測試誤差遠大於在測試集上得到的誤差,如下圖所示:
過擬合效果示意圖
導致過擬合的直接原因是模型學習了太多噪聲模式,並錯誤的將其視為資料模式;導致過擬合的主要原因有:
1. 訓練資料集太小
2. 模型太複雜
3. 過度訓練

常用的過擬合解決方案

知道了產生過擬合的原因,就可以制定相應的解決方案,一般而言,解決的主要方法有:增加訓練資料量、減少模型的複雜度、新增正則項等。在深度學習中,以上方法都可以使用,但是dropout是一個更加高效、簡單的防止過擬合的方法。

2.dropout

dropout是指在訓練一個大的神經網路的時候,隨機“關閉”一些神經元,即把這些神經元從網路中“抹去”,這相當於在本次訓練中,這些被“抹去”的神經元不參與本次訓練,英文即是“dropout”的意思。如下圖所示:
dropout示意圖
我們看到圖中打叉的神經元就是被“dropout”掉的神經元,和這些個神經元相連線的權重值也一併被“抹去”,不參與本次訓練。不參與本次訓練是說在當前的batch中,不參與訓練,每個batch都會隨機挑選神經元做dropout。

dropout為什麼可以防止過擬合

我們知道“隨機森林”是一種不容易發生過擬合的演算法,其採用的方法是“bagging”,即通過對多個樹的輸出結果加權平均,得出最後的結果。而每棵樹都是在不同的訓練集上、設定不同的引數得到的,因此是一種典型的通過多個不同引數,甚至不同型別的模型來降低方差的一種方法。這種方法對傳統的機器學習演算法、或者小型的NN模型可行,但是當資料量很大、模型很複雜的時候,我們不能訓練多個不同的模型出來做”bagging”,因為深度神經網路的訓練是一個很耗時的過程,需要大量的計算資源和時間。
dropout則為這種思想提供了一種“廉價”的解決方案,因為每一次迭代的過程中,我們會隨機dropout掉一些神經元(至於在那一層做dropout,需要看不通的情況),如果設定的dropout的值為0.5,則表示每個神經元有50%的概率被留下來,50%的概率被”抹去“。這就相當於我們從原來的神經網路中隨機取樣了50%的節點,組成了一個新的神經網路,這個是原來的神經網路的一個子網路,但是規模要比原來的神經網路小很多,並且訓練代價也比較小, 這個新的子網路就相當於是”隨即森林“中的一個子樹(sub-tree)了。我們多次迭代優化,每次迭代優化都會做這樣的”隨機取樣“,從原來的網路中構造一個子網路(sub-network),而每次構造的網路也都不盡相同,這就使得學習到的sub-network在結果上差異性,最後再對這些每個迭代學習到的不同的sub-network做一個”bagging“來得到最終的輸出結果。

dropout中的一些細節問題
  • 如何對多個不同的sub-network做bagging:這裡並沒有做真正意義上的bagging,我們預測的時候,其實使用的整個完整的神經網路,並沒有做任何dropout。這裡面有一個”權值共享“的概念,正式這個概念讓dropout的計算變得可行。因為每次迭代都會產生不用的sub-network,優化不同的權值,這必然使得前後兩次之間的sub-network有相同的神經元被保留下來,那麼這些神經元對應的權值沒有必要在重新開始優化,而是繼續沿用上一個迭代優化好的值。這就大大減少了優化單個sub-network的時間,使得在很少的時間內,這個sub-network就可以得到不錯的繁華效果。否則,每個迭代步驟都要從新初始化權值矩陣,開始優化,這又是一個巨大的計算開銷。
  • train 和 test 的時候,dropout的概率怎麼設定:按照原始的論文中,假設dropout的值是 p%,原始神經網路的神經元個數是N,因為在訓練的過程中只有 p% 的神經元被保留下來,相應也只有p%的需要被優化的權值保留下來,這導致dropout後sub-network的輸出也是整個原始神經網路的輸出值的p%。所以,在測試的是時候使用的整個神經網路,我們只需要將每一層的權值矩陣乘以p%就可以保證測試網路的輸出期望和訓練網路的輸出期望值大小一致了。
    train and test dropout set
    注意,如果你使用了tensorflow,則在測試的時候要保持dropout的值為1,即不”抹去“任何神經元,這個和具體的實現有關,感興趣的可以看看tensorflow官網關於dropout函式的API。
  • 為什麼很少見CNN層加dropout: 這種情況確實不多見,典型的TextCNN模型,就是沒有在卷積層加dropout。但是原始論文中確實又指出可以在卷積層做dropout ,只是收益並不是太明顯。另外,dropout對於具有大量引數的全連線效果最好,而CNN的卷積層不是全連線,引數不是很多,所以效果不明顯。論文還建議如果在CNN中加,最好是在開始的層加dropout,越往後的層,越是要小心加dropout。
  • 神經網路加上dropout後,test loss 比 train loss還要小:正常,在不考慮測試集取樣偏差的情況下,這種情況的解釋是:每次train loss是在一個batch上計算的,而單個batch又是在一個通過dropout得到的sub-network計算得到的,即相當於在單顆樹上得到的train loss;而測試的時候,用的整個神經網路,即相當於在整個”森林“上做預測,結果當然會好一下。