深度學習筆記-收錄

原文鏈接:https://github.com/fengdu78/deeplearning_ai_books

一. 訓練誤差和泛化誤差

對於機器學習模型在訓練數據集和測試數據集上的表現。如果你改變過實驗中的模型結構或者超參數,你也許發現了:當模型在訓練數據集上更準確時,它在測試數據集上卻不⼀定更準確。這是爲什麼呢?

因爲存在着訓練誤差和泛化誤差:
在這裏插入圖片描述

  1. 訓練誤差:模型在訓練數據集上表現出的誤差。
  2. 泛化誤差:模型在任意⼀個測試數據樣本上表現出的誤差的期望,並常常通過測試數據集上的誤差來近似。

訓練誤差的期望小於或等於泛化誤差。也就是說,⼀般情況下,由訓練數據集學到的模型參數會使模型在訓練數據集上的表現優於或等於在測試數據集上的表現。由於⽆法從訓練誤差估計泛化誤差,⼀味地降低訓練誤差並不意味着泛化誤差⼀定會降低。

機器學習模型應關注降低泛化誤差。


二. 該如何選擇模型
在機器學習中,通常需要評估若⼲候選模型的表現並從中選擇模型。這⼀過程稱爲模型選擇(model selection)。可供選擇的候選模型可以是有着不同超參數的同類模型。以多層感知機爲例,我們可以選擇隱藏層的個數,以及每個隱藏層中隱藏單元個數和激活函數。爲了得到有效的模型,我們通常要在模型選擇上下⼀番功夫。

1 . 驗證數據集
從嚴格意義上講,測試集只能在所有超參數和模型參數選定後使⽤⼀次。不可以使⽤測試數據選擇模型,如調參。由於⽆法從訓練誤差估計泛化誤差,因此也不應只依賴訓練數據選擇模型。鑑於此,我們可以預留⼀部分在訓練數據集和測試數據集以外的數據來進⾏模型選擇。這部分數據被稱爲驗證數據集,簡稱驗證集(validation set)。例如,我們可以從給定的訓練集中隨機選取⼀小部分作爲驗證集,而將剩餘部分作爲真正的訓練集。
可以通過預留這樣的驗證集來進行模型選擇,判斷驗證集在模型中的表現能力。

2. K 折交叉驗證
由於驗證數據集不參與模型訓練,當訓練數據不夠⽤時,預留⼤量的驗證數據顯得太奢侈。⼀種改善的⽅法是K折交叉驗證(K-fold cross-validation)。在K折交叉驗證中,我們把原始訓練數據集分割成K個不重合的⼦數據集,然後我們做K次模型訓練和驗證。每⼀次,我們使⽤⼀個⼦數據集驗證模型,並使⽤其他K − 1個⼦數據集來訓練模型。在這K次訓練和驗證中,每次⽤來驗證模型的⼦數據集都不同。最後,我們對這K次訓練誤差和驗證誤差分別求平均。


三. ⽋擬合和過擬合

欠擬合:模型⽆法得到較低的訓練誤差。
過擬合:是模型的訓練誤差遠小於它在測試數據集上的誤差。
給定訓練數據集,
如果模型的複雜度過低,很容易出現欠擬合;
如果模型複雜度過⾼,很容易出現過擬合。

應對⽋擬合和過擬合的⼀個辦法是針對數據集選擇合適複雜度的模型。

1. 訓練數據集⼤⼩
影響⽋擬合和過擬合的另⼀個重要因素是訓練數據集的⼤小。⼀般來說,如果訓練數據集中樣本數過少,特別是⽐模型參數數量(按元素計)更少時,過擬合更容易發⽣。此外,泛化誤差不會隨訓練數據集⾥樣本數量增加而增⼤。因此,在計算資源允許的範圍之內,我們通常希望訓練數據集⼤⼀些,特別是在模型複雜度較⾼時,例如層數較多的深度學習模型。

2. 正則化
應對過擬合問題的常⽤⽅法:權重衰減(weight decay),權重衰減等價於L2範數正則化(regularization)。正則化通過爲模型損失函數添加懲罰項使學出的模型參數值較小,是應對過擬合的常⽤⼿段。


四. 丟棄法(Dropout)

除了上面提到的權重衰減以外,深度學習模型常常使⽤丟棄法(dropout)來應對過擬合問題。丟棄法有⼀些不同的變體。本節中提到的丟棄法特指倒置丟棄法(inverted dropout)。

回憶⼀下,“多層感知機”描述了⼀個單隱藏層的多層感知機。其中輸⼊個數爲4,隱藏單元個數爲5,且隱藏單元hi(i = 1, . . . , 5)的計算表達式爲:

在這裏插入圖片描述
這⾥ϕ是激活函數,x1, . . . , x4是輸⼊,隱藏單元i的權重參數爲w1i, . . . , w4i,偏差參數爲bi。當對該隱藏層使⽤丟棄法時,該層的隱藏單元將有⼀定概率被丟棄掉。設丟棄概率爲p,那麼有p的概率hi會被清零,有1 − p的概率hi會除以1 − p做拉伸。丟棄概率是丟棄法的超參數。具體來說,設隨機變量ξi爲0和1的概率分別爲p和1 − p。使⽤丟棄法時我們計算新的隱藏單元.
在這裏插入圖片描述

由於E(ξi) = 1 − p,因此:
在這裏插入圖片描述

即丟棄法不改變其輸⼊的期望值。讓我們對隱藏層使⽤丟棄法,⼀種可能的結果如下圖所⽰,其中h2和h5被清零。這時輸出值的計算不再依賴h2和h5,在反向傳播時,與這兩個隱藏單元相關的權重的梯度均爲0。由於在訓練中隱藏層神經元的丟棄是隨機的,即h1, . . . , h5都有可能被清零,輸出層的計算⽆法過度依賴h1, . . . , h5中的任⼀個,從而在訓練模型時起到正則化的作⽤,並可以⽤來應對過擬合。在測試模型時,我們爲了拿到更加確定性的結果,⼀般不使⽤丟棄法。


五.梯度消失/梯度爆炸(Vanishing / Exploding gradients)

訓練神經網絡,尤其是深度神經所面臨的一個問題就是梯度消失或梯度爆炸,也就是你訓練神經網絡的時候,導數或坡度有時會變得非常大,或者非常小,甚至於以指數方式變小,這加大了訓練的難度。
本質上,梯度消失和爆炸是一種情況。在深層網絡中,由於網絡過深,如果初始得到的梯度過小,或者傳播途中在某一層上過小,則在之後的層上得到的梯度會越來越小,即產生了梯度消失。梯度爆炸也是同樣的。一般地,不合理的初始化以及激活函數,如sigmoid等,都會導致梯度過大或者過小,從而引起消失/爆炸。

解決方案:

1、預訓練加微調

其基本思想是每次訓練一層隱節點,訓練時將上一層隱節點的輸出作爲輸入,而本層隱節點的輸出作爲下一層隱節點的輸入,此過程就是逐層“預訓練”(pre-training);在預訓練完成後,再對整個網絡進行“微調”(fine-tunning)。
此方法有一定的好處,但是目前應用的不是很多了。

2、梯度剪切、正則

梯度剪切這個方案主要是針對梯度爆炸提出的,其思想是設置一個梯度剪切閾值,然後更新梯度的時候,如果梯度超過這個閾值,那麼就將其強制限制在這個範圍之內。這可以防止梯度爆炸。
另外一種解決梯度爆炸的手段是採用權重正則化(weithts regularization)比較常見的是L1和L2正則。

3、ReLu、leakReLu等激活函數

ReLu:其函數的導數在正數部分是恆等於1,這樣在深層網絡中,在激活函數部分就不存在導致梯度過大或者過小的問題,緩解了梯度消失或者爆炸。同時也方便計算。當然,其也存在存在一些缺點,例如過濾到了負數部分,導致部分信息的丟失,輸出的數據分佈不在以0爲中心,改變了數據分佈。
leakrelu:就是爲了解決relu的0區間帶來的影響,其數學表達爲:leakrelu=max(k*x,0)其中k是leak係數,一般選擇0.01或者0.02,或者通過學習而來。

4、Batch Normalization(批標準化)

Batch Normalization是深度學習發展以來提出的最重要的成果之一了,目前已經被廣泛的應用到了各大網絡中,具有加速網絡收斂速度,提升訓練穩定性的效果,Batch Normalization本質上是解決反向傳播過程中的梯度問題。Batch Normalization,簡稱BN,即批規範化,通過規範化操作將輸出信號x規範化到均值爲0,方差爲1保證網絡的穩定性。

  • 有一些從 0 到 1 而不是從 1 到 1000 的特徵值,通過歸一化所有的輸入特徵值𝑥,以獲得類似範圍的值,可以加速學習。所以 Batch 歸一化起的作用的原因,直觀的一點就是,它在做類似的工作,但不僅僅對於這裏的輸入值,還有隱藏單元的值。它可以使權重比你的網絡更滯後或更深層,比如,第 10 層的權重更能經受得住變化。

5、殘差結構
殘差的方式,能使得深層的網絡梯度通過跳級連接路徑直接返回到淺層部分,使得網絡無論多深都能將梯度進行有效的回傳。

6、LSTM

LSTM全稱是長短期記憶網絡(long-short term memory networks),是不那麼容易發生梯度消失的,主要原因在於LSTM內部複雜的“門”(gates)。在計算時,將過程中的梯度進行了抵消。

六、隨機梯度下降法

1 mini-batch梯度下降

你可以把訓練集分割爲小一點的子集訓練,這些子集被取名爲 mini-batch,假設每一個子集中只有 1000 個樣本,那麼把其中的𝑥 (1)到𝑥 (1000)取出來,將其稱爲第一個子訓練集,也叫做 mini-batch,然後你再取出接下來的 1000 個樣本,從𝑥 (1001)到𝑥 (2000),然後再取 1000個樣本,以此類推。

在訓練集上運行 mini-batch 梯度下降法,你運行 for t=1……5000,因爲我們有5000個各有 1000 個樣本的組,在 for 循環裏你要做得基本就是對𝑋 {𝑡}和𝑌 {𝑡}執行一步梯度下降法。

  • batch_size=1,就是SGD。
  • batch_size=n,就是mini-batch
  • batch_size=m,就是batch

其中1<n<m,m表示整個訓練集大小。

優缺點:

  • batch:相對噪聲低些,幅度也大一些,你可以繼續找最小值。
  • SGD:大部分時候你向着全局最小值靠近,有時候你會遠離最小值,因爲那個樣本恰好給你指的方向不對,因此隨機梯度下降法是有很多噪聲的,平均來看,它最終會靠近最小值,不過有時候也會方向錯誤,因爲隨機梯度下降法永遠不會收斂,而是會一直在最小值附近波動。一次性只處理了一個訓練樣本,這樣效率過於低下。
  • mini-batch:實踐中最好選擇不大不小的 mini-batch,得到了大量向量化,效率高,收斂快。

首先,如果訓練集較小,直接使用 batch 梯度下降法,這裏的少是說小於 2000 個樣本。一般的 mini-batch 大小爲 64 到 512,考慮到電腦內存設置和使用的方式,如果 mini-batch 大小是 2 的𝑛次方,代碼會運行地快一些。

2 調節 Batch_Size 對訓練效果影響到底如何?

Batch_Size 太小,模型表現效果極其糟糕(error飆升)。
隨着 Batch_Size 增大,處理相同數據量的速度越快。
隨着 Batch_Size 增大,達到相同精度所需要的 epoch 數量越來越多。
由於上述兩種因素的矛盾, Batch_Size 增大到某個時候,達到時間上的最優。
由於最終收斂精度會陷入不同的局部極值,因此 Batch_Size 增大到某些時候,達到最終收斂精度上的最優。

七、優化算法

1. 動量法

在每次迭代中,梯度下降根據⾃變量當前位置,沿着當前位置的梯度更新⾃變量。然而,如果⾃變量的 迭代⽅向僅僅取決於⾃變量當前位置,這可能會帶來⼀些問題。

讓我們考慮⼀個輸⼊和輸出分別爲⼆維向量x = [x1, x2]⊤和標量的⽬標函數
=0.1x_12+2x_22)。這⾥將係數從1減小到了0.1。下⾯實現基於這個⽬標函數的梯度下降,並演⽰使⽤學習率爲0.4時⾃變量的迭代軌跡。
在這裏插入圖片描述

可以看到,同⼀位置上,⽬標函數在豎直⽅向(x2軸⽅向)⽐在⽔平⽅向(x1軸⽅向)的斜率的絕對值更⼤。因此,給定學習率,梯度下降迭代⾃變量時會使⾃變量在豎直⽅向⽐在⽔平⽅向移動幅度更⼤。那麼,我們需要⼀個較小的學習率從而避免⾃變量在豎直⽅向上越過⽬標函數最優解。然而,這會造成⾃變量在⽔平⽅向上朝最優解移動變慢。

動量法的提出是爲了解決梯度下降的上述問題。由於小批量隨機梯度下降⽐梯度下降更爲⼴義,本章後續討論將沿⽤“小批量隨機梯度下降”⼀節中時間步t的小批量隨機梯度gt的定義。設時間步t的⾃變量爲xt,學習率爲ηt。在時間步0,動量法創建速度變量v0,並將其元素初始化成0。在時間步t > 0,動量法對每次迭代的步驟做如下修改:
在這裏插入圖片描述
其中,動量超參數γ滿⾜0 ≤ γ < 1。當γ = 0時,動量法等價於小批量隨機梯度下降。在梯度下降時候使用動量法後的迭代軌跡:
在這裏插入圖片描述
可以看到使⽤較小的學習率η = 0.4和動量超參數γ = 0.5時,動量法在豎直⽅向上的移動更加平滑,且在⽔平⽅向上更快逼近最優解。

所以,在動量法中,⾃變量在各個⽅向上的移動幅度不僅取決當前梯度,還取決於過去的各個梯度在各個⽅向上是否⼀致。在本節之前⽰例的優化問題中,所有梯度在⽔平⽅向上爲正(向右),而在豎直⽅向上時正(向上)時負(向下)。這樣,我們就可以使⽤較⼤的學習率,從而使⾃變量向最優解更快移動。

2. AdaGrad算法

優化算法中,⽬標函數⾃變量的每⼀個元素在相同時間步都使⽤同⼀個學習率來⾃我迭代。在“動量法”⾥我們看到當x1和x2的梯度值有較⼤差別時,需要選擇⾜夠小的學習率使得⾃變量在梯度值較⼤的維度上不發散。但這樣會導致⾃變量在梯度值較小的維度上迭代過慢。動量法依賴指數加權移動平均使得⾃變量的更新⽅向更加⼀致,從而降低發散的可能。本節我們介紹AdaGrad算法,它根據⾃變量在每個維度的梯度值的⼤小來調整各個維度上的學習率,從而避免統⼀的學習率難以適應所有維度的問題。

AdaGrad算法會使⽤⼀個小批量隨機梯度gt按元素平⽅的累加變量st。在時間步0,AdaGrad將s0中每個元素初始化爲0。在時間步t,⾸先將小批量隨機梯度gt按元素平⽅後累加到變量st:
在這裏插入圖片描述
其中⊙是按元素相乘。接着,將⽬標函數⾃變量中每個元素的學習率通過按元素運算重新調整⼀下:
在這裏插入圖片描述
其中η是學習率,ϵ是爲了維持數值穩定性而添加的常數,如10的-6次方。這⾥開⽅、除法和乘法的運算都是按元素運算的。這些按元素運算使得⽬標函數⾃變量中每個元素都分別擁有⾃⼰的學習率。

需要強調的是,小批量隨機梯度按元素平⽅的累加變量st出現在學習率的分⺟項中。因此,

如果⽬標函數有關⾃變量中某個元素的偏導數⼀直都較⼤,那麼該元素的學習率將下降較快;
反之,如果⽬標函數有關⾃變量中某個元素的偏導數⼀直都較小,那麼該元素的學習率將下降較慢。

然而,由於st⼀直在累加按元素平⽅的梯度,⾃變量中每個元素的學習率在迭代過程中⼀直在降低(或不變)。所以,當學習率在迭代早期降得較快且當前解依然不佳時,AdaGrad算法在迭代後期由於學習率過小,可能較難找到⼀個有⽤的解。
在這裏插入圖片描述
3. RMSProp算法
當學習率在迭代早期降得較快且當前解依然不佳時,AdaGrad算法在迭代後期由於學習率過小,可能較難找到⼀個有⽤的解。爲了解決這⼀問題,RMSProp算法對AdaGrad算法做了⼀點小小的修改。

不同於AdaGrad算法⾥狀態變量st是截⾄時間步t所有小批量隨機梯度gt按元素平⽅和,RMSProp算法將這些梯度按元素平⽅做指數加權移動平均。具體來說,給定超參數0 ≤ γ < 1,RMSProp算法在時間步t > 0計算:
在這裏插入圖片描述
和AdaGrad算法⼀樣,RMSProp算法將⽬標函數⾃變量中每個元素的學習率通過按元素運算重新調整,然後更新⾃變量:
在這裏插入圖片描述
其中η是學習率,ϵ是爲了維持數值穩定性而添加的常數,如10的-6次方。因爲RMSProp算法的狀態變量st是對平⽅項gt ⊙ gt的指數加權移動平均,所以可以看作是最近1/(1 − γ)個時間步的小批量隨機梯度平⽅項的加權平均。如此⼀來,⾃變量每個元素的學習率在迭代過程中就不再⼀直降低(或不變)。
在這裏插入圖片描述
4. AdaDelta算法
除了RMSProp算法以外,另⼀個常⽤優化算法AdaDelta算法也針對AdaGrad算法在迭代後期可能較難找到有⽤解的問題做了改進。有意思的是,AdaDelta算法沒有學習率這⼀超參數。
AdaDelta算法也像RMSProp算法⼀樣,使⽤了小批量隨機梯度gt按元素平⽅的指數加權移動平均變量st。在時間步0,它的所有元素被初始化爲0。給定超參數0 ≤ ρ < 1(對應RMSProp算法中的γ),在時間步t > 0,同RMSProp算法⼀樣計算:
在這裏插入圖片描述
與RMSProp算法不同的是,AdaDelta算法還維護⼀個額外的狀態變量∆xt,其元素同樣在時間步0時被初始化爲0。我們使⽤∆xt−1來計算⾃變量的變化量:
在這裏插入圖片描述
最後,使⽤∆xt來記錄⾃變量變化量G,按元素平⽅的指數加權移動平均:
在這裏插入圖片描述
可以看到,如不考慮ϵ的影響,AdaDelta算法與RMSProp算法的不同之處在於使⽤N來替代超參數η。
5. Adam算法
Adam算法在RMSProp算法基礎上對小批量隨機梯度也做了指數加權移動平均。
Adam算法使⽤了動量變量vt和RMSProp算法中小批量隨機梯度按元素平⽅的指數加權移動平均變量st,並在時間步0將它們中每個元素初始化爲0。給定超參數0 ≤ β1 < 1(算法作者建議設爲0.9),時間步t的動量變量vt即小批量隨機梯度gt的指數加權移動平均:
在這裏插入圖片描述
和RMSProp算法中⼀樣,給定超參數0 ≤ β2 < 1(算法作者建議設爲0.999),將小批量隨機梯度按元素平⽅後的項gt ⊙ gt做指數加權移動平均得到st:
在這裏插入圖片描述
對於任意時間步 t,可以將 vt 再除以(1-βt),從而使過去各時間步小批量隨機梯度權值之和爲1。這也叫作偏差修正。在Adam算法中,對變量 vt 和 st 均作偏差修正:
在這裏插入圖片描述

接下來,Adam算法使⽤以上偏差修正後的變量vˆt和sˆt,將模型參數中每個元素的學習率通過按元素運算重新調整:
在這裏插入圖片描述
其中η是學習率,ϵ是爲了維持數值穩定性而添加的常數,如10的-8次方。和AdaGrad算法、RMSProp算法以及AdaDelta算法⼀樣,⽬標函數⾃變量中每個元素都分別擁有⾃⼰的學習率。最後,使⽤迭代⾃變量:
在這裏插入圖片描述
6. 局部最優–鞍點問題
一個具有高維度空間的函數,如果梯度爲 0,那麼在每個方向,它可能是凸函數,也可能是凹函數。如果你在 2 萬維空間中,那麼想要得到局部最優,所有的 2 萬個方向都需要是這樣,但發生的機率也許很小,也許是2的-20000次方。你更有可能遇到有些方向的曲線會這樣向上彎曲,另一些方向曲線向下彎,而不是所有的都向上彎曲,因此在高維度空間,你更可能碰到鞍點。
在這裏插入圖片描述
而不會碰到局部最優。至於爲什麼會把一個曲面叫做鞍點,你想象一下,就像是放在馬背上的馬鞍一樣,如果這是馬,這是馬的頭,這就是馬的眼睛,畫得不好請多包涵,然後你就是騎馬的人,要坐在馬鞍上,因此這裏的這個點,導數爲 0 的點,這個點叫做鞍點。我想那確實是你坐在馬鞍上的那個點,而這裏導數爲 0。

鞍點中的平穩段是一個問題,這樣使得學習十分緩慢,這也是像 Momentum 或是RMSprop,Adam 這樣的算法,能夠加速學習算法的地方。在這些情況下,更成熟的優化算法,如 Adam 算法,能夠加快速度,讓你儘早往下走出平穩段。

八、如何解決訓練樣本少的問題

  1. 利用預訓練模型進行遷移微調(fine-tuning),預訓練模型通常在特徵上擁有很好的語義表達。此時,只需將模型在小數據集上進行微調就能取得不錯的效果。CV有ImageNet,NLP有BERT等。
  2. 數據集進行下采樣操作,使得符合數據同分布。
  3. 數據集增強、正則或者半監督學習等方式來解決小樣本數據集的訓練問題。

九、如何提升模型的穩定性?

  1. 正則化(L2, L1, dropout):模型方差大,很可能來自於過擬合。正則化能有效的降低模型的複雜度,增加對更多分佈的適應性。
  2. 前停止訓練:提前停止是指模型在驗證集上取得不錯的性能時停止訓練。這種方式本質和正則化是一個道理,能減少方差的同時增加的偏差。目的爲了平衡訓練集和未知數據之間在模型的表現差異。
  3. 擴充訓練集:正則化通過控制模型複雜度,來增加更多樣本的適應性。
  4. 特徵選擇:過高的特徵維度會使模型過擬合,減少特徵維度和正則一樣可能會處理好方差問題,但是同時會增大偏差。

十、有哪些改善模型的思路

  1. 數據角度
    增強數據集。無論是有監督還是無監督學習,數據永遠是最重要的驅動力。更多的類型數據對良好的模型能帶來更好的穩定性和對未知數據的可預見性。對模型來說,“看到過的總比沒看到的更具有判別的信心”。

  2. 模型角度
    模型的容限能力決定着模型可優化的空間。在數據量充足的前提下,對同類型的模型,增大模型規模來提升容限無疑是最直接和有效的手段。

  3. 調參優化角度
    如果你知道模型的性能爲什麼不再提高了,那已經向提升性能跨出了一大步。超參數調整本身是一個比較大的問題。一般可以包含模型初始化的配置,優化算法的選取、學習率的策略以及如何配置正則和損失函數等等。

  4. 訓練角度
    在越大規模的數據集或者模型上,誠然一個好的優化算法總能加速收斂。但你在未探索到模型的上限之前,永遠不知道訓練多久算訓練完成。所以在改善模型上充分訓練永遠是最必要的過程。充分訓練的含義不僅僅只是增大訓練輪數。有效的學習率衰減和正則同樣是充分訓練中非常必要的手段。

十一、如何提高深度學習系統的性能

  1. 提高模型的結構。
  2. 改進模型的初始化方式,保證早期梯度具有某些有益的性質,或者具備大量的稀疏性,或者利用線性代數原理的優勢。
  3. 選擇更強大的學習算法。

來自吳恩達的課堂筆記喔!相信也有不少人整理了。

發現新大陸了:某個大佬的Github
裏面有吳恩達的視頻課程的筆記整理,太強了!記錄一下!
再次強調,大佬的Github
再次強調,大佬的Github
再次強調,大佬的Github

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