改善深層神經網路——深度學習的實用層面(5)
目錄
偏差大的解決辦法:在正則化引數合適的情況下增大網路(不影響方差)
方差大解決辦法:調整正則化引數或者準備更多資料增大資料集(不影響偏差)
正則化
邏輯迴歸正則化:
神經網路正則化:
6.Dropout正則化
除了L2 regularization之外,還有另外一種防止過擬合的有效方法:Dropout。
Dropout是指在深度學習網路的訓練過程中,對於每層的神經元,按照一定的概率將其暫時從網路中丟棄。也就是說,每次訓練時,每一層都有部分神經元不工作,起到簡化複雜網路模型的效果,從而避免發生過擬合。
Dropout有不同的實現方法,接下來介紹一種常用的方法:Inverted dropout
dl = np.random.rand(al.shape[0],al.shape[1])<keep_prob
然後,第ll層經過dropout,隨機刪減20%的神經元,只保留80%的神經元,其輸出為:
al = np.multiply(al,dl)
最後,還要對alal進行scale up處理,即:
al /= keep_prob
以上就是Inverted dropout的方法。之所以要對al進行scale up是為了保證在經過dropout後,al作為下一層神經元的輸入值儘量保持不變。假設第層有50個神經元,經過dropout後,有10個神經元停止工作,這樣只有40神經元有作用。那麼得到的al只相當於原來的80%。scale up後,能夠儘可能保持al的期望值相比之前沒有大的變化。
Inverted dropout的另外一個好處就是在對該dropout後的神經網路進行測試時能夠減少scaling問題。因為在訓練時,使用scale up保證al的期望值沒有大的變化,測試時就不需要再對樣本資料進行類似的尺度伸縮操作了。
對於m個樣本,單次迭代訓練時,隨機刪除掉隱藏層一定數量的神經元;然後,在刪除後的剩下的神經元上正向和反向更新權重w和常數項b;接著,下一次迭代中,再恢復之前刪除的神經元,重新隨機刪除一定數量的神經元,進行正向和反向更新w和b。不斷重複上述過程,直至迭代訓練完成。
值得注意的是,使用dropout訓練結束後,在測試和實際應用模型時,不需要進行dropout和隨機刪減神經元,所有的神經元都在工作。
7.理解Dropout
Dropout通過每次迭代訓練時,隨機選擇不同的神經元,相當於每次都在不同的神經網路上進行訓練,類似機器學習中Bagging的方法(三個臭皮匠,賽過諸葛亮),能夠防止過擬合。
除此之外,還可以從權重w的角度來解釋為什麼dropout能夠有效防止過擬合。對於某個神經元來說,某次訓練時,它的某些輸入在dropout的作用被過濾了。而在下一次訓練時,又有不同的某些輸入被過濾。經過多次訓練後,某些輸入被過濾,某些輸入被保留。這樣,該神經元就不會受某個輸入非常大的影響,影響被均勻化了。也就是說,對應的權重w不會很大。這從從效果上來說,與L2 regularization是類似的,都是對權重w進行“懲罰”,減小了w的值。
總結一下,對於同一組訓練資料,利用不同的神經網路訓練之後,求其輸出的平均值可以減少overfitting。Dropout就是利用這個原理,每次丟掉一定數量的隱藏層神經元,相當於在不同的神經網路上進行訓練,這樣就減少了神經元之間的依賴性,即每個神經元不能依賴於某幾個其他的神經元(指層與層之間相連線的神經元),使神經網路更加能學習到與其他神經元之間的更加健壯robust的特徵。
在使用dropout的時候,有幾點需要注意。首先,不同隱藏層的dropout係數keep_prob可以不同。一般來說,神經元越多的隱藏層,keep_out可以設定得小一些.,例如0.5;神經元越少的隱藏層,keep_out可以設定的大一些,例如0.8,設定是1。另外,實際應用中,不建議對輸入層進行dropout,如果輸入層維度很大,例如圖片,那麼可以設定dropout,但keep_out應設定的大一些接近1,例如0.8,0.9。總體來說,就是越容易出現過擬合的隱藏層,其keep_prob就設定的相對小一些。沒有準確固定的做法,通常可以根據validation進行選擇。
Dropout在電腦視覺CV領域應用比較廣泛,因為輸入層維度較大,而且沒有足夠多的樣本數量。值得注意的是dropout是一種regularization技巧,用來防止過擬合的,最好只在需要regularization的時候使用dropout。
使用dropout的時候,可以通過繪製cost function來進行debug,看看dropout是否正確執行。一般做法是,將所有層的keep_prob全設定為1,再繪製cost function,即涵蓋所有神經元,看J是否單調下降。下一次迭代訓練時,再將keep_prob設定為其它值。
8.其他正則化方法
除了L2 regularization和dropout regularization之外,還有其它減少過擬合的方法。
一種方法是增加訓練樣本數量。但是通常成本較高,難以獲得額外的訓練樣本。但是,我們可以對已有的訓練樣本進行一些處理來“製造”出更多的樣本,稱為data augmentation。例如圖片識別問題中,可以對已有的圖片進行水平翻轉、垂直翻轉、任意角度旋轉、縮放或擴大等等。如下圖所示,這些處理都能“製造”出新的訓練樣本。雖然這些是基於原有樣本的,但是對增大訓練樣本數量還是有很有幫助的,不需要增加額外成本,卻能起到防止過擬合的效果。
在數字識別中,也可以將原有的數字圖片進行任意旋轉或者扭曲,或者增加一些noise,如下圖所示:
還有另外一種防止過擬合的方法:early stopping。一個神經網路模型隨著迭代訓練次數增加,train set error一般是單調減小的,而dev set error 先減小,之後又增大。也就是說訓練次數過多時,模型會對訓練樣本擬合的越來越好,但是對驗證集擬合效果逐漸變差,即發生了過擬合。因此,迭代訓練次數不是越多越好,可以通過train set error和dev set error隨著迭代次數的變化趨勢,選擇合適的迭代次數,即early stopping。
然而,Early stopping有其自身缺點。通常來說,機器學習訓練模型有兩個目標:一是優化cost function,儘量減小J;二是防止過擬合。這兩個目標彼此對立的,即減小J的同時可能會造成過擬合,反之亦然。我們把這二者之間的關係稱為正交化orthogonalization。該節課開始部分就講過,在深度學習中,我們可以同時減小Bias和Variance,構建最佳神經網路模型。但是,Early stopping的做法通過減少迭代訓練次數來防止過擬合,這樣J就不會足夠小。也就是說,early stopping將上述兩個目標融合在一起,同時優化,但可能沒有“分而治之”的效果好。
與early stopping相比,L2 regularization可以實現“分而治之”的效果:迭代訓練足夠多,減小J,而且也能有效防止過擬合。而L2 regularization的缺點之一是最優的正則化引數λλ的選擇比較複雜。對這一點來說,early stopping比較簡單。總的來說,L2 regularization更加常用一些。
9.標準化輸入
在訓練神經網路時,標準化輸入可以提高訓練的速度。標準化輸入就是對訓練資料集進行歸一化的操作,即將原始資料減去其均值μ後,再除以其方差:
以二維平面為例,下圖展示了其歸一化過程:
值得注意的是,由於訓練集進行了標準化處理,那麼對於測試集或在實際應用時,應該使用同樣的μ和對其進行標準化處理。這樣保證了訓練集合測試集的標準化操作一致。
之所以要對輸入進行標準化操作,主要是為了讓所有輸入歸一化同樣的尺度上,方便進行梯度下降演算法時能夠更快更準確地找到全域性最優解。假如輸入特徵是二維的,且x1的範圍是[1,1000],x2的範圍是[0,1]。如果不進行標準化處理,x1與x2之間分佈極不平衡,訓練得到的w1和w2也會在數量級上差別很大。這樣導致的結果是cost function與w和b的關係可能是一個非常細長的橢圓形碗。對其進行梯度下降演算法時,由於w1和w2數值差異很大,只能選擇很小的學習因子α,來避免J發生振盪。一旦α較大,必然發生振盪,J不再單調下降。如下左圖所示。
然而,如果進行了標準化操作,x1與x2分佈均勻,w1和w2數值差別不大,得到的cost function與w和b的關係是類似圓形碗。對其進行梯度下降演算法時,αα可以選擇相對大一些,且J一般不會發生振盪,保證了J是單調下降的。如下右圖所示。
另外一種情況,如果輸入特徵之間的範圍本來就比較接近,那麼不進行標準化操作也是沒有太大影響的。但是,標準化處理在大多數場合下還是值得推薦的。
10.梯度消失和梯度爆炸
在神經網路尤其是深度神經網路中存在可能存在這樣一個問題:梯度消失和梯度爆炸。意思是當訓練一個 層數非常多的神經網路時,計算得到的梯度可能非常小或非常大,甚至是指數級別的減小或增大。這樣會讓訓練過程變得非常困難。
舉個例子來說明,假設一個多層的每層只包含兩個神經元的深度神經網路模型,如下圖所示:
為了簡化複雜度,便於分析,我們令各層的啟用函式為線性函式,即g(Z)=Zg(Z)=Z。且忽略各層常數項b的影響,令b全部為零。那麼,該網路的預測輸出為:
如果各層權重的元素都稍大於1,例如1.5,則預測輸出將正比於。L越大,越大,且呈指數型增長。我們稱之為數值爆炸。相反,如果各層權重W[l]的元素都稍小於1,例如0.5,則預測輸出將正比於。網路層數L越多,呈指數型減小。我們稱之為數值消失。
也就是說,如果各層權重都大於1或者都小於1,那麼各層啟用函式的輸出將隨著層數l的增加,呈指數型增大或減小。當層數很大時,出現數值爆炸或消失。同樣,這種情況也會引起梯度呈現同樣的指數型增大或減小的變化。L非常大時,例如L=150,則梯度會非常大或非常小,引起每次更新的步進長度過大或者過小,這讓訓練過程十分困難。
深度神經網路的權重初始化
下面介紹如何改善Vanishing and Exploding gradients這類問題,方法是對權重w進行一些初始化處理,不能讓矩陣w比1大很多也不能比1小很多。
深度神經網路模型中,以單個神經元為例,該層()的輸入個數為n,其輸出為:
這裡忽略了常數項b。為了讓z不會過大或者過小,思路是讓w與n有關,且n越大,w應該越小才好。這樣能夠保證z不會過大。一種方法是在初始化w時,令。相應的python虛擬碼為:
w[l] = np.random.randn(n[l],n[l-1])*np.sqrt(1/n[l-1])
如果啟用函式是tanh,一般選擇上面的初始化方法。
如果啟用函式是ReLU,權重w的初始化一般令其方差為:
w[l] = np.random.randn(n[l],n[l-1])*np.sqrt(2/n[l-1])
除此之外,Yoshua Bengio對啟用函式tanh提出了另外一種初始化w的方法,令其方差為:
w[l] = np.random.randn(n[l],n[l-1])*np.sqrt(2/n[l-1]*n[l])
至於選擇哪種初始化方法因人而異,可以根據不同的啟用函式選擇不同方法。另外,我們可以對這些初始化方法中設定某些引數,作為超引數,通過驗證集進行驗證,得到最優引數,來優化神經網路。
11.梯度的數值逼近和梯度檢測
利用微積分的思想,函式f在點處的梯度可以表示為:
其中且足夠小。
介紹完如何近似求出梯度值後,我們將介紹如何進行梯度檢查,來驗證訓練過程中是否出現bugs。
梯度檢查首先要做的是分別將這些矩陣構造成一維向量,然後將這些一維向量組合起來構成一個更大的一維向量。這樣cost function就可以表示成。
然後將反向傳播過程通過梯度下降演算法得到的按照一樣的順序構造成一個一維向量dθ。dθ的維度與θ一致。
接著利用J(θ)對每個θi計算近似梯度,其值與反向傳播演算法得到的dθi相比較,檢查是否一致。例如,對於第i個元素,近似梯度為:
計算完所有θi的近似梯度後,可以計算與dθ的歐氏(Euclidean)距離來比較二者的相似度。公式如下:
——歐幾里得範數,求誤差平方之和然後求平方根
一般來說,如果歐氏距離越小,例如,甚至更小,則表明dθapprox與dθ越接近,即反向梯度計算是正確的,沒有bugs。如果歐氏距離較大,例如10−5,則表明梯度計算可能出現問題,需要再次檢查是否有bugs存在。如果歐氏距離很大,例如10−3,甚至更大,則表明dθapprox與dθ差別很大,梯度下降計算過程有bugs,需要仔細檢查。
在進行梯度檢查的過程中有幾點需要注意的地方:
-
不要在整個訓練過程中都進行梯度檢查,僅僅作為debug使用。
-
如果梯度檢查出現錯誤,找到對應出錯的梯度,檢查其推導是否出現錯誤。
-
注意不要忽略正則化項,計算近似梯度的時候要包括進去。
-
梯度檢查時關閉dropout,檢查完畢後再開啟dropout。
-
隨機初始化時執行梯度檢查,經過一些訓練後再進行梯度檢查(不常用)。