2.1)深度學習筆記:深度學習的實踐層面

目錄

1)Train/Dev/Test sets

2)Bias/Variance

3)Regularization(重點)

4)Why regularization reduces overfitting(理解)

5)Dropout Regularization(重點)

6)Understanding Dropout

7)Other regularization methods(瞭解)

8)Normalizing inputs

9) Vanishing and Exploding gradients

10)Weight Initialization for Deep Networks(重點)

11)Numerical approximation of gradients

12)Gradient checking

13)Gradient Checking Implementation Notes

14)Summary


以下筆記是吳恩達老師深度學習課程第二門課第一週的的學習筆記:Practical aspects of Deep Learning。筆記參考了黃海廣博士的內容,在此表示感謝。 


1)Train/Dev/Test sets

今天我們可能已經知道:應用深度學習是一個典型的迭代過程。 在建立訓練模型的過程中,數據集會被劃分爲以下幾個部分:

  • 訓練集(train set):用訓練集對算法或模型進行訓練;
  • 驗證集(development set):利用驗證集(又稱爲交叉驗證集)進行交叉驗證選擇出最好的模型
  • 測試集(test set):最後利用測試集對模型進行測試,獲取模型運行的無偏估計。

在數據量比較少的時候,如 100、1000、10000 的數據量大小,可以將數據集按照以下比例進行劃分:

  • 無驗證集的情況:70% / 30%;
  • 有驗證集的情況:60% / 20% / 20%;

而在如今的大數據時代,對於一個問題,我們擁有的數據集的規模可能是百萬級別的,所以驗證集和測試集所佔的比重會趨向於變得更小。驗證集的目的是爲了驗證不同的算法哪種更加有效,所以驗證集只要足夠大到能夠驗證大約 10 種算法哪種更好時,就不需要使用 20% 的數據作爲驗證集。在百萬數據中抽取 1 萬的數據作爲驗證集就可以了。

測試集的主要目的是評估模型的效果,如在單個分類器中,往往在百萬級別的數據中,我們選擇其中 1000 條數據足以評估單個模型的效果。

100 萬數據量:98% / 1% / 1%;

超百萬數據量:99.5% / 0.25% / 0.25%(或者99.5% / 0.4% / 0.1%)

吳恩達老師在視頻中補充到:建議驗證集要和訓練集來自於同一個分佈(數據來源一致),可以使得機器學習算法訓練得更快並獲得更好的效果。如果不需要用無偏估計來評估模型的性能,則可以不需要測試集。


2)Bias/Variance

偏差(Bias)和方差(Variance)是機器學習領域非常重要的兩個概念和需要解決的問題。在傳統的機器學習算法中,Bias和Variance是對立的,分別對應着欠擬合和過擬合,我們常常需要在Bias和Variance之間進行權衡。而在深度學習中,我們可以同時減小Bias和Variance,構建最佳神經網絡模型。

欠擬合(underfitting)的情況下,即出現高偏差(high bias)的情況,不能很好地對數據進行分類。

當模型設置的太複雜時,使得模型出現過擬合(overfitting)的情況,在驗證集上出現高方差(high variance)現象。

當訓練出一個模型以後,如果:

  • 訓練集的錯誤率較小,而驗證集的錯誤率卻較大,說明模型存在較大方差,可能出現了過擬合;
  • 訓練集和開發集的錯誤率都較大,且兩者相當,說明模型存在較大偏差,可能出現了欠擬合;
  • 訓練集錯誤率較大,且開發集的錯誤率遠較訓練集大,說明方差和偏差都較大,模型很差;
  • 訓練集和開發集的錯誤率都較小,且兩者的相差也較小,說明方差和偏差都較小,這個模型效果比較好。

吳恩達老師在視頻中針對偏差和方差問題給出了一些建議:

對於高偏差問題:

  • 擴大神經網絡規模,如添加隱藏層或隱藏單元數目;
  • 尋找合適的網絡架構,使用更大的 NN 結構;
  • 花費更長時間訓練。

對於高方差問題:

  • 獲取更多的數據;
  • 正則化(regularization);
  • 尋找更合適的網絡結構。


3)Regularization(重點)

正則化是在cost函數中加入一個正則化項,懲罰模型。正則化可以用於解決高方差的問題。

我們先回顧一下之前介紹的Logistic Regression。我們採用的是L2正則化,加入正則化後的cost函數爲:

                                                     $$J(w,b) = \frac{1}{m}\sum_{i=1}^mL(\hat{y}^{(i)},y^{(i)})+\frac{\lambda}{2m}{||w||}^2_2$$

                                                                 $\|w\|_{2}^{2}=\sum_{j=1}^{n_{x}} w_{j}^{2}=w^{T} w$

這裏我們只對參數w進行了正則化處理而不對b處理。因爲b爲一個常數,相對來說w的維度很大,對模型泛化能力的影響很大。

除了L2正則化之外,還有另一張正則化方法,L1正則化,表達式爲:

                                                          J(w, b)=\frac{1}{m} \sum_{i=1}^{m} L\left(\hat{y}^{(i)}, y^{(i)}\right)+\frac{\lambda}{2 m}\|w\|_{1}

                                                                              \|w\|_{1}=\sum_{j=1}^{n_{x}}\left|w_{j}\right|

由於 L1 正則化最後得到 w 向量中將存在大量的 0,使模型變得稀疏化,因此 L2 正則化更加常用 。注意lambda在 Python 中屬於保留字,所以在編程的時候,用lambd代替這裏的正則化因子。

在深度學習模型中,L2正則化的表達式爲:

                                         J(w^{[1]}, b^{[1]}, ..., w^{[L]}, b^{[L]}) = \frac{1}{m}\sum_{i=1}^mL(\hat{y}^{(i)},y^{(i)})+\frac{\lambda}{2m}\sum_{l=1}^L{{||w^{[l]}||}}^2

                                                                         $${{||w^{[l]}||}}^2 = \sum^{n^{[l-1]}}_{i=1}\sum^{n^{[l]}}_{j=1}(w^{[l]}_{ij})^2

{{||w^{[l]}||}}^2被稱爲弗羅貝尼烏斯範數(Frobenius Norm),所以神經網絡中的正則化項被稱爲弗羅貝尼烏斯範數矩陣。

加入正則化之後,我們的梯度下降計算變爲:

                                                                    $$dw^{[l]}= \frac{\partial L}{\partial w^{[l]}} +\frac{\lambda}{m}w^{[l]}$$

                                                                        $w^{[l]} :=w^{[l]}-\alpha \cdot d w^{[l]}$

加入正則化之後新的梯度下降公式變爲:

                                                           w^{[l]}:= (1 - \frac{\alpha\lambda}{m})w^{[l]} - \alpha \frac{\partial L}{\partial w^{[l]}}

可以看見,權重w衰減,所以L2正則化項也被稱爲權重衰減。



4)Why regularization reduces overfitting(理解)

我們都知道正則化可以有效避免過擬合,但爲什麼可以避免過擬合呢?我們舉例來說明:下面是欠擬合、剛好擬合和過擬合的情況。

假如我們選擇了非常複雜的神經網絡模型,如上圖左上角所示。在未使用正則化的情況下,我們得到的分類超平面可能是類似上圖右側的過擬合。但是,如果使用L2 正則化,當λ很大時,w[l]≈0。w[l]近似爲零,意味着該神經網絡模型中的某些神經元實際的作用很小,可以忽略。從效果上來看,其實是將某些神經元給忽略掉了。這樣原本過於複雜的神經網絡模型就變得不那麼複雜了,而變得非常簡單化了。如下圖所示,整個簡化的神經網絡模型變成了一個邏輯迴歸模型。問題就從high variance變成了high bias了。

因此,選擇合適大小的λ值,就能夠同時避免high bias和high variance,得到最佳模型。

數學解釋:

假設神經元中使用的激活函數爲tanh函數。

在加入正則化項後,當 λ 增大,導致$w^{[l]}減小,$z^{[l]} = w^{[l]}a^{[l-1]} + b^{[l]}$便會減小。由上圖可知,在 z 較小(接近於 0)的區域裏,tanh(z)函數近似線性,所以每層的函數就近似線性函數,整個網絡就成爲一個簡單的近似線性的網絡,因此不會發生過擬合。


5)Dropout Regularization(重點)

除了L2正則化,還有一種防止過擬合的有效方法:Dropout。dropout(隨機失活是在神經網絡的隱藏層爲每個神經元結點設置一個隨機消失的概率,保留下來的神經元形成一個結點較少、規模較小的網絡用於訓練。dropout 正則化較多地被使用在計算機視覺(Computer Vision)領域。下圖爲概率爲0.5的Dropout的正則化例子。

Dropout有不同的實現方法,接下來介紹一種常用的方法:Inverted dropout。假設對於第ll層神經元,設定保留神經元比例概率keep_prob=0.8,即該層有20%的神經元停止工作。dl爲dropout向量,設置dl爲隨機vector,其中80%的元素爲1,20%的元素爲0。在python中可以使用如下語句生成dropout vector:

keep_prob = 0.8    # 設置神經元保留概率
dl = np.random.rand(al.shape[0], al.shape[1]) < keep_prob
al = np.multiply(al, dl)
al /= keep_prob

最後一步al /= keep_prob 是因爲 $a^{[l]}$中的一部分元素失活(相當於被歸零),爲了在下一層計算時不影響 $z^{[l+1]} = w^{[l+1]}a^{[l]} + b^{[l+1]}$的期望值,因此除以一個keep_prob注意,在測試階段不要使用 dropout,因爲那樣會使得預測結果變得隨機。


6)Understanding Dropout

Dropout通過每次迭代訓練時,隨機選擇不同的神經元,相當於每次都在不同的神經網絡上進行訓練,類似機器學習中Bagging的方法,能夠防止過擬合。

對於單個神經元,其接收輸入特徵並輸出。但是加入了 dropout 後,輸入的特徵都存在被隨機消失的可能,所以該神經元不會再特別依賴於任何一個輸入特徵,即不會給任何一個輸入特徵設置太大的權重。 因此,通過傳播過程,dropout 將產生和 L2 正則化相同的收縮權重的效果。

對於不同的層,設置的keep_prob也不同。一般來說,神經元較少的層,會設keep_prob爲 1.0,而神經元多的層則會設置比較小的keep_prob

dropout 的一大缺點是成本函數無法被明確定義。因爲每次迭代都會隨機消除一些神經元結點的影響,因此無法確保成本函數單調遞減。因此,使用 dropout 時,先將keep_prob全部設置爲 1.0 後運行代碼,確保 J(w, b)函數單調遞減,再打開 dropout。


7)Other regularization methods(瞭解)

除了L2 正則化和dropout 正則化之外,還有其它減少過擬合的方法。

一種方法是增加訓練樣本數量。但是通常成本較高,難以獲得額外的訓練樣本。但是,我們可以對已有的訓練樣本進行一些處理來“製造”出更多的樣本,稱爲data augmentation。例如圖片識別問題中,可以對已有的圖片進行水平翻轉、垂直翻轉、任意角度旋轉、縮放或擴大等等。如下圖所示,這些處理都能“製造”出新的訓練樣本。雖然這些是基於原有樣本的,但是對增大訓練樣本數量還是有很有幫助的,不需要增加額外成本,卻能起到防止過擬合的效果。

還有另外一種防止過擬合的方法:early stopping。將訓練集和驗證集進行梯度下降時的成本變化曲線畫在同一個座標軸內,當訓練集誤差降低但驗證集誤差升高,兩者開始發生較大偏差時及時停止迭代,並返回具有最小驗證集誤差的連接權和閾值,以避免過擬合。這種方法的缺點是無法同時達成偏差和方差的最優。


8)Normalizing inputs

在訓練神經網絡時,標準化輸入可以提高訓練的速度。標準化輸入就是對訓練數據集進行歸一化的操作,即將原始數據減去其均值μ後,再除以其方差\sigma^2

                                                                               $$x = \frac{x - \mu}{\sigma}$$,

                                                                               $$\mu = \frac{1}{m}\sum^m_{i=1}x^{(i)}$$

                                                                             \sigma^2 = \frac{1}{m}\sum^{m}_{i=1}(x^{(i)})^2

爲什麼使用標準化輸入呢?我們來看下面這幅圖:

有圖可知,使用標準化輸入前後,成本函數的形狀有較大改變。

在不使用標準化的成本函數中,如果設置一個較小的學習率,可能需要很多次迭代才能到達全局最優解;而如果使用了標準化,那麼無論從哪個位置開始迭代,都能以相對較少的迭代次數找到全局最優解。


9) Vanishing and Exploding gradients

在神經網絡尤其是深度神經網絡中存在這樣一個問題:梯度消失和梯度爆炸。意思是當訓練一個層數非常多的神經網絡時,計算得到的梯度可能非常小或非常大,甚至是指數級別的減小或增大。這樣會讓訓練過程變得非常困難。假設存在下面這個每層包含兩個神經元的深度神經網絡:

假定 $g(z) = z, b^{[l]} = 0$,對於目標輸出有: $$\hat{y} = W^{[L]}W^{[L-1]}...W^{[2]}W^{[1]}X$$

  • 對於 $W^{[l]}$的值>1 的情況,激活函數的值將以指數級遞增;
  • 對於W^{[l]}的值< 1 的情況,激活函數的值將以指數級遞減。

對於梯度計算同樣。因此,在計算梯度時,根據不同情況梯度函數會以指數級遞增或遞減,導致訓練梯度難度上升,梯度下降算法的步長會變得非常小,需要訓練的時間將會非常長。


10)Weight Initialization for Deep Networks(重點)

下面介紹如何改善梯度消失和梯度爆炸這類問題,方法是對權重w進行一些初始化處理。、

深度神經網絡模型中,以單個神經元爲例,該層l的輸入個數爲n,其輸出爲:

                                                   $$z={w}_1{x}_1+{w}_2{x}_2 + ... + {w}_n{x}_n + b$$

可知,當輸入的數量 n 較大時,我們希望每個 w_i的值都小一些,這樣它們的和得到的 z也較小。

一種方法是在初始化w時,令其方差爲\frac{1}{n}。相應的python僞代碼爲:

w[l] = np.random.randn(n[l],n[l-1])*np.sqrt(1/n[l-1]) 

如果激活函數是tanh,一般選擇上面的初始化方法。

如果激活函數是ReLU,權重w的初始化一般令其方差爲\frac{2}{n}

w[l] = np.random.randn(n[l],n[l-1])*np.sqrt(2/n[l-1]) 

至於選擇哪種初始化方法因人而異,可以根據不同的激活函數選擇不同方法。另外,我們可以對這些初始化方法中設置某些參數,作爲超參數,通過驗證集進行驗證,得到最優參數,來優化神經網絡。


11)Numerical approximation of gradients

Back Propagation神經網絡有一項重要的測試是梯度檢查(gradient checking)。其目的是檢查驗證反向傳播過程中梯度下降算法是否正確。

雙邊誤差求導(即導數的定義):

                                                           

                                                      $$f'(\theta) = {\lim_{\varepsilon\to 0}} \frac{f(\theta + \varepsilon) - (\theta - \varepsilon)}{2\varepsilon}$$

當 ε 越小時,結果越接近真實的導數,也就是梯度值。可以使用這種方法來判斷反向傳播進行梯度下降時,是否出現了錯誤。


12)Gradient checking

介紹完如何近似求出梯度值後,我們將介紹如何進行梯度檢查,來驗證訓練過程中是否出現bugs。

梯度檢查首先要做的是分別將W^{[1]},b^{[1]},...,W^{[L]},b^{[L]}全部連接起來,構成一個一維向量\theta。 這樣成本函數就成爲J(\theta)

同時,對 dW^{[1]},db^{[1]},...,dW^{[L]},db^{[L]}執行同樣的操作得到一維向量 d\theta,它和 \theta 有同樣的維度。

接着利用J(\theta)對每個\theta_i計算近似梯度,其值與反向傳播算法得到的d\theta_i相比較,檢查是否一致。例如,對於第i個元素,近似梯度爲:

             d \theta_{a p p r o x}[i]=\frac{J\left(\theta_{1}, \theta_{2}, \cdots, \theta_{i}+\varepsilon, \cdots\right)-J\left(\theta_{1}, \theta_{2}, \cdots, \theta_{i}-\varepsilon, \cdots\right)}{2 \varepsilon}$

計算完所有\theta_i的近似梯度後,計算d\theta_{approx}d\theta的歐氏距離,公式如下:

                                                                    $$\frac{{||d\theta_{approx} - d\theta||}_2}{{||d\theta_{approx}||}_2+{||d\theta||}_2}$$

一般來說,如果歐氏距離越小,例如10^{-7},甚至更小,則表明反向梯度計算是正確的,沒有bugs。

如果歐氏距離較大,例如10^{-5},則表明梯度計算可能出現問題,需要再次檢查是否有bugs存在。

如果歐氏距離很大,例如10^{-3},甚至更大,則表明梯度下降計算過程有bugs,需要仔細檢查。


13)Gradient Checking Implementation Notes

在進行梯度檢查的過程中有幾點需要注意的地方:

  • 不要在訓練中使用梯度檢驗,它只用於debug;
  • 如果算法的梯度檢驗失敗,要檢查所有項,並試着找出 bug;
  • 當成本函數包含正則項時,也需要帶上正則項進行檢驗;
  • 梯度檢驗不能與 dropout 同時使用。因爲每次迭代過程中,dropout 會隨機消除隱藏層單元的不同子集,難以計算 dropout 在梯度下降上的成本函數 J。建議關閉 dropout,用梯度檢驗進行雙重檢查,確定在沒有 dropout 的情況下算法正確,然後打開 dropout;

14)Summary

本節課主要介紹了深度學習的實踐層面

首先我們講了如何配置訓練集,驗證集和測試集,並如何分析偏差、方差,如何處理欠擬合過擬合問題

然後我們介紹瞭如何在深度神經網絡模型中應用不同形式的正則化,如L2正則化和dropout正則化

最後我們介紹了歸一化輸入,這可以加快神經網絡的訓練速度,以及梯度檢驗

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