/--->【DL-CV】更高級的參數更新/優化(一)
【DL-CV】批量歸一化(BN算法)<前篇---後篇>
/--->【DL-CV】更高級的參數更新/優化(二)python
在損失函數那篇文章中,咱們引入了正則化並簡單介紹了L2正則化。其做用是防止網絡過擬合,提升網絡的泛化能力。本文將介紹一些防止過擬合的方法,算法
所謂過擬合,就是網絡對訓練集極度適應,以致於訓練出來的權重幾乎只服務於訓練集,致使在訓練好的網絡在跑訓練集的時候表現得很好(準確率高),而跑測試集或其餘數據表現得不好。過擬合的出現將下降網絡的泛化能力,是很是糟糕的事情。segmentfault
正則化是抑制網絡過擬合,提升網絡泛化能力的一種方法。Dropout是其替代品,也能防止過擬合提升泛化能力。下面介紹這兩種方法網絡
正則化經過在損失函數上加上正則化損失來實現,根據正則化損失定義的不一樣,正則化又能分爲好幾種。dom
$$R(W)=\sum_k \sum_l W^2_{k,l}$$
L2正則化是是最經常使用的正則化方法,即對於網絡中的每一個權重值$w$,向損失函數中增長一個$\frac{1}{2}\lambda w^2$做爲正則化懲罰,其中$\lambda$是正則化強度;乘了個$\frac{1}{2}$是很常見的事,由於這樣式子關於 $w$ 梯度就是 $\lambda w$ 而不是 $2\lambda w$ 了。函數
L2正則化能夠直觀地理解爲對於大數值的權重向量進行嚴厲懲罰(平方懲罰),驅使權重往更加均勻的方向發展而不是某些權重絕對值很大某些權重絕對值很小,這樣能提升網絡的泛化能力。學習
$$R(W)=\sum_k \sum_l| W_{k,l}|$$
L1正則化是另外一個經常使用的正則化方法,即對於網絡中每一個權重值$w$,向損失函數增長一個$\lambda|w|$做爲其正則化懲罰,其中$\lambda$是正則化強度。測試
L1正則化相對於L2正則化對大數值權重的懲罰沒那麼重(沒有平方懲罰),他會讓權值在最訓練的過程當中很是接近零(L2則是讓權重變成分散的小數值)。在實踐中,若是不是特別關注某些明確的特徵選擇,通常說來L2正則化都會比L1正則化效果好優化
L1正則化也能夠和L2正則化組合使用變成$\lambda_1|w|+\lambda_2w^2$,這也被稱做Elastic net regularizaton。不過沒這麼經常使用就是了spa
Dropout堪稱對付過擬合的超級武器,其使用簡單,效果強勁。咱們先來介紹dropout的使用:
Dropout能夠理解爲,在每次訓練時,隨機抽取一部分神經元組成一個子網絡,基於輸入數據只更新子網絡的參數(子網絡並不相互獨立,由於他們共享着參數)。最後在測試時不使用隨機失活,能夠理解爲對子網絡們作了模型集成,以此來計算出一個平均的預測。
p = 0.5 # 激活神經元的機率. p值更高 = 隨機失活更弱 def train_step(X): """ X中是輸入數據 """ # 3層neural network的前向傳播 H1 = np.maximum(0, np.dot(X, W1 ) + b1) U1 = np.random.rand(*H1.shape) < p # 第一個隨機失活遮罩 H1 *= U1 # drop! H2 = np.maximum(0, np.dot(H1, W2) + b2) U2 = np.random.rand(*H2.shape) < p # 第二個隨機失活遮罩 H2 *= U2 # drop! out = np.dot(H2, W3) + b3 # 反向傳播略 # 參數更新略 def predict(X): H1 = np.maximum(0, np.dot(W1, X) + b1) * p # 注意:激活數據要乘以p H2 = np.maximum(0, np.dot(W2, H1) + b2) * p # 注意:激活數據要乘以p out = np.dot(W3, H2) + b3
一種理解是Dropout避免了特徵間的相互適應。如上圖,假如網絡中的神經元學到了如上特徵,「有耳朵」,「有尾巴」,「毛毛的」等等特徵,這些特徵組合起來判斷是不是貓。正常來講(做爲人來講),特徵越多越好,但在這種狀況下(深度學習),徹底依靠這些特徵將可能致使過擬合的發生。使用Dropout後,網絡的部分鏈接將被中斷,網絡不能依賴這些特徵的組合來給出結果,而是隻能使用零散的特徵來給出判斷,這在某種程度上防止了過擬合,提升了網路的泛化能力。
更多解釋和理解可參考此文
上面提到的Dropout方法在測試時每層激活值是要乘$p$的,額外的乘法操做會下降測試時的效率。因此更多時候咱們會使用一個叫Inverted Dropout 的方法,他把隨機性抵消的操做從預測階段搬到了訓練階段:在訓練階段的Dropout操做後,咱們對神經元的激活值除以$p$來抵消隨機性。這樣預測階段會更高效。
p = 0.5 # 激活神經元的機率. p值更高 = 隨機失活更弱 def train_step(X): """ X中是輸入數據 """ # 3層neural network的前向傳播 H1 = np.maximum(0, np.dot(X, W1 ) + b1) U1 = (np.random.rand(*H1.shape) < p) / p # 第一個隨機失活遮罩,/p H1 *= U1 # drop! H2 = np.maximum(0, np.dot(H1, W2) + b2) U2 = (np.random.rand(*H2.shape) < p) / p # 第二個隨機失活遮罩 H2 *= U2 # drop! out = np.dot(H2, W3) + b3 # 反向傳播略 # 參數更新略 def predict(X): H1 = np.maximum(0, np.dot(X, W1) + b1) # 免去*p H2 = np.maximum(0, np.dot(H1, W2) + b2) out = np.dot(H2, W3) + b3
除了將神經元隨機置0的Dropout外,還有將權重值隨機置0的DropConnect,興趣自查