我們常說調參,但具體調的是什么,在此做一份總結:
超參數是我們控制我們模型結構、功能、效率等的 調節旋鈕,具體有哪些呢:
- 學習率
- epoch 迭代次數
- 隱藏層
- 激活函數
- batch size
- 優化器,如:Adam,SGD……
學習率 大 | 學習率 小 | |
學習速度 | 塊 | 慢 |
使用時間點 | 剛開始訓練時 | 一定epoch后 |
副作用 | 容易發生損失值爆炸, 結果容易震盪,不容易收斂 | 容易過擬合,收斂速度慢 |
學習率設置原則(在這主要以遷移學習為主):
由於模型已經在原始數據上收斂,所以應該設置較小學習率,在新數據上微調。若非遷移學習則先將學習率設置在0.01~0.001為宜,一定輪數之后再逐漸減緩,接近訓練結束學習率的衰減應在100倍以上。
目標函數損失值 曲線(理想狀態應該為綠色滑梯式下降曲線):
- 曲線 初始時 上揚 【紅線】:
Solution:初始 學習率過大 導致 振盪,應減小學習率,並 從頭 開始訓練 。 - 曲線 初始時 強勢下降 沒多久 歸於水平 【紫線】:
Solution:后期 學習率過大 導致 無法擬合,應減小學習率,並 重新訓練 后幾輪 。 - 曲線 全程緩慢 【黃線】:
Solution:初始 學習率過小 導致 收斂慢,應增大學習率,並 從頭 開始訓練 。
初始化
當用normal初始化cnn的參數時,最后acc只能到70%多,僅僅改成xavier,acc可以到98%。
還有一次給word embedding初始化,最開始使用了TensorFlow中默認的initializer(即glorot_uniform_initializer,也就是大家經常說的無腦使用xavier),訓練速度慢不說,結果也不好。改為uniform,訓練速度飆升,結果也飆升。
鏈接:https://www.zhihu.com/question/25097993/answer/127472322
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
一些大的注意事項:
1. 剛開始, 先上小規模數據, 模型往大了放, 只要不爆顯存, 能用256個filter你就別用128個. 直接奔着過擬合去. 沒錯, 就是訓練過擬合網絡, 連測試集驗證集這些都可以不用.
為什么?
+ 你要驗證自己的訓練腳本的流程對不對. 這一步小數據量, 生成速度快, 但是所有的腳本都是和未來大規模訓練一致的(除了少跑點循環)
+ 如果小數據量下, 你這么粗暴的大網絡奔着過擬合去都沒效果. 那么, 你要開始反思自己了, 模型的輸入輸出是不是有問題? 要不要檢查自己的代碼(永遠不要懷疑工具庫, 除非你動過代碼)? 模型解決的問題定義是不是有問題? 你對應用場景的理解是不是有錯? 不要懷疑NN的能力, 不要懷疑NN的能力, 不要懷疑NN的能力. 就我們調參狗能遇到的問題, NN沒法擬合的, 這概率是有多小?
+ 你可以不這么做, 但是等你數據准備了兩天, 結果發現有問題要重新生成的時候, 你這周時間就醬油了.
2. Loss設計要合理.
+ 一般來說分類就是Softmax, 回歸就是L2的loss. 但是要注意loss的錯誤范圍(主要是回歸), 你預測一個label是10000的值, 模型輸出0, 你算算這loss多大, 這還是單變量的情況下. 一般結果都是nan. 所以不僅僅輸入要做normalization, 輸出也要這么弄.
+ 多任務情況下, 各loss想法限制在一個量級上, 或者最終限制在一個量級上, 初期可以着重一個任務的loss
3. 觀察loss勝於觀察准確率
准確率雖然是評測指標, 但是訓練過程中還是要注意loss的. 你會發現有些情況下, 准確率是突變的, 原來一直是0, 可能保持上千迭代, 然后突然變1. 要是因為這個你提前中斷訓練了, 只有老天替你惋惜了. 而loss是不會有這么詭異的情況發生的, 畢竟優化目標是loss.
給NN一點時間, 要根據任務留給NN的學習一定空間. 不能說前面一段時間沒起色就不管了. 有些情況下就是前面一段時間看不出起色, 然后開始穩定學習.
4. 確認分類網絡學習充分
分類網絡就是學習類別之間的界限. 你會發現, 網絡就是慢慢的從類別模糊到類別清晰的. 怎么發現? 看Softmax輸出的概率的分布. 如果是二分類, 你會發現, 剛開始的網絡預測都是在0.5上下, 很模糊. 隨着學習過程, 網絡預測會慢慢的移動到0,1這種極值附近. 所以, 如果你的網絡預測分布靠中間, 再學習學習.
5. Learning Rate設置合理
+ 太大: loss爆炸, 或者nan
+ 太小: 半天loss沒反映(但是, LR需要降低的情況也是這樣, 這里可視化網絡中間結果, 不是weights, 有效果, 倆者可視化結果是不一樣的, 太小的話中間結果有點水波紋或者噪點的樣子, 因為filter學習太慢的原因, 試過就會知道很明顯)
+ 需要進一步降低了: loss在當前LR下一路降了下來, 但是半天不再降了.
+ 如果有個復雜點的任務, 剛開始, 是需要人肉盯着調LR的. 后面熟悉這個任務網絡學習的特性后, 可以扔一邊跑去了.
+ 如果上面的Loss設計那塊你沒法合理, 初始情況下容易爆, 先上一個小LR保證不爆, 等loss降下來了, 再慢慢升LR, 之后當然還會慢慢再降LR, 雖然這很蛋疼.
+ LR在可以工作的最大值下往小收一收, 免得ReLU把神經元弄死了. 當然, 我是個心急的人, 總愛設個大點的.
6 對比訓練集和驗證集的loss
判斷過擬合, 訓練是否足夠, 是否需要early stop的依據, 這都是中規中矩的原則, 不多說了.
7 清楚receptive field的大小
CV的任務, context window是很重要的. 所以你對自己模型的receptive field的大小要心中有數. 這個對效果的影響還是很顯著的. 特別是用FCN, 大目標需要很大的receptive field. 不像有fully connection的網絡, 好歹有個fc兜底, 全局信息都有.
- 預處理: -mean/std zero-center就夠了, PCA, 白化什么的都用不上. 我個人觀點, 反正CNN能學習encoder, PCA用不用其實關系不大, 大不了網絡里面自己學習出來一個.
- shuffle, shuffle, shuffle.
- 網絡原理的理解最重要, CNN的conv這塊, 你得明白sobel算子的邊界檢測.
- Dropout, Dropout, Dropout(不僅僅可以防止過擬合, 其實這相當於做人力成本最低的Ensemble, 當然, 訓練起來會比沒有Dropout的要慢一點, 同時網絡參數你最好相應加一點, 對, 這會再慢一點).
- CNN更加適合訓練回答是否的問題, 如果任務比較復雜, 考慮先用分類任務訓練一個模型再finetune.
- 無腦用ReLU(CV領域).
- 無腦用3x3.
- 無腦用xavier.
- LRN一類的, 其實可以不用. 不行可以再拿來試試看.
- filter數量2^n.
- 多尺度的圖片輸入(或者網絡內部利用多尺度下的結果)有很好的提升效果.
- 第一層的filter, 數量不要太少. 否則根本學不出來(底層特征很重要).
- sgd adam 這些選擇上, 看你個人選擇. 一般對網絡不是決定性的. 反正我無腦用sgd + momentum.
- batch normalization我一直沒用, 雖然我知道這個很好, 我不用僅僅是因為我懶. 所以要鼓勵使用batch normalization.
- 不要完全相信論文里面的東西. 結構什么的覺得可能有效果, 可以拿去試試.
- 你有95%概率不會使用超過40層的模型.
- shortcut的聯接是有作用的.
- 暴力調參最可取, 畢竟, 自己的生命最重要. 你調完這個模型說不定過兩天這模型就扔掉了.
- 機器, 機器, 機器.
- Google的inception論文, 結構要好好看看.
- 一些傳統的方法, 要稍微了解了解. 我自己的程序就用過1x14的手寫filter, 寫過之后你看看inception里面的1x7, 7x1 就會會心一笑...
- ensemble:
- 將不同的經典網絡提取出的特征向量,假設
VGG16
提取出的特征向量維度是[N,c1]
,ResNet50
提取的特征向量維度是[N,c2]
,Xception
提取的特征向量維度是[N, c3]
,那么我們可以使用三個系數a、b、c
將其組合為形狀為[N, a*c1+b*c2+c*c3]
,其中a、b、c
三個參數的取值代表我們使用哪個模型的特征多一些,如果是分類回歸比賽,我們在后面接特征處理網絡就可以了。可以取不同的a、b、c
得到不同的特征,然后對結果做voting
,soft-voting
等多種處理,一般結果不會太差啦。 - 可以使用不同的初始化方式訓練出模型,然后做ensemble。
- 可以使用用不同超參數(如學習率,
batch_size
,優化器)訓練出不同模型,然后做ensemble。
為什么你的模型效果這么差?
為什么別人的模型都能快速達到較低的錯誤率,而你的模型錯誤率卻居高不下。
造出這種現象的原因可以分為4大類:
1、模型實現中的bug:比如標簽錯誤的問題。
2、超參數選擇不合適:模型對超參數很敏感,學習率太高或太低都不行。
3、數據模型不適配:比如你要訓練一個自動駕駛圖像識別的模型,用ImageNet數據集來訓練就不合適。
4、數據集的構造問題:沒有足夠數據、分類不均衡、有噪聲的標簽、訓練集合測試集分布不同。
深度學習debug的流程策略
針對上面的問題,小哥總結出調試深度學習模型的第一要義——悲觀主義。
既然消除模型中的錯誤很難,我們不如先從簡單模型入手,然后逐漸增加模型的復雜度。
他把這個過程分為5個步驟:
- 從最簡單模型入手;
- 成功搭建模型,重現結果;
- 分解偏差各項,逐步擬合數據;
- 用由粗到細隨機搜索優化超參數;
- 如果欠擬合,就增大模型;如果過擬合,就添加數據或調整。
從簡單模型開始
在這一步之前,假定你已經有了初始的測試集、需要改進的單一指標、基於某種標准的模型目標性能。
首先,選擇一個簡單的架構。比如,你的輸入是圖片就選擇類似LeNet的架構,輸入是語言序列就選擇有一個隱藏層的LSTM。
模型推薦的默認設置:
- Adam優化器學習速率3e-4
- 激活函數選用ReLU或tanh
- ReLU初始化推薦使用He normal,tanh初始化推薦使用Glorot normal
為了簡化問題,我們從一個只有1萬樣本的數據集開始訓練,數據的特點包括:固定數量的目標、分類、更小的圖片尺寸。由此創建一個簡單的合成訓練集。
開始搭建深度學習模型
在搭建模型之前,有(Implement)5種最常見的bug:
- 錯誤的張量形狀;預處理輸入錯誤;損失函數錯誤輸入;忘記設置正確的訓練模型;錯誤的數據類型。
- 為了防止這些錯誤發生,給出的建議是:盡可能減少代碼的行數,使用現成的組件,然后再構建復雜的數據pipeline。
- 運行模型后,你可能會遇到形狀不匹配、數據類型錯誤、內存不足等等問題。
- 對於第一個問題,可以在調試器中逐步完成模型創建和推理。數據類型錯誤是由於沒有把其他類型數據轉化成float32,內存不足是因為張量或者數據集太大。
評估
下面我們開始用錯誤率評估模型的性能。
測試集錯誤率 = 錯誤率下限 + 偏移 + 方差 + 分布偏差 + 驗證集過擬合
為了處理訓練集和測試集分布的偏差,我們使用兩個驗證數據集,一個樣本來自訓練集,一個樣本來自測試集。
改進模型和數據
上一步中粗略搭建的模型錯誤率仍然相當高,我們應該如何改進?
讓我們先用以下方法解決欠擬合的問題:
讓模型更大(比如加入更多的層,每層中使用更多的單元);減少正規化;錯誤分析;選擇另一種性能更好的模型架構;調節超參數;加入更多特征。
首先,我們給模型加入更多的層,轉換到ResNet-101,調節學習率,使訓練集錯誤率降低到0.8%。

在出現過擬合后,我們可以增加訓練集的樣本量解決這個問題,把圖片數量擴大到25萬張。
經歷過優化參數、權重衰減、數據增強等一系列操作后,我們終於把測試錯誤率降低到目標值。
接下來我們着手解決訓練集和測試集的分布偏差問題。
分析測試驗證集錯誤率,收集或者合成更多訓練數據彌補二者的偏差。比如下面的自動駕駛目標識別模型,訓練完成后,讓它判斷圖片里有沒有人,常常發生錯誤。
經過分析得出,訓練集缺乏夜晚場景、反光等情況。后續將在訓練集中加入此類數據糾正偏差。
另一種修正錯誤率的方法稱為領域適配,這是一種使用未標記或有限標記數據進行訓練的技術。它能在源分布上進行訓練,並將其推廣到另一個“目標”。
超參數優化
這是調試的最后一步,我們需要選取那些更敏感的超參數,下圖是模型對不同超參數的敏感性:
常用的超參數優
化方法有:手動優化、網格搜索、隨機搜索、由粗到細、貝葉斯優化。
你可以手動優化超參數,但是耗時而且需要理解算法的細節。Josh推薦的方法是由粗到細的隨機搜索、貝葉斯優化。
由粗到細的隨機搜索可以縮小超高性能參數的范圍,缺點是由一些手動的操作。貝葉斯優化是優化超參數最有效一種無需手動干涉的方式,具體操作請參考: