半天2k贊,李飛飛高徒發布33條神經網絡訓練秘技
本文經AI新媒體量子位(公眾號ID:QbitAI)授權轉載,轉載請聯系出處。
同學,現在有一份33條神經網絡訓練秘笈,擺在你面前。
AI大佬Andrej Karpathy (簡稱AK) ,剛剛發布了一篇長長長長博客,苦口婆心地列舉了33條技巧和注意事項,全面避免大家踩坑,已有2,300多贊。
AK在斯坦福讀博的時候,是飛飛實驗室的成員,畢業去了OpenAI,然后又成了特斯拉的AI負責人,直到如今。
他的博客雖然一年一更,但一字一句皆是皆是多年心血凝結而成,每次更新必有重大回響。
有生之年,我們把內文翻譯如下:
訓練模型的“處方”
總的來說,Andrej Karpathy的技巧就是:不要心急 (文章結尾會道出原因) ,從簡單到復雜逐步完善你的神經網絡。
1、先別著急寫代碼
訓練神經網絡前,別管代碼,先從預處理數據集開始。我們先花幾個小時的時間,了解數據的分布并找出其中的規律。
Andrej有一次在整理數據時發現了重復的樣本,還有一次發現了圖像和標簽中的錯誤。所以先看一眼數據能避免我們走很多彎路。
由于神經網絡實際上是數據集的壓縮版本,因此您將能夠查看網絡(錯誤)預測并了解它們的來源。如果你的網絡給你的預測看起來與你在數據中看到的內容不一致,那么就會有所收獲。
一旦從數據中發現規律,可以編寫一些代碼對他們進行搜索、過濾、排序。把數據可視化能幫助我們發現異常值,而異常值總能揭示數據的質量或預處理中的一些錯誤。
2、設置端到端的訓練評估框架
處理完數據集,接下來就能開始訓練模型了嗎?并不能!下一步是建立一個完整的訓練+評估框架。
在這個階段,我們選擇一個簡單又不至于搞砸的模型,比如線性分類器、CNN,可視化損失。獲得準確度等衡量模型的標準,用模型進行預測。
這個階段的技巧有:
· 固定隨機種子
使用固定的隨機種子,來保證運行代碼兩次都獲得相同的結果,消除差異因素。
· 簡單化
在此階段不要有任何幻想,不要擴增數據。擴增數據后面會用到,但是在這里不要使用,現在引入只會導致錯誤。
· 在評估中添加有效數字
在繪制測試集損失時,對整個測試集進行評估,不要只繪制批次測試損失圖像,然后用Tensorboard對它們進行平滑處理。
· 在初始階段驗證損失函數
驗證函數是否從正確的損失值開始。例如,如果正確初始化一層,則應在softmax初始化時測量-log(1/n_classes)。
· 初始化
正確初始化一層的權重。如果回歸一些平均值為50的值,則將最終偏差初始化為50。如果有一個比例為1:10的不平衡數據集,請設置對數的偏差,使網絡預測概率在初始化時為0.1。正確設置這些可以加速模型的收斂。
· 人類基線
監控除人為可解釋和可檢查的損失之外的指標。盡可能評估人的準確性并與之進行比較。或者對測試數據進行兩次注釋,并且對于每個示例,將一個注釋視為預測,將第二個注釋視為事實。
· 設置一個獨立于輸入的基線
最簡單的方法是將所有輸入設置為零,看看模型是否學會從輸入中提取任何信息。
· 過擬合一個batch
增加了模型的容量并驗證我們可以達到的損失。
· 驗證減少訓練損失
嘗試稍微增加數據容量。
· 在訓練模型前進行數據可視化
將原始張量的數據和標簽可視化,可以節省了調試次數,并揭示了數據預處理和數據擴增中的問題。
· 可視化預測動態
在訓練過程中對固定測試批次上的模型預測進行可視化。
· 使用反向傳播來獲得依賴關系:
一個方法是將第i個樣本的損失設置為1.0,運行反向傳播一直到輸入,并確保僅在第i個樣本上有非零的梯度。
· 概括一個特例:對正在做的事情編寫一個非常具體的函數,讓它運行,然后在以后過程中確保能得到相同的結果。
3、過擬合
首先我們得有一個足夠大的模型,它可以過擬合,減少訓練集上的損失,然后適當地調整它,放棄一些訓練集損失,改善在驗證集上的損失)。
這一階段的技巧有:
· 挑選模型
為了獲得較好的訓練損失,我們需要為數據選擇合適的架構。不要總想著一步到位。如果要做圖像分類,只需復制粘貼ResNet-50,我們可以在稍后的過程中做一些自定義的事。
· Adam方法是安全的
在設定基線的早期階段,使用學習率為3e-4的Adam 。根據經驗,亞當對超參數更加寬容,包括不良的學習率。
· 一次只復雜化一個
如果多個信號輸入分類器,建議逐個輸入,然后增加復雜性,確保預期的性能逐步提升,而不要一股腦兒全放進去。比如,嘗試先插入較小的圖像,然后再將它們放大。
· 不要相信學習率衰減默認值
如果不小心,代碼可能會過早地將學習率減少到零,導致模型無法收斂。我們完全禁用學習率衰減避免這種狀況的發生。
4、正則化
理想的話,我們現在有一個大模型,在訓練集上擬合好了。
現在,該正則化了。舍棄一點訓練集上的準確率,可以換取驗證集上的準確率。
這里有一些技巧:
· 獲取更多數據
至今大家最偏愛的正則化方法,就是添加一些真實訓練數據。
不要在一個小數據集花太大功夫,試圖搞出大事情來。有精力去多收集點數據,這是一個確保性能單調提升的方法。
· 數據擴增
把數據集做大,除了繼續收集數據之外,就是擴增了。旋轉,翻轉,拉伸,做擴增的時候可以野性一點。
· 有創意的擴增
還有什么辦法擴增數據集?比如域隨機化 (Domain Randomization) ,模擬 (Simulation) ,巧妙的混合 (Hybrids) ,比如把數據插進場景里去。甚至可以用上GAN。
· 預訓練
當然,就算你手握充足的數據,直接用預訓練模型也沒壞處。
· 跟監督學習死磕
不要對無監督預訓練太過興奮了。至少在視覺領域,無監督到現在也沒有非常強大的成果。雖然,NLP領域有了BERT,有了會講故事的GPT-2,但我們看到的效果很大程度上還是經過了人工挑選。
· 輸入低維一點
把那些可能包含虛假信號的特征去掉,因為這些東西很可能造成過擬合,尤其是數據集不大的時候。
同理,如果低層細節不是那么重要的話,就輸入小一點的圖片,捕捉高層信息就好了。
· 模型小一點
許多情況下,都可以給網絡加上領域知識限制 (Domain Knowledge Constraints) ,來把模型變小。
比如,以前很流行在ImageNet的骨架上放全連接層,但現在這種操作已經被平均池化取代了,大大減少了參數。
·減小批尺寸
對批量歸一化 (Batch Normalization) 這項操作來說,小批量可能帶來更好的正則化效果 (Regularization) 。
· Dropout
給卷積網絡用dropout2d。不過使用需謹慎,因為這種操作似乎跟批量歸一化不太合得來。
· 權重衰減
增加權重衰減 (Weight Decay) 的懲罰力度。
· 早停法
不用一直一直訓練,可以觀察驗證集的損失,在快要過擬合的時候,及時喊停。
· 也試試大點的模型
注意,這條緊接上條 (且僅接上條) 。
我發現,大模型很容易過擬合,幾乎是必然,但早停的話,模型可以表現很好。
如果想要更加確信,自己訓練出的網絡,是個不錯的分類器,就把權重可視化一下,看看邊緣 (Edges) 美不美。
如果過濾器看起來像噪音,就需要再搞一搞了。同理,激活 (Activations) 有時候也會看出瑕疵來,那樣就要研究一下哪里出了問題。
5、調參
讀到這里,你的AI應該已經開始探索廣闊天地了。這里,有幾件事需要注意。
· 隨機網格搜索
在同時調整多個超參數的情況下,網格搜索聽起來是很誘人,可以把各種設定都包含進來。
但是要記住,隨機搜索更好一些。
直覺上說,這是因為網絡通常對其中一些參數比較敏感,對其他參數不那么敏感。
如果參數a是有用的,參數b起不了什么作用,就應該對a取樣更徹底一些,不要只在幾個固定點上多次取樣。
· 超參數優化
世界上,有許多許多靚麗的貝葉斯超參數優化工具箱,很多小伙伴也給了這些工具好評。
但我個人的經驗是,State-of-the-Art都是用實習生做出來的 (誤) 。
6、還能怎么壓榨**
當你已經找到了好用的架構和好用的超參數,還是有一些技巧,可以在幫你現有模型上獲得更好的結果,榨干潛能:
· 模型合體
把幾個模型結合在一起,至少可以保證提升2%的準確度,不管是什么任務。
如果,你買不起太多的算力,就用蒸餾 (Distill) 把模型們集合成一個神經網絡。
· 放那讓它訓練吧
通常,人類一看到損失趨于平穩,就停止訓練了。
但我感覺,還是訓練得昏天黑地,不知道多久了,比較好。
有一次,我意外把一個模型留在那訓練了一整個寒假。
我回來的時候,它就成了State-of-the-Art。
One More Thing
無獨有偶,前兩天有只“陣亡的程序猿”說:
AWS的錢,不是花在你用了多少,而是花在你忘了關電腦。
同學,如果你也曾經有這樣的經歷,那么恭喜,你也有訓練出State-of-the-Art的潛力。
原文鏈接:
http://karpathy.github.io/2019/04/25/recipe/