最近拜讀大神Karpathy的經驗之談 A Recipe for Training Neural Networks https://karpathy.github.io/2019/04/25/recipe/,這個祕籍對不少深度學習算法訓練過程當中遇到的各自問題進行了總結,並提出了不少很好的建議,翻譯於此,但願可以幫助更多人學到這些內容。python
譯文以下:git
幾周前,我發佈了一條關於「最多見的神經網絡錯誤」的推文,列出了一些與訓練神經網絡相關的常見問題。這條推文獲得了比我預期的要多得多的認同(包括網絡研討會:))。顯然,不少人我的遇到了「卷積層是這樣工做的」和「咱們的卷積網絡達到最早進結果」之間的巨大差距。github
因此我認爲若是清空我塵土飛揚的博客並將這個推文擴展到這個主題應該獲得的長篇形式應該是有趣的事情。然而,與其列舉常見的錯誤或深刻分析它們,我更想深刻挖掘並討論如何避免出現這些錯誤(或者很是快速地修復它們)。這樣作的關鍵是遵循某個過程,據我所知,這個過程並無文檔記錄下來。讓咱們從促使我作這個的兩個重要發現開始吧。算法
據稱很容易開始訓練神經網絡。許多圖書和框架都以展現了若是採用30行代碼解決您的數據問題,並以此而自豪。這給你們一個很是錯誤的印象,即這些東西是即插即用。常見的示例代碼以下:api
>>> your_data = # 導入數據 >>> model = SuperCrossValidator(SuperDuper.fit, your_data, ResNet50, SGDOptimizer) # 由此征服世界這些
這些庫和示例激活了咱們大腦裏面熟悉標準軟件的部分 - 一般它們認爲乾淨和抽象的API是能夠輕易得到的。 好比,後面的功能能夠採用以下調用:網絡
>>> r = requests.get('https://api.github.com/user', auth=('user', 'pass')) >>> r.status_code 200
這很酷! 一個勇敢的開發人員已經承擔了理解查詢字符串,URL,GET / POST請求,HTTP鏈接等等的負擔,而且在很大程度上隱藏了幾行代碼背後的複雜性。 這偏偏是咱們熟悉和期待的。 不幸的是,神經網不是那樣的。 它們不是「現成的」技術,第二個與訓練ImageNet分類器略有不一樣。 我試圖在個人帖子「是的你應該理解反向傳播」中經過反向傳播的例子說明這一點,並將其稱爲「漏洞抽象」,但不幸的是狀況更加可怕。 Backprop + SGD並無神奇地讓你的網絡正常工做。 Batch Norm也不會神奇地使其收斂得更快。RNN不會神奇地讓你「插入」文本。 只是由於你能夠將你的問題採用加強學習來建模,並不意味着你應該如此。 若是您堅持使用該技術而不瞭解其工做原理,則可能會失敗。 這讓我想到......架構
當您寫錯或錯誤配置代碼時,您一般會遇到某種異常。你輸入了一個整數,但這原本應該是一個字符串的!某函數只須要3個參數!導入失敗!鍵值不存在!兩個列表中的元素個數不相等。此外,一般不會爲特定功能建立單元測試。框架
解決了這些問題,也只是訓練神經網絡的開始。一切均可以在語法上正確,但整個訓練沒有妥善安排,並且很難說清楚。 「可能的錯誤面」是很大的,邏輯(與語法相反)層面的問題,而且對單元測試很是棘手。例如,在數據加強期間左右翻轉圖像時,您可能忘記翻轉數據標籤。您的網絡仍然能夠(使人震驚地)工做得很是好,由於您的網絡能夠在內部學習檢測翻轉的圖像,而後左右翻轉其預測。或許你的自迴歸模型會由於一個偶然錯誤而意外地將它想要預測的東西做爲輸入。或者你想要修剪你的梯度可是修剪了損失,致使在訓練期間異常樣本被忽略。或者您從預訓練模型初始化了您的權重,但沒有使用原始均值。或者你只是用錯了正則化權重,學習率,衰減率,模型大小等。所以,錯誤設置的神經網絡只有在你運氣好的時候纔會拋出異常;大部分時間它會訓練,但默默地輸出看起來有點糟糕的結果。函數
所以,「快速和激烈」方法訓練的神經網絡並不能發揮其做用,咱們只會遭受其痛苦。 如今,痛苦是讓神經網絡運做良好的一個很是天然的過程,但能夠經過對訓練過程當中的全部細節瞭然於胸來減輕訓練過程的折磨。 在個人經驗中,與深度學習成功最相關的品質是耐心和對細節的關注。單元測試
鑑於上述兩個事實,我已經爲本身開發了一個特定的過程,使我可以將神經網絡應用於新問題。稍後我會竭力描述如何作到的。 你會發現它很是重視上述兩個原則。 特別是,它遵循從簡單到複雜的規律,而且在每一步咱們對將要發生的事情作出具體假設,而後經過實驗驗證它們或進行檢查直到咱們發現了問題。 咱們試圖防止的是同時引入了許多複雜「未經驗證的」問題,這必然會致使須要花不少時間去查找的錯誤/錯誤配置。 若是編寫您的神經網絡代碼就像訓練同樣,您須要使用很是小的學習速率並猜想,而後在每次迭代後評估整個的測試集。
訓練神經網絡的第一步是根本不是接觸任何神經網絡代碼,而是從完全檢查數據開始。這一步相當重要。我喜歡花費大量時間(以小時爲單位)掃描數千個示例,瞭解它們的分佈並尋找模式。幸運的是,你的大腦很是擅長這一點。有一次我發現了數據中包含重複的例子。另外一次我發現了錯誤的圖像/標籤對。我一般會尋找不均衡的數據,也會關注本身對數據的分類過程,這些過程暗示了咱們最終會嘗試的各類架構。例如 -咱們須要局部特徵仍是全局上下文?數據有多少變化,這些變化採起什麼形式?什麼變化是假的,是能夠預處理的?空間位置是否重要,或者咱們是否想要將其平均化?細節有多重要,咱們能夠在多大程度上對圖像進行下采樣?標籤有多少噪聲?
此外,因爲神經網絡實際上能夠看做壓縮/編譯的數據集,所以您將可以查看網絡的(錯誤)預測並瞭解它們的來源。若是你的網絡給你的預測看起來與你在數據中看到的內容不一致,那麼就會有所收穫。
一旦得到定性的感知,編寫一些簡單的代碼來搜索/過濾/排序也是一個好主意,不管你能想到什麼(例如標籤的類型、大小、數量等),並可視化它們的分佈,和沿任何座標軸的異常值。異常值尤爲能揭示數據質量或預處理中的一些錯誤。
當咱們瞭解了數據以後,咱們能夠採用咱們超級精彩的多尺度ASPP FPN ResNet訓練牛X的模型嗎? 答案是不。 這是一條充滿痛苦的道路。 咱們的下一步是創建一個完整的訓練+評估框架,並經過一系列實驗驗證其正確性。在這個階段,最好選擇一些你能正確使用的簡單模型 - 例如 線性分類器,或很是小的ConvNet。 咱們但願對其進行訓練,可視化損失,任何其餘指標(例如準確度),模型預測,並在此過程當中使用明確的假設進行一系列實驗。
這個階段的須要注意的地方和建議主要包括: