Dropout理論與實現

                                 Dropout理論與實現

一、前言

  深度學習中爲了防止過擬合有很多方法,如正則化、數據增強、Dropout、BatchNorm等等,其中Dropout是一種比較經典的算法,從2012年提出到現在依舊有着重要地位,經典就是經典。

  對於Dropout,從開始學習深度學習就只知道它可以有效防止過擬合,對於爲什麼它可以一直模模糊糊,只知道在遇到問題的時候就慌慌忙忙地採用包括其在內的各種辦法,但是卻不知所以然,因此雖然是比較老的算法了,但是還是有必要理解清楚。網上有着很多關於Dropout的博客,還是有必要自己去理解並筆記的必要,畢竟如人飲水,冷暖自知……

二、理論

  Dropout在2012的論文《Dropout: A Simple Way to Prevent Neural Networks from Overfitting》和《Improving neural networks by preventing co-adaptation of feature detectors》有詳細地討論,現在對其做簡單推導。

1、問題

  如果一個較大的神經網絡在很小的數據集上直接訓練,很容易過擬合(在訓練集表現優異,但是在測試集上表現很差),模型的泛化能力很差。通常可以通過蒐集更多的樣本,增大數據集量級來解決(畢竟深度學習是吃數據集的算法),然而現實中很那蒐集到那麼多的樣本,另外到底數據集要大到什麼程度有時候也不知道。

2、Dropout的提出

  Hiton在《Improving neural networks by preventing co-adaptation of feature detectors》中提到造成過擬合的原因:由於大的神經網絡的神經元之間有着複雜的共適應性(co- adaptation), co-adaptation的意思是每個神經元學到的特徵,必須結合其它的特定神經元作爲上下文,才能提供對訓練的幫助。而Dropout的提出則是爲了削弱這種複雜的共適應性,也可以理解爲削弱神經元之間的依賴關係。

3、Dropout具體實現(How,具體如何做的呢?)

                                                                         圖 1

  Dropout的思路,按照一定的概率隨機丟棄一部分神經元(如圖1所示),這樣每次都會有一種新的組合,假設有某一層有N個神經元,就有2的N次方個組合(子網絡),最後子網絡的輸出均值就是最終的結果,講道理應該這樣。但是如果同時訓練這麼子網絡代價太大,而且測試時又要組合多個網絡的輸出結果,不可行。

  Dropout的做法比較巧,在一個網絡中就實現了。訓練階段在每個mini-batch中,依概率P隨機屏蔽掉一部分神經元,只訓練保留下來的神經元對應的參數,屏蔽掉的神經元梯度爲0,參數不參數與更新。而測試階段則又讓所有神經元都參與計算,那麼究竟如何實現的呢,總結下來就是下面的公式:

  標準的神經網絡計算公式(學了BP神經網絡就比較熟悉,這是其中一層的神經元計算公式):

  f是激活函數。Dropout是這麼幹的,

  r是依伯努利概率分佈(0-1分佈)隨機產生的mask向量,向量元素取值0或1,取1的概率爲P,取0的概率爲1-P ,向量維度與某一層的輸入神經元維度一致。這就比較明顯了,r向量與神經元對應元素相乘,r中元素爲1的被保留,爲0的則置0,那麼只有被保留的神經元對應的參數得到訓練(強迫神經元和其他隨機挑選出來的神經元共同工作,減弱了神經元節點間的聯合適應性)。

  訓練的時候是這樣操作的,很好理解,要知道測試的時候我們沒有丟棄的操作,所有神經元都參與計算,爲什麼就一步到位了呢?

  論文《Dropout: A Simple Way to Prevent Neural Networks fromOver-fitting》 截圖:

  論文中說在測試階段通過一種近似逼近的方法完成,即在測試階段與Dropout層神經元對應參數W乘以該神經元被保留下來的概率P(P=1-Dropout ratio),因爲每個神經元被保留下來的概率爲P,那麼對應參數scale-down,即乘上概率P。我們知道測試階段前想過程要儘可能和要和訓練階段基本一致,所以,爲了使得dropout layer 下一層的輸入和訓練時具有相同的“意義”和“數量級”,我們要對測試時的dropout layer的輸出(即下層的輸入)做 rescale: 乘以一個P,表示最後的sum中只有這麼大的概率,或者這麼多的部分被保留,這個是經驗意義上的等價,那麼數學意義呢?怎麼和平均意義等價呢?可不可以這樣解釋:

  如果按照之前的笨辦法, Dropout層中每個神經元被保留的概率服從伯努利分佈,在N(N趨於無窮大)次訓練中,假設某個神經元在這被保留下來的此數目爲n,那麼

             

  需要注意的是測試階段所有神經元都會參與計算(不丟棄),不同的是訓練時需要按概率(1-P)丟棄的神經元對應參數要乘以P.我們知道訓練階段每個minibatch都會丟棄N(1-P)的神經元,只留下PN的神經元。來看一個公式:

  測試階段沒有Dropout,我們希望一次完成計算:

           

按照論文說法,測試階段有

           

那麼訓練如果直接訓練'就可以直接在測試階段權值乘參數而不需要額外的乘以保留概率,又

          

 

則在訓練階段Dropout層做通過乘scale的操作等價地訓練,訓練階段公式

        

其中X是經過Dropout之後保的X,即按概率P保留部分神經元值,丟棄部分(1-P)置零,這樣的話訓練階段就等價的完成了對W'的訓練,測試階段不丟棄神經元直接運下面的式子逼近平均化結果

        

很多深度學習框架的源碼都是按照這個思路實現的。算法流程總結如下:

    1)在訓練階段,每個mini-batch中,按照伯努利概率分佈隨機的丟棄一部分神經元(即神經元置零)。用一個mask向量與該層神經元對應元素相乘,mask向量維度與輸入神經一致,元素爲0或1。

    2)然後對神經元rescale操作,即每個神經元除以保留概率P,也即乘上1/P。

    3)反向傳播只對保留下來的神經元對應參數進行更新。

    4)測試階段,Dropout層不對神經元進行丟棄,保留所有神經元直接進行前向過程。

三、實現

1、Caffe實現源碼

Caffe對Dropout實現對應於dropout_layer的實現,詳細的實現代碼在dropout_layer.hpp、dropout_layer.cpp和dropout_layer.cu中。dropout_layer.cpp的cpp寫了具體初始化與實現流程。

 

threshold即爲Dropout ratio(被丟棄的概率),因此scale就是

1.0/(1.0-threshold)。

 

Mask向量維度與輸入該層的神經元向量一樣。

 

訓練階段,按伯努利分佈產生mask向量,其中每一個元素等於1 的概率爲1.0-threshold,即被保留的概率。然後對應元素相乘在乘上一個scale。測試階段不用做任何操作,直接輸出與輸入一樣,不丟棄。

2、python實現

python實現就更簡單了,就幾行搞定。

#!encoding=utf-8
import numpy as np
def dropout(x, drop_out_ratio,type):
    if drop_out_ratio < 0. or drop_out_ratio>= 1:  # drop_out_ratio是概率值,必須在0~1之間
        raise Exception('Dropout level must be in interval [0, 1[.')
    if type=="train":
        scale = 1. / (1. - drop_out_ratio)
        mask_vec = np.random.binomial(n=1, p=1. - drop_out_ratio,size=x.shape)  # 即將生成一個0、1分佈的向量,0表示這個神經元被屏蔽,不工作了,也就是dropout了
        x *= mask_vec * scale                                                                             # 0、1與x相乘,我們就可以屏蔽某些神經元,讓它們的值變爲0,再乘上scale係數

    return x

參考博客:

1、https://blog.csdn.net/hjimce/article/details/50413257

2、https://blog.csdn.net/u012702874/article/details/45030991

3、《Improving neural networks by preventing co-adaptation of feature detectors》

4、《Dropout: A Simple Way to Prevent Neural Networks from Overfitting》

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章