吳恩達深度學習筆記(32)-Dropout正則化Dropout Regularization
dropout 正則化(Dropout Regularization)
除了L2正則化,還有一個非常實用的正則化方法——“Dropout(隨機失活)”,我們來看看它的工作原理。
假設你在訓練上圖這樣的神經網路,它存在過擬合,這就是dropout所要處理的,我們複製這個神經網路,dropout會遍歷網路的每一層,並設定消除神經網路中節點的概率。假設網路中的每一層,每個節點都以拋硬幣的方式設定概率,每個節點得以保留和消除的概率都是0.5,設定完節點概率,我們會消除一些節點,然後刪除掉從該節點進出的連線,最後得到一個節點更少,規模更小的網路,然後用backprop方法進行訓練。
![吳恩達深度學習筆記(32)-Dropout正則化Dropout Regularization](https://img-blog.csdnimg.cn/20181218224328609.png)
這是網路節點精簡後的一個樣本,對於其它樣本,我們照舊以拋硬幣的方式設定概率,保留一類節點集合,刪除其它型別的節點集合。對於每個訓練樣本,我們都將採用一個精簡後神經網路來訓練它,這種方法似乎有點怪,單純遍歷節點,編碼也是隨機的,可它真的有效。不過可想而知,我們針對每個訓練樣本訓練規模極小的網路,最後你可能會認識到為什麼要正則化網路,因為我們在訓練極小的網路。
如何實施dropout呢?
方法有幾種,接下來我要講的是最常用的方法,即inverted dropout(反向隨機失活),出於完整性考慮,我們用一個三層(l=3)網路來舉例說明。編碼中會有很多涉及到3的地方。我只舉例說明如何在某一層中實施dropout。
首先要定義向量d,d^([3])表示一個三層的dropout向量:
d3 = np.random.rand(a3.shape[0],a3.shape[1])
然後看它是否小於某數,我們稱之為keep-prob,keep-prob是一個具體數字,上個示例中它是0.5,而本例中它是0.8,它表示保留某個隱藏單元的概率,此處keep-prob等於0.8,它意味著消除任意一個隱藏單元的概率是0.2,它的作用就是生成隨機矩陣,如果對a([3])進行因子分解,效果也是一樣的。d([3])是一個矩陣,每個樣本和每個隱藏單元,其中d^([3])中的對應值為1的概率都是0.8,對應為0的概率是0.2,隨機數字小於0.8。它等於1的概率是0.8,等於0的概率是0.2。
接下來要做的就是從第三層中獲取啟用函式,這裡我們叫它a([3]),a([3])含有要計算的啟用函式,a([3])等於上面的a([3])乘以d^([3]),a3 =np.multiply(a3,d3),這裡是元素相乘,也可寫為a3*=d3,它的作用就是讓d([3])中所有等於0的元素(輸出),而各個元素等於0的概率只有20%,乘法運算最終把d[3] 中相應元素輸出,即讓d([3])中0元素與a([3])中相對元素歸零。
如果用python實現該演算法的話,d^([3])則是一個布林型陣列,值為true和false,而不是1和0,乘法運算依然有效,python會把true和false翻譯為1和0,大家可以用python嘗試一下。
最後,我們向外擴充套件a^([3]),用它除以0.8,或者除以keep-prob引數。
a3/=keep-prob
下面我解釋一下為什麼要這麼做,為方便起見,我們假設第三隱藏層上有50個單元或50個神經元,在一維上a^([3])是50,我們通過因子分解將它拆分成50×m維的,保留和刪除它們的概率分別為80%和20%,這意味著最後被刪除或歸零的單元平均有10(50×20%=10)個,
現在我們看下z([4]),z([4])=w^([4]) a([3])+b([4]),我們的預期是,a([3])減少20%,也就是說a([3])中有20%的元素被歸零,為了不影響z([4])的期望值,我們需要用w([4]) a([3])/0.8,它將會修正或彌補我們所需的那20%,a([3])的期望值不會變,劃線部分就是所謂的dropout方法。
它的功能是,不論keep-prop的值是多少0.8,0.9甚至是1,如果keep-prop設定為1,那麼就不存在dropout,因為它會保留所有節點。反向隨機失活(inverted dropout)方法通過除以keep-prob,確保a^([3])的期望值不變。
事實證明,在測試階段,當我們評估一個神經網路時,也就是用綠線框標註的反向隨機失活方法,使測試階段變得更容易,因為它的資料擴充套件問題變少,我們將在下節課討論。
據我瞭解,目前實施dropout最常用的方法就是Inverted dropout,建議大家動手實踐一下。Dropout早期的迭代版本都沒有除以keep-prob,所以在測試階段,平均值會變得越來越複雜,不過那些版本已經不再使用了。
現在你使用的是d向量,你會發現,不同的訓練樣本,清除不同的隱藏單元也不同。實際上,如果你通過相同訓練集多次傳遞資料,每次訓練資料的梯度不同,則隨機對不同隱藏單元歸零,有時卻並非如此。比如,需要將相同隱藏單元歸零,第一次迭代梯度下降時,把一些隱藏單元歸零,第二次迭代梯度下降時,也就是第二次遍歷訓練集時,對不同型別的隱藏層單元歸零。向量d或d^([3])用來決定第三層中哪些單元歸零,無論用foreprop還是backprop,這裡我們只介紹了foreprob。
如何在測試階段訓練演算法,在測試階段,我們已經給出了x,或是想預測的變數,用的是標準計數法。我用a^([0]),第0層的啟用函式標註為測試樣本x,我們在測試階段不使用dropout函式,尤其是像下列情況:
z([1])=w([1]) a([0])+b([1])
a([1])=g([1]) (z^([1]))
z^([2])= w^([2]) a([1])+b([2])
a^([2])=⋯
以此類推直到最後一層,預測值為^y。
顯然在測試階段,我們並未使用dropout,自然也就不用拋硬幣來決定失活概率,以及要消除哪些隱藏單元了,因為在測試階段進行預測時,我們不期望輸出結果是隨機的,如果測試階段應用dropout函式,預測會受到干擾。
理論上,你只需要多次執行預測處理過程,每一次,不同的隱藏單元會被隨機歸零,預測處理遍歷它們,但計算效率低,得出的結果也幾乎相同,與這個不同程式產生的結果極為相似。
Inverted dropout函式在除以keep-prob時可以記住上一步的操作,目的是確保即使在測試階段不執行dropout來調整數值範圍,啟用函式的預期結果也不會發生變化,所以沒必要在測試階段額外新增尺度引數,這與訓練階段不同。
l=keep-prob
為什麼dropout會起作用呢?
為什麼dropout會起作用呢?下一個筆記我們將更加直觀地瞭解dropout的具體功能。