深度學習DeepLearning.ai系列課程學習總結:9.深度學習基礎實踐理論

WangZhe0912發表於2017-12-03

轉載過程中,圖片丟失,程式碼顯示錯亂。

為了更好的學習內容,請訪問原創版本:

http://www.missshi.cn/api/view/blog/5a1ff5cf9112b3493d000000

Ps:初次訪問由於js檔案較大,請耐心等候(8s左右)


在本文中,我們將瞭解一些深度學習中的實際理論內容。

主要包括:

1. 訓練、驗證、測試集的劃分

2. 對偏差和方差的理解

3. 機器學習中解決高偏差/高方差的基本方法

4. 正則化基本理論

5. Dropout的原理

6. 其他防止過擬合的方法

7. 如何加快訓練速度

8. 梯度消失和梯度爆炸的概念

9. 梯度校驗方法

訓練、驗證、測試集的劃分

在神經網路訓練開始之前,我們需要對很多網路結構及超引數進行確定。 
例如網路有多少層;每層有多少個神經單元,學習速率,啟用函式型別等等。 
機器學習通過是一個反覆實踐的過程,就像之前提到的這個圖一樣: 
enter image description here 
下面,我們首先來了解一下如何對訓練集、驗證集和測試集進行分配: 
對於整個資料集而言,我們需要將其分為訓練集、驗證集和測試集三個部分。 
首先,我們需要利用訓練集進行模型訓練,然後通過驗證集來判斷我們訓練模型的好壞,並找出其中最好的模型最終在測試集上進行評估。 
在之前的小樣本的機器學習應用中,一個常見的分配方式是進行三七分配:即70%的資料用於訓練,而30%的資料用於進行驗證。 
或者是6,2,2分配:即訓練集、驗證集和測試集分別佔60%,20%,20%。 
這種方式在樣本數量不大的時候(1W以下),是一種比較恰當的選擇。 
然而,在現在的大資料時代,隨著資料量的爆發時增長,這樣方式已經不再適用了。 
我們的資料量可能很容易達到百萬量級,此時,驗證集和測試集並不需要那麼大的比例。 
我們通常只需要1W條資料左右用於驗證和訓練就足夠了。 
也就是說,當樣本量是100W時,訓練集、驗證集和測試集分別佔98%,1%,1%就足夠了。 
同理,如果樣本量是1000萬時,那麼我們可以將訓練集、驗證集和測試集分別佔99.6%,0.2%,0.2%。 
此外,我們還需要考慮另外一種情況,就是訓練集和測試集來源於不同的分佈: 
以一個識別貓的App為例,使用者可以上傳一張圖片來辨別是否是一張貓的照片。 
那麼在實際應用中,使用者通過手機上傳的圖片可能並不太清晰、甚至有些模糊。 
然而,我們在訓練過程中,我們並沒有大量的這類使用者上傳的圖片,只有少量的此類圖片,並不足以我們完成模型的訓練。 
但是,我們可以利用爬蟲,從網路上爬取大量的貓的照片,但是網上貓的照片通常是高清的。 
此時,就面臨著一個問題:真實的應用資料與我們所能擁有的更為大量的資料並不來源於同一個分佈,那麼此時該如何解決呢? 
此時,我們首先需要保證驗證集和測試集是來源於同一分佈且與真實應用場景的分佈相同,即驗證集和測試集應該是全部來源於使用者上傳的圖片。 
而對於訓練集,可以包含一部分使用者上傳的圖片,此時,如何資料量不足的話,我們可以將大量的網路爬蟲得到的圖片新增至訓練集中用於訓練。

偏差與方差

偏差和方差是機器學習中兩個很重要的概念。 
接下來,我們將詳細瞭解一下偏差和方差在機器學習中的意義。 
在通常的機器學習中偏差和方差通常是一個權衡的問題,而在深度學習應用中,我們則通常會將兩者分開進行討論,我們也將會講解兩者之間的這些關聯。 
以下面的三張圖為例: 
方差和偏差的講解

  • 左圖中,就是一個典型的高偏差的場景。以這種方式進行分類時,明顯會表現出欠擬合的狀態。此時,說明訓練不夠充分。
  • 右圖中,我們可以看出是一個典型的高方差的場景。很明顯,該模型對於訓練樣本過於擬合,對於真實場景不具備很好的擴充套件性,此時,一種常見的方法是擴大訓練樣本。
  • 在中間的圖中,則很好的保證了偏差和方法。一方面,儘可能的符合了分佈場景;另一方面也避免了分割函式過高的複雜度。

接下來,我們沿用之前經常提到的對貓咪進行分類的場景進行說明。 
貓咪 
我們可以用訓練集樣本的誤差和驗證集樣本的誤差來對應到偏差與方差中。 
假設我們訓練出的模型在訓練集中,錯誤率為1%,而在驗證集中,錯誤率為11%。 
那麼說明對於訓練集,表現的效能很好,但是在驗證集中效能並不好。 
通常而言,這種場景中是由於對訓練集過度擬合造成的。此時,我們稱之為高方差。 
如果當模型在訓練集中,錯誤率為15%,而在驗證集中,錯誤率為16%。而該任務對於人類而言,錯誤率通常不足1%。 
那麼也就說明了該模型還沒有很好的擬合,即屬於欠擬合狀態,此時,我們稱之為高偏差。 
再舉一個例子:當模型在訓練集中,錯誤率為15%,而在驗證集中,錯誤率為30%。 
那麼這種情況下,說明該模型既有高方差,又有很高的偏差。 
而噹噹模型在訓練集中,錯誤率為0.5%,而在驗證集中,錯誤率為1%時,說明該模型既較小的方差,又有很小的偏差。 
總結一下:

訓練誤差 驗證誤差 方差 偏差
1% 11%
15% 16%
15% 30%
0.5% 1%

上述的所有分析都是基於我們對識別貓這個任務的複雜度預測的。 
我們認為該任務對於人類而言,錯誤率接近於0。 
我們通常稱最優誤差為貝葉斯誤差。也就是說,在該場景中,貝葉斯誤差接近於0。 
如果在某個複雜的任務中,貝葉斯誤差本身就相對較高,那麼,我們在判斷偏差時,也需要根據根據相應的標準進行判斷。

機器學習中解決高偏差/高方差的基本方法

在解決問題之前,我們首先需要判斷當前情況下是否存在高偏差。 
如果的確偏差很大,對訓練集都不能很好的擬合時,我們通常可以考慮以下思路:

  • 採用更大的網路
  • 訓練更長的時間
  • 換一個新的網路結構

通過這些方面的反覆試驗,首先要保證其偏差降低到一定程度後,再繼續後續過程。 
當偏差降低到一個可接受的值時,我們將繼續考慮其方差的問題。 
此時,我們要檢視模型在驗證集上的效能,如果模型在驗證集上表現出的效能並不足夠好,我們通常可以考慮一下思路:

  • 使用更多的資料進行訓練
  • 正則化
  • 換一個新的網路結構

最終,我們的目標就是通過不斷的除錯、試驗來找出一個具有較低偏差、較低方差的模型。 
總結一下,高偏差和高方差是兩種完全不同的問題,解決方法有完全不同,我們需要根據特定的問題來選擇對應的解決方法。 
在早期的機器學習中,我們通常很難做到僅僅減少方差/偏差時,不影響另外一個指標。因此,通常需要考慮兩者的權衡問題。 
但是在深度學習和大資料時代,理論上,我們只需要擴大網路結構並用更多的資料進行訓練,就可以保證較小的方差和偏差。

正則化基本理論

當你發現你的網路發生了過擬合的問題時(存在高偏差),那麼首先想到的一種方法應該就是正則化了。此外,收集更多的樣本資料也是避免過擬合的一個好的方法。但是,當收集樣本很大時,我們首選的方法就是正則化了。 
接下來,我們將首先講解正則化的相關基本理論。 
邏輯迴歸模型為例: 
我們需要最小化的表示式如下:minw,bJ(w,b)minw,bJ(w,b) 
其中,J(w,b)J(w,b)的計算公式如下: 

J(w,b)=1mi=1mL(y^(i),y(i))+λm||w||22J(w,b)=1m∑i=1mL(y^(i),y(i))+λm||w||22

其中,||w||22=nxj=1w2j=wTw||w||22=∑j=1nxwj2=wTw 
該方法我們也稱之為L2正則化方法。 
L2是最常見的正則化方法之一。 
除了L2正則化外,可能你還聽說過L1正則化。 
此時,用||w||1||w||1來代替||w||22||w||22,且||w||1=nxj=1|wj|||w||1=∑j=1nx|wj| 
需要注意的是,在新增正則化的過程中,有一個重要的超引數λλ。 
我們在實際應用中,通常需要通過驗證集和多次試驗來選擇合適的λλ。 
下面,我們來看下在神經網路中,正規表示式是如何計算的吧: 
J(w[1],b[1],,w[l],b[l])||w||2Famp;=amp;=amp;1mi=1mL(y^(i),y(i))+λml=1L||w||2Famp;i=1n[l1]j=1n[l](w[l]ij)2(1)(2)(1)J(w[1],b[1],⋯,w[l],b[l])amp;=amp;1m∑i=1mL(y^(i),y(i))+λm∑l=1L||w||F2(2)其中:||w||F2amp;=amp;∑i=1n[l−1]∑j=1n[l](wij[l])2

我們稱||w||2F||w||F2為frobenius範數。 
那麼,我們來看一下新增了正則化後的反向傳播是什麼樣子的吧: 
dw[l]w[l]w[l]amp;=amp;:=amp;:=amp;:=amp;()+λmw[l]amp;w[l]αdw[l]amp;w[l]α[()+λmw[l]]amp;(1λαm)w[l]α()(3)(4)(5)(6)(3)dw[l]amp;=amp;(原始內容)+λmw[l](4)w[l]amp;:=amp;w[l]−αdw[l](5)w[l]amp;:=amp;w[l]−α[(原始內容)+λmw[l]](6)amp;:=amp;(1−λαm)w[l]−α(原始內容)

此時,我們可以發現ww的權重變小,這一現象我們也稱之為權重衰減。 
那麼,為什麼通過正則化可以很好的防止過擬合問題呢? 
我們從公式的角度進行一下直觀的理解: 
由於在代價函式中,我們新增了一個正則項n[l1]i=1n[l]j=1(w[l]ij)2∑i=1n[l−1]∑j=1n[l](wij[l])2。 
λλ足夠大時,如果矩陣ww中有很多不為0的數值,那麼將會造成很大的代價函式值。 
因此,在降低代價函式值得同時,將會對網路的結構進行簡化,此時則可以有效的防止過擬合的問題。 
但是,需要注意的時,如果λλ值很大的時候,會導致模型從過擬合狀態直接變化為欠擬合狀態,因此,選擇一個合適的λλ的值非常重要。

Dropout的原理與實現

除了L2正則化以外,Dropout方法也是一個十分常用的正則化手段。 
enter image description here 
假設我們在上圖的神經網路結構中進行訓練,驗證時發現了較嚴重的過擬合現象。 
那麼Dropout的基本原理如下: 
遍歷每層的神經元節點,並設定每層節點隨機消失的概率。 
例如,我們設定所有節點都是有0.5的概率會消失。 
那麼,在完成這個過程後,我們會發現有一些節點現在已經被失效: 
enter image description here 
然後,我們刪除掉與這些節點關聯的連線: 
enter image description here 
此時,我們將會得到一個節點更少,網路更加簡單的模型結構。 
對於該樣本,以同樣的結構進行前向傳播和反向傳播。 
而當下一樣本輸入時,我們需要重新隨機選擇節點置為失效並進行前向傳播和反向傳播。 
上面,我們講解了Dropout的基本原理,那麼具體應該如何去實現呢? 
接下來,我們將以一個三層的神經網路結構來進行說明。

  1. keep_prob = 0.8 # 設定消除的概率為0.2
  2. d3 = np.random.rand(a3.shape[0], a3.shape[1]) < keep_prob # 隨機的0,1矩陣
  3. a3 = np.multiply(a3, d3) # 部分元素清零
  4. a3 /= keep_prob # 復原尺度

需要注意的是,在使用Dropout進行訓練得到的模型,在進行驗證,測試或應用時,應該不再適用Dropout函式進行隨機失效處理。 
主要原因是因為在測試或驗證階段,我們不希望輸出的結果是隨機的。 
那麼為什麼Dropout函式會對避免過擬合有很好的效果呢?我們來繼續分析一下: 
從直觀上理解,新增了Dropout函式後,我們無法對某些神經元或特徵進行強依賴,而是更多地會依賴於整個的權重分配。 
Ps:

  • 在使用Dropout函式時,不同層的keep_prob可以變化。例如,對於某些神經元較多的層,我們可以設定更低的keep_prob來避免過擬合,因此理論上,在引數越多的層,造成過擬合的可能性通常更大。
  • Dropout函式在計算機視覺領域應用相對較多。
  • 只有在模型過擬合的時候才考慮使用Dropout函式。
  • 缺點是在使用了Dropout函式後,代價函式JJ不再能夠被明確的定義。每次迭代中會隨機刪除一些節點。此時,我們很難進行除錯驗證。因此,我們通常建議先將keep_prob設定為1,進行除錯,保證代價函式單調遞減時,再開啟Dropout層進行訓練。

其他防止過擬合的方法

除了L2正則化和Dropout函式外,還有一些方法可以用於正則化來防止過擬合。 
方法1:資料擴充 
當我們無法獲得更多的資料時,我們可以根據已有的資料來生成一些新的資料。 
以影像領域為例,我們可以對原始影像進行任意翻轉、裁剪等來生成一些新的樣本。 
enter image description here 
這種方式雖然不像全新的樣本那麼有價值,但是好在獲取成本極低,也可以對我們訓練起到一定的幫助作用。 
方法2:Early stop 
在迭代的過程中,代價函式的變化曲線通常如下: 
enter image description here 
如果我們將驗證集的誤差也繪製在同一張圖上時,通常而言得到的結果如下: 
enter image description here 
從圖中,我們可以發現,驗證集的誤差通常會首先呈現出下降的趨勢,達到最低點後則會開始上升。 
Early stop指的就是當驗證集誤差達到最低點後,就停止繼續訓練。 
但是這樣一來,將會有一個缺點:就是無法單獨來保證偏差和方差兩個指標。因為提前終止訓練會導致偏差無法繼續下降。

加快訓練速度

在模型訓練的過程中,一個加快訓練速度的好的方法是歸一化輸入。 
假設我們的輸入是二維特徵,以下圖為例: 
enter image description here 
那麼歸一化可以分為兩個步驟:

  1. 零均值化 
    μ=1mi=1mx(i)x:=xμμ=1m∑i=1mx(i)x:=x−μ

    enter image description here
  2. 歸一化方差 
    σ2=1mi=1m[x(i)]2x:=x/σ2σ2=1m∑i=1m[x(i)]2x:=x/σ2

    enter image description here

Ps:如果我們在訓練過程中對訓練資料進行了零均值化和方差歸一化,那麼我們要記錄在零均值化和方差歸一化時的引數μμσσ,同樣在驗證,測試和應用過程中,使用相同的引數對輸入進行處理。 
那麼為什麼通過對輸入資料進行歸一化會是有效的呢? 
我們來看一個沒有進行歸一化的場景: 
enter image description here 
這是一個非常窄小的代價函式。 
此時,其輪廓線的下降曲線通常如下: 
enter image description here 
即當起始位置位於狹長區域時,可能需要經過較多次迭代才能找到一個較優的值。 
此外,在這個過程中,我們還需要保持較小的步長才能保證迭代尋優的過程穩定。 
而如果我們對資料進行歸一化後,其代價函如下: 
enter image description here 
而其輪廓線的下降曲線通常如下: 
enter image description here 
而在此時,無論初始位置位於哪兒,都會更容易的找到較優的值。 
同時,即使選擇相對較大的步長,通常也不會影響模型的收斂穩定性。

梯度消失和梯度爆炸

在神經網路的訓練過程中,我們常常需要考慮梯度消失/梯度爆炸的問題。 
那麼梯度消失或梯度爆炸的含義是什麼呢?通常是指我們在訓練一個較大的神經網路時,隨著網路層數的增加、導數的值可能會變得非常大或者非常小,而這將會導致訓練的難度加大。 
那麼為什麼會出現這種現象呢? 
以下面一個神經網路為例: 
enter image description here
假設我們使用線性啟用函式g(z)=zg(z)=z以及設定偏置為0,即b=0b=0。 
此時, 

y^=w[l]w[l1]w[l2]w[3]w[2]w[1]xy^=w[l]w[l−1]w[l−2]⋯w[3]w[2]w[1]x

如果: 
w=[1.50amp;0amp;1.5]y^=w[l][1.5l10amp;0amp;1.5l1]xw=[1.5amp;00amp;1.5]y^=w[l][1.5l−1amp;00amp;1.5l−1]x

那麼,可以發現如果網路很深時,即l很大時,y^y^將會呈指數式的變大。 
反之,如果w的大小為0.5,那麼如果網路很深時,即l很大時,y^y^將會呈指數式的減少。 
這就是我們所說的梯度爆炸和梯度衰減現象。

這種現象又該怎麼去解決呢? 
首先,在初始化神經網路的權重時,要有一定的技巧。 
以一個神經元為例: 
enter image description here 
其中:z=w1x1+w2x2++wnxnz=w1x1+w2x2+…+wnxn 
此處,我們先忽略b。 
nn很大時,即輸入的神經元很多時,我們希望對應的wiwi較小,即每個輸入的權重值較小。 
這樣才能保證輸出的大小一致。 
例如,我們可以初始化時候,設定所有的wiwi權重初始為1n1n。(Ps:實驗證明,當選擇ReLU啟用函式時,的wiwi權重係數設定為2n2n可以得到較好的結果。) 
示例: 

w[l]=np.random.rand(shape)np.sqrt(2/n[l1])w[l]=np.random.rand(shape)∗np.sqrt(2/n[l−1])

此外,在使用tanh作為啟用函式時,更好的初始化係數如下: 
w[l]=np.random.rand(shape)np.sqrt(1/n[l1])w[l]=np.random.rand(shape)∗np.sqrt(1/n[l−1])

同理,對於Xavier初始化方法(後續講解)而言,則更好的初始化係數如下: 
w[l]=np.random.rand(shape)np.sqrt(2/(n[l1]+n[l]))w[l]=np.random.rand(shape)∗np.sqrt(2/(n[l−1]+n[l]))

通過對網路權重進行合理的初始化,可以在一定程度上緩解梯度爆炸/消失問題。

梯度校驗方法

當我們在實現了一個反向傳播的程式碼時,我們通常需要去驗證我們實現的內容是否正確,然後再進行長時間的訓練。 
首先,我們來學習如何從數值計算來逼近梯度值: 
以下圖為例: 
enter image description here 
表示了y=x3y=x3函式。 
θθ點的梯度的數值計算公式如下: 

g(θ)f(θ+ε)f(θε)2εg(θ)≈f(θ+ε)−f(θ−ε)2ε

當我們選擇θ=1θ=1ε=0.01ε=0.01時: 
可以得到g(θ)=3g(θ)=3,逼近演算法計算得到的值為3.0001,誤差為0.0001。

接下來,我們將學習如何進行梯度校驗,梯度校驗可以幫我們提前發現反向傳播實現中的一些問題。

  1. W[1],b[1],,W[L],b[L]W[1],b[1],…,W[L],b[L]重新Reshape後組成了一個一維的向量θθ
  2. dW[1],db[1],,dW[L],db[L]dW[1],db[1],…,dW[L],db[L]重新Reshape後組成了一個一維的向量dθ
  3. 依次計算θθ中的每一個元素的dθapproxdθapprox 
    dθapprox[i]=J(θ1,θ2,,θi+ε,+)J(θ1,θ2,,θiε,+)2εdθapprox[i]=J(θ1,θ2,…,θi+ε,+…)−J(θ1,θ2,…,θi−ε,+…)2ε
  4. 使用我們之前編寫的反向傳播演算法計算dθ
  5. 計算當ε=107ε=10−7時二者的差異: 
    error=||dθapproxdθ||2||dθapprox||2+||dθ||2error=||dθapprox−dθ||2||dθapprox||2+||dθ||2

    Ps:當error屬於10710−7量級時,計算結果通常是正確的。 
    當error屬於10510−5量級時,計算結果有可能會是錯誤的,儘量重新進行驗證。 
    當error屬於10310−3量級時,計算結果通常是錯誤的,需要重新計算。

下面是在使用梯度校驗的一些說明和注意事項:

  • 僅僅在除錯階段使用,而不是在訓練階段使用。(訓練階段使用會極大的影響訓練速度)
  • 如果驗證有問題,需要逐個項進行檢查。
  • 在梯度檢查時,需要注意正則化的影響。
  • 在梯度檢查時,需要禁用Dropout函式。(設定keep_prob為1)
  • 使用隨機方法進行初始化,可以先進行一定程式的訓練後再進行梯度校驗(有時當W和b很小時,梯度校驗無法發現問題)。




更多更詳細的內容,請訪問原創網站:

http://www.missshi.cn/api/view/blog/5a1ff5cf9112b3493d000000

Ps:初次訪問由於js檔案較大,請耐心等候(8s左右)


相關文章