模型在訓練集上表現很好、在開發集上卻差了一截,是深度學習最常見的狀況之一。依照第 1 章的偏誤與變異分析,這代表變異過高,也就是過擬合(overfitting)。最可靠的解法是收集更多資料,但資料往往昂貴,甚至根本無法取得,這時正則化(regularization)就是第一道防線。
這一章前半整理常用的正則化方法,後半則是訓練神經網路時的實務經驗:如何有系統地調校超參數、如何確認反向傳播沒有寫錯、有哪些值得養成的訓練習慣,以及 GPU 記憶體不夠時該怎麼辦。
9.1正則化方法總覽Overview of Regularization
狹義的正則化,是指在損失函數中加入懲罰項;但在深度學習的語境中,「正則化」通常採取更廣的意義:任何能降低過擬合、讓模型在新資料上表現更好的方法,即使它會讓訓練集誤差稍微上升。
| 方法 | 做法 | 特性 |
|---|---|---|
| 懲罰項(L2/L1) | 在損失函數加上權重大小的懲罰 | 最基本,幾乎都會使用;多一個超參數 |
| Dropout | 訓練時隨機關閉部分神經元 | 在電腦視覺等大型網路中效果顯著 |
| 資料擴增 | 對訓練資料做不改變標籤的變換 | 近似免費增加資料,但需要額外的設計與運算 |
| 提早停止 | 開發集誤差開始上升時停止訓練 | 簡單,但同時影響偏誤與變異,不符合正交化 |
9.2L2 與 L1 懲罰Weight Penalties
L2 正則化
以二元分類的交叉熵成本函數為例,加入 L2 懲罰後的成本函數為:
其中
反向傳播時,懲罰項對
為什麼稱為權重衰減
把這個梯度代入更新式並整理:
每一步在做一般的梯度更新之前,都先把權重乘上一個略小於 1 的係數
為什麼能減少過擬合
L2 與 L1 的比較
| 懲罰 | 形式 | 對權重的效果 | 特性 |
|---|---|---|---|
| L2 | 權重整體變小,但很少剛好為 0 | 沒有特徵選擇效果;預設選擇 | |
| L1 | 部分權重變成剛好為 0 | 稀疏解,有特徵選擇效果 |
兩者的差異來自梯度。L2 懲罰的梯度與權重本身成正比,權重越接近 0,被推回去的力量就越小,所以權重只會變小、很少歸零。L1 懲罰(
9.3丟棄法Dropout
丟棄法(dropout)在每一次訓練迭代中,讓每個神經元以機率
反向 dropout 的實作
最常見的實作方式是反向 dropout(inverted dropout)。以某一層的激勵值 a 為例:
import numpy as np
keep_prob = 0.8 # 每個神經元被保留的機率
# 前向傳播
d = np.random.rand(*a.shape) < keep_prob # 布林遮罩,約 80% 為 True
a = a * d / keep_prob # 關掉部分神經元,並放大其餘的值
# 反向傳播:使用同一個遮罩
da = da * d / keep_prob
除以 keep_prob 是關鍵:保留下來的神經元輸出被放大
測試時不使用 dropout
測試或部署時不使用 dropout:若預測時也隨機關閉神經元,同一筆資料每次會得到不同的預測結果。由於訓練時已經用
為什麼有效
從單一神經元的角度來看,它的任何一個輸入都可能隨時消失,因此不能把權重押在少數幾個輸入上,而必須把權重分散到許多輸入。權重分散的結果,是權重的平方和變小,效果與 L2 正則化類似。另一個角度是:每次迭代訓練不同的子網路,最後的完整網路可以看成大量子網路的近似平均,帶有集成(ensemble)的效果。
不同層可以設定不同的保留機率:參數多、容易過擬合的層(例如大型全連接層)可用較低的
9.4資料擴增與提早停止Data Augmentation & Early Stopping
資料擴增
收集更多資料是降低變異最可靠的方法,但成本很高。資料擴增(data augmentation)是在現有資料上做不改變標籤的變換,產生額外的訓練樣本。以影像為例,常見的做法包括:
- 水平翻轉
- 隨機裁切(random crop)與縮放
- 小角度旋轉
- 色彩擾動(color jitter):隨機調整亮度、對比與飽和度
擴增出來的資料提供的資訊不如真正的新資料(翻轉後的貓仍是同一隻貓),但幾乎不花收集成本。要注意變換必須合理:例如辨識文字或數字時,水平翻轉會產生不存在的字元;醫學影像的左右方向本身可能就具有意義。設計適合任務的擴增方式需要領域知識與人工嘗試,大量擴增也會增加訓練時間。
提早停止
訓練時同時記錄訓練集與開發集的誤差。隨著迭代次數增加,訓練誤差持續下降,開發集誤差則通常先下降、再開始上升。提早停止(early stopping)就是在開發集誤差最低時停止訓練,或回到當時保存的參數。由於權重從接近 0 的初始值開始,通常越訓練越大,提早停止可以讓權重維持在中等大小,效果與 L2 正則化相近。它的好處是只需要訓練一次,就能沿著訓練過程掃過「不同強度的正則化」,不必像 L2 那樣嘗試許多個
9.5超參數調校Hyperparameter Tuning
神經網路的超參數很多,而且沒有一組放諸四海皆準的最佳設定:不同領域、不同資料集,甚至同一個問題在資料量或硬體改變之後,最佳值都可能不同。經驗非常寶貴,但同樣重要的是有系統的搜尋方法。至於偏誤或變異過高時應優先調整哪些旋鈕,請見第 1 章。
符號與重要性
描述網路中某一個數值時,常用的符號是
| 超參數 | 符號 | 優先順序 |
|---|---|---|
| 學習率 | 第一優先 | |
| 動量係數 | 第二優先 | |
| 小批次大小 | 第二優先 | |
| 隱藏單元數 | 第二優先 | |
| 隱藏層數 | 第三優先 | |
| 學習率衰減 | 衰減率 |
第三優先 |
| Adam 的 |
— | 通常使用預設值 |
學習率幾乎總是最重要的一個:它設定錯誤時,其他超參數再怎麼調整也無濟於事。
隨機搜尋優於網格搜尋
網格搜尋(grid search)在每個超參數上取幾個固定值,再試遍所有組合;隨機搜尋(random search)則在範圍內隨機抽樣組合。超參數很多時,隨機搜尋明顯較有效率(Bergstra & Bengio, 2012),原因是我們事先不知道哪個超參數最重要。假設要調整
找到表現較好的區域後,可以縮小範圍,在該區域內更密集地抽樣,這稱為由粗到細(coarse to fine)的搜尋。
在對數尺度上抽樣
隨機抽樣不代表要在範圍內均勻抽樣。例如學習率的合理範圍是
動量係數
兩種調校風格
運算資源有限時,可以專心照顧單一模型:每天觀察學習曲線,逐步調整學習率等設定。資源充足時,則可以同時平行訓練大量不同設定的模型,最後挑出表現最好的一個。Andrew Ng 把這兩種方式分別比喻為熊貓(panda,一次只照顧一隻幼獸)與魚子醬(caviar,一次產下大量魚卵)。
9.6梯度檢查Gradient Checking
自行實作反向傳播時很容易寫錯,而且這類錯誤不一定會讓訓練失敗,只是讓模型學得比較差,很難察覺。梯度檢查(gradient checking)以數值微分來驗證反向傳播算出的梯度是否正確。
中央差分
把所有參數(各層的
這是中央差分(centered difference),誤差為
判斷標準
把數值梯度
使用相對誤差而非絕對差距,是為了不受梯度本身大小的影響。
| 相對誤差 | 判斷 |
|---|---|
| 約 |
正確 |
| 約 |
可能有問題,需要逐一檢查各分量 |
| 約 |
很可能有錯誤 |
若檢查失敗,可以找出差距最大的分量,看它們集中在哪一層、屬於
注意事項
- 只用於除錯:每個分量都需要兩次前向傳播,參數有數百萬個時非常慢。確認正確之後就關閉,不要在訓練過程中執行。
- 記得包含正則化項:如果成本函數含有 L2 懲罰,
與 都必須把它算進去。 - 不能搭配 dropout:dropout 讓
每次計算的結果都不同,數值梯度失去意義。檢查時先把 keep_prob 設為 1,確認無誤後再開啟 dropout。 - 使用雙精度浮點數:
很小時,單精度的捨入誤差可能蓋過真正的差距。
9.7實務技巧Training Tips
以下是訓練神經網路時值得養成的習慣:
- 每個 epoch 重新打亂資料:若每次都以相同順序切出小批次,梯度估計會帶有資料順序造成的偏差。每個 epoch 開始前重新洗牌(shuffle),讓每次的小批次組合都不同。
- 訓練多少個 epoch:30 個 epoch 可以作為初次嘗試的起點,但並非固定規則。資料量、模型大小與學習率排程都會影響需要的 epoch 數,應以開發集的學習曲線判斷是否已經收斂。
- 遷移學習(transfer learning):自己的資料不多時,先用在大型資料集(例如 ImageNet)上預訓練好的權重初始化模型,再以自己的資料微調(fine-tune)。這通常比從頭訓練快得多,效果也更好(見第 10 章)。
- 保存檢查點並重新啟動:定期保存模型參數(checkpoint),訓練中斷時就能從最近的檢查點繼續,不必從頭開始;也可以從表現好的檢查點出發,調整設定後重新訓練幾次,比較結果。
集成與多重裁切
模型集成(model ensembling)是獨立訓練多個模型,預測時取它們輸出的平均;多重裁切(multi-crop)則是在測試時對同一張影像取多個裁切版本(例如四個角落與中央,再加上它們的水平翻轉,共 10 張),分別預測後取平均。兩者通常能讓準確率再提升一些,在競賽與學術基準測試中很常見。
9.8GPU 記憶體GPU Memory
訓練深度網路時,GPU 記憶體常常是最先碰到的限制。需要放進記憶體的內容包括:
- 模型參數:例如 VGG-16 約有 1.38 億個參數,以 32 位元浮點數儲存約需 550 MB。
- 梯度與最佳化器狀態:梯度與參數一樣大;動量法另需一份速度,Adam 則需要兩份(一階與二階動差)。
- 中間激勵值:反向傳播需要用到前向傳播時每一層的輸出,這部分與批次大小成正比,在大型卷積網路中通常佔最多。
以 2019 年前後常見的訓練環境為例,VGG-16 所需的 GPU 記憶體大約如下:
| 網路 | 批次大小 | 所需 GPU 記憶體(約) |
|---|---|---|
| VGG-16 | 64 | 8 GB |
| VGG-16 | 128 | 14 GB |
這些數字會隨框架、輸入尺寸與實作方式而不同,只能作為數量級的參考;但可以看出,批次大小加倍時記憶體需求大幅增加,增加的部分主要來自激勵值。
記憶體不足時,可以考慮以下做法:
- 縮小批次大小:最直接的方法。若希望維持原本的有效批次大小,可以使用梯度累積(gradient accumulation),累積數個小批次的梯度後才更新一次參數。批次大小改變時,學習率通常也需要重新調整。
- 縮小模型:減少層數或通道數,或改用參數效率較高的架構。
- 分散到多張 GPU:資料平行(data parallelism)讓每張 GPU 持有一份完整模型、各自處理批次的一部分;模型大到單張 GPU 放不下時,則用模型平行(model parallelism)把不同的層放到不同的 GPU 上。
此外,混合精度訓練(mixed precision training)以 16 位元浮點數儲存激勵值並進行大部分運算,只在需要精度的地方保留 32 位元,能大幅降低記憶體用量並加快運算,是現今訓練大型模型的標準做法。
9.9參考資料References
- Goodfellow, Bengio & Courville, Deep Learning, MIT Press, 2016,第 7 章 Regularization for Deep Learning、第 11 章 Practical Methodology。
- Srivastava, Hinton, Krizhevsky, Sutskever & Salakhutdinov, "Dropout: A Simple Way to Prevent Neural Networks from Overfitting", JMLR, 2014。
- Bergstra & Bengio, "Random Search for Hyper-Parameter Optimization", JMLR, 2012。
- Loshchilov & Hutter, "Decoupled Weight Decay Regularization", ICLR 2019。
- Simonyan & Zisserman, "Very Deep Convolutional Networks for Large-Scale Image Recognition", ICLR 2015(VGG-16)。
- Micikevicius et al., "Mixed Precision Training", ICLR 2018。
- deeplearning.ai, Improving Deep Neural Networks: Hyperparameter Tuning, Regularization and Optimization(Coursera 深度學習專項課程第二門課);Stanford CS231n 課程筆記(梯度檢查)。