當前位置:
首頁 > 新聞 > 深度學習的這些坑你都遇到過嗎?神經網路 11 大常見陷阱及應對方法

深度學習的這些坑你都遇到過嗎?神經網路 11 大常見陷阱及應對方法

總結了11大常見的問題,分析原因並給出應對方法,不可多得的實踐經驗

新智元編譯

來源:theorangeduck.com

作者:Daniel Holden

編譯:劉小芹,文強

【新智元導讀】如果你的神經網路不工作,該怎麼辦?本文作者列舉了搭建神經網路時可能遇到的11個常見問題,包括預處理數據、正則化、學習率、激活函數、網路權重設置等,並提供解決方法和原因解釋,是深度學習實踐的有用資料。

如果你的神經網路不工作,該怎麼辦?作者在這裡列出了建神經網路時所有可能做錯的事情,以及他自己的解決經驗。

1、忘記規範化數據了

問題描述

在使用神經網路時,思考如何正確地規範化數據是非常重要的。這是一個無法改變的步驟——假如這一步驟沒有小心、正確地做,你的網路就幾乎不可能工作。由於這個步驟非常重要,在深度學習社區中也是眾所周知的,所以它很少在論文中被提及,因此初學者常常在這一步出錯。

怎樣解決?

一般來說,規範化(normalization)的意思是:將數據減去均值,再除以其方差。通常這是對每個輸入和輸出特徵單獨做的,但你可能經常會希望對特徵組做或特別主翼處理某些特徵的規範化。

為什麼?

我們需要對數據進行規範化的主要原因是大部分的神經網路流程假設輸入和輸出數據都以一個約是1的標準差和約是0的均值分布。這些假設在深度學習文獻中到處都是,從權重初始化、激活函數到訓練網路的優化演算法。

還需要注意

未訓練的神經網路通常會輸出約在-1到1範圍之間的值。如果你希望輸出其他範圍的值(例如RBG圖像以0-255範圍的位元組存儲)會出現一些問題。在開始訓練時,網路會非常不穩定,因為比如說預期值是255,網路產生的值是-1或1——這會被大多數用於訓練神經網路的優化演算法認為是嚴重的錯誤。這會產生過大的梯度,可能導致梯度爆炸。如果不爆炸,那麼訓練的前幾個階段就是浪費的,因為網路首先學習的是將輸出值縮小到大致是預期的範圍。如果規範化了數據(在這種情況下,你可以簡單地將數值除以128再減去1),就不會發生這些問題。

一般來說,神經網路中特徵的規模也決定了其重要性。如果輸出中的有一個特徵規模很大,那麼與其他特徵相比它會產生更大的錯誤。類似地,輸入中的大規模特徵將主導網路並導致下游發生更大的變化。因此,使用神經網路庫的自動規範化往往是不夠的,這些神經網路庫會在每個特徵的基礎上盲目地減去平均值併除以方差。你可能有一個輸入特徵,通常範圍在0.0到0.001之間——這個特徵的範圍如此之小,因為它是一個不重要的特徵(在這種情況下,你可能不想重新scale),或者因為與其他特徵相比它有一些小的單元(在這種情況下,你可能想重新scale)?類似地,要小心具有這樣一個較小範圍的特徵,它們的方差接近或等於0,如果將它們規範化,則會導致NaN不穩定。仔細考慮這些問題很重要——考慮你的每個特徵真正代表什麼,並將所有輸入特徵的「units」相等,將這一過程視為規範化。這是我認為深度學習中人在這個loop中真正需要的幾個方面之一。

2、你忘記檢查結果了

問題描述

你已經訓練了幾個epochs的網路,也看到錯誤在減少。這是否意味著已經完成了?不幸地告訴你,幾乎可以肯定你的代碼中還有某些問題。在數據預處理、訓練代碼、甚至inference中都可能有bug。只是因為錯誤率下降了並不意味著你的網路在學習有用的東西。

怎樣解決?

在流程的每個階段都檢查數據是否正確是非常重要的。通常,你需要找到一些可視化結果的方法。如果是圖像數據,那麼這很簡單,動畫數據也不需要很麻煩就能可視化。但如果是其他類型的數據,你必須找到能夠檢查結果的方法,以確保在預處理、訓練和推斷的每個流程都正確,並將結果與ground truth數據進行比較。

為什麼?

與傳統的編程不同,機器學習系統幾乎在所有情況下都會悄悄地發生失敗。傳統編程過程中,我們習慣了計算機在發生錯誤時拋出錯誤,並將其作為信號返回去檢查bug。不幸的是,這個過程不適用於機器學習,因此,我們應該非常小心,在每個階段用人眼去檢查流程,以便知道何時出現bug,何時需要返回並更徹底地檢查代碼。

還需要注意

有很多方法可以檢查網路是否正常工作。一部分方法是為了確切地說明所報告的訓練錯誤是什麼意思。可視化應用於訓練集的網路的結果——你的網路的結果與實踐中的ground truth 相比較如何?你可能會在訓練期間將錯誤從100降到1,但是如果1的錯誤仍然是不可接受的結果,那結果仍然無法使用。如果網路在訓練集上工作,那就檢查驗證集——它仍然適用於以前沒有見過的數據嗎?我的建議是從一開始就習慣於可視化所有內容——不要只在網路不工作時才可視化——要確保在開始嘗試使用不同的神經網路結構之前,你已經檢查過完整的流程。這是準確評估一些潛在的不同方法的唯一方法。

3、你忘記預處理數據了

問題描述

大多數數據是很棘手的——通常我們知道的數據是類似的,可以用非常不同的數字表示。以角色動畫( character animation)為例:如果我們使用角色的關節相對於運動捕捉的studio的中心的3D位置來表示數據,那麼在某個位置或面向某個方向執行動作時,相較於在不同的位置、或不同的方向執行同一個動作,可能會產生大量不同的數字表示。那麼我們需要以不同的方式表示數據——例如在一些局部reference框架(例如相對於角色的質量中心),以便相似的動作有相似的數值表示。

怎樣解決?

思考你的特徵表示什麼——是否有一些簡單的transformation,可以確保表示相似東西的數據點總是得到相似的數值表示?是否有一個局部的坐標系統可以更自然地表示數據——或許是更好的顏色空間——不同的格式?

為什麼?

對於作為輸入的數據,神經網路僅作一些基本的假設,其中之一是數據所處空間是連續的——對於大部分空間來說,兩個數據點之間的點至少有一些「mix」,兩個相鄰的數據點某種意義上表示「相似」的東西。在數據空間中存在較大的不連續性(discontinuities),或存在表示同樣事物的大量分離數據(separated data),將使得學習任務變得更加困難。

還需要注意

數據預處理的另一種方法是試著減少所需數據變化的組合爆炸。例如,如果在角色動畫數據訓練的神經網路必須在每個位置和每個方向學習相同的動作組合,那麼網路有大量容量被浪費了,並且大部分的學習過程是重複的。

4、忘記使用正則化了

問題描述

正則化(Regularization)——通常以dropout、noise或網路隨機過程的某種形式進行,是訓練神經網路的另一個無法改變的方面。即使你認為你擁有比參數多得多的數據量,或過擬合不重要的情況,或沒出現過擬合,你仍然應該添加dropout或其他形式的noise。

怎樣解決?

正則化神經網路的最基本方法是在網路的每個線性層(卷積層或dense層)之前添加dropout。從中等到高的retainment probability開始,例如0.75或0.9。根據過擬合的可能性進行調整。如果你仍然認為不可能出現過擬合,那麼可以將retainment probability設置到很高,例如0.99。

為什麼?

正則化不僅僅是有關控制過擬合。通過在訓練過程中引入一些隨機過程,你在某種意義上是「平滑」(smoothing)了損失格局。這可以加快訓練速度,幫助處理數據中的異常值,並防止網路的極端權重配置。

還需要注意

數據增強(data augmentation)或其他類型的noise也可以像dropout一樣作為正則化的方式。雖然通常dropout被認為是將序偶多隨機子網路的預測結合起來的技術,但也可以將dropout視為通過在訓練過程中產生許多類似輸入數據的變化來動態地擴展訓練集大小的方法。而且我們知道,避免過擬合和提高網路準確性的最佳方式是擁有更多網路未見過的數據。

5、使用的Batch太大

問題描述

使用太大的batch可能會對網路在訓練過程中的準確性產生負面影響,因為這樣會降低梯度下降的隨機性。

怎樣解決?

找到在訓練時你能接受的最小的batch。在訓練時能夠最大限度利用GPU並行性的批量大小,對於準確性來說可能並不是最好的,因為在某些時候,更大的batch需要訓練更多回(epoch)才能達到相同的準確度。不要擔心從非常小的batch開始,比如16、8甚至是1。

為什麼?

使用更小的batch生產更方便(choppier)、更隨機的權重更新。這樣做有兩大好處。首先,能幫助訓練「跳出」原本可能被卡住的局部最小值;其次,可以使訓練在「更平坦」的最小值結束,一般而言,後者會代表更好的泛化性能。

還需要注意

數據中的其他元素有時也能像批量大小一樣生效。例如,在處理圖像時,將解析度翻倍,可能會有把批量大小×4類似的效果。直觀一點看,在CNN中,每個濾波器的權重更新將在輸入圖像的所有像素以及批處理中的每個圖像上進行平均。將圖像解析度翻番,將產生超過四倍像素的平均效果,就像將批量大小提高了4倍一樣。總之,重要的是考慮在每次迭代中最終的漸變更新將被平均多少,並在負面影響與儘可能多地利用GPU並行性之間保持平衡。

6、學習率不正確

問題描述

學習率可能會對網路好不好訓練有很大的影響。如果你剛剛入行,在常見深度學習框架各種默認選項的影響下,幾乎可以肯定你沒有把學習率設置對。

怎樣解決?

把梯度剪裁(gradient clipping)關掉。找到在訓練時不會發生錯誤的最高的學習率的值。然後將學習率設置得比這個值低一點點——這很可能非常接近最佳學習率了。

為什麼?

許多深度學習框架默認會啟用梯度裁剪。這個選項可以防止訓練過程中過度優化,它會在每個步驟中強制改變權重,讓權重發生最大限度的改變。這可能有用,特別是當數據中含有許多異常值的時候,因為異常值會產生很大的錯誤,從而導致大的梯度和權重更新。但是,默認開啟這個選項也會讓用戶很難手動找到最佳的學習率。我發現大多數深度學習的新手都因為梯度裁剪的原因將學習率設得太高,使得整體訓練行為變慢,也使改變學習率的效果不可預測。

還需要注意

如果你正確清理了數據,刪除了大部分異常值並且正確設置學習率,那麼你實際上並不需要梯度裁剪。在關閉梯度裁剪後,如果你發現訓練錯誤偶爾會爆發,那麼你完全可以重新打開梯度裁剪這個選項。但是,需要記住,訓練錯誤頻發的原因幾乎總是表明你數據的一些其他異常——裁剪只是一種臨時的補救方法。

7、在最後一層使用了錯誤的激活函數

問題描述

在最後一層使用激活函數,有時可能意味著你的網路無法產生所需的全部範圍的值。最常見的錯誤是在最後一層使用ReLU,從而導致網路只能輸出正值。

怎樣解決?

如果你做一個回歸,那麼在絕大多數時候你不會想在最後一層使用任何類型的激活函數,除非你確切地知道你想要輸出的值的種類是什麼。

為什麼?

再想想你的數據值實際代表什麼,以及它們在標準化以後的範圍。最可能的情況是,你的輸出值為unbounded正數或負數——在這種情況下,你不應在最終層使用激活函數。如果你的輸出值只在某些範圍內有意義,例如由0-1內的概率組成,那麼最終層應該有使用特定的激活函數,例如Sigmoid激活函數。

還需要注意

在最後一層使用激活函數有許多需要注意的地方。也許你知道你的系統最終會將輸出裁剪到 [-1,1]。那麼,將這個裁剪過程添加到最終層的激活當中就是有意義的,因為這將確保你的網路錯誤函數不會懲罰大於1或小於-1的值。但是,沒有錯誤也意味著這些大於1或小於-1的值也不會有梯度——這在某些情況下會使你的網路無法訓練。或者,你可能會嘗試在最後一層使用tanh,因為這個激活函數輸出的值的範圍是 [-1, 1],但這也可能帶來問題,因為這個函數的梯度在1或-1附近變得非常小,而為了產生-1或1可能使你的權重變得非常大。一般來說,最好保險起見,不要在最後一層使用激活函數。有時候聰明反被聰明誤。

8、網路里有壞的梯度

問題描述

使用ReLU激活函數的深層網路通常會受所謂「死神經元」的影響,而後者是由不良梯度引起的。這可能會對網路的性能產生負面影響,在某些情況下甚至完全無法訓練。

怎樣解決?

如果你發現訓練誤差經過多個epoch後都沒有變化,可能是使用了ReLU激活函數,讓所有的神經元都死掉了。嘗試切換到另一個激活函數,例如leaky ReLU或ELU,然後再看看是否還存在這樣的情況。

為什麼?

ReLU激活函數的梯度對於正值為1,負值為0。這是因為當輸入小於0時,輸入的一個很小變化不會影響輸出。短期看,這可能不是一個問題,因為正值的梯度很大。但是,層與層可以疊在一起,負的權重可以將那些梯度很大的正值變為梯度為0的負值;通常情況下,一些乃至所有隱藏單元對於成本函數都具有零梯度,無論輸入是什麼。在這種情況下,我們說網路是「死的」,因為權重完全無法更新。

還需要注意

任何具有零梯度的運算(如裁剪、舍入或最大/最小),在被用於計算成本函數相對於權重的導數時,都將產生不良梯度。如果它們在符號圖裡有出現,那麼一定要非常小心,因為它們往往會帶來意外的問題。

9、沒有正確地初始化網路權重

問題描述

如果你沒有正確地初始化你的神經網路權重,那麼神經網路根本就不太可能訓練。神經網路中的許多其他組件都有某些正確或標準化的權重初始化,並將權重設置為零,或者使用你自己的自定義隨機初始化不起作用。

怎樣解決?

「he」,「lecun」或「xavier」的權重初始化都是很受歡迎的選擇,在幾乎所有情況下都能很好地工作。你選一個就好(我最喜歡的是「lecun」),當你的神經網路正常運作以後,你也可以自由地進行實驗呀。

為什麼?

你可能已經知道,可以使用「小的隨機數」初始化神經網路權重,但事情並沒有那麼簡單。所有上述初始化都是使用複雜和詳細的數學發現的,這些數學基礎說明了它們為什麼用起來最好。更重要的是,圍繞這些初始化構建了其他神經網路組件,並根據經驗使用它們進行測試——使用你自己的初始化可能會使其他研究人員的結果復現得更加困難。

還需要注意

其他層可能也需要仔細地進行初始化。網路biases被初始化為零,而其他更複雜的層(如參數激活函數)可能會帶有自己的初始化,把這個弄對也同樣重要。

10、你用的神經網路太深

問題描述

更深更好嗎?嗯,情況並非總是如此……當我們拚命刷新基準,把某些任務的精度1%、1%地提升時,更深的神經網路一般來說更好。但是,如果你只有3~5層的小網路沒有學習任何東西,那麼我可以保證你用100層的也會失敗,如果不是更糟糕的話。

怎樣解決?

從3到8層的淺層神經網路開始。只有當你的神經網路跑起來學東西以後,再探索提升精度的方法,並嘗試加深網路。

為什麼?

在過去十年中,神經網路的所有改進都是小的fundamental的變化,這些改變只適用於較小型網路作為深層次的性能。如果您的網路不工作,除深度之外更有可能是其他的問題。

還需要注意

從小的網路開始也意味著訓練速度更快,推理更快,迭代不同的設計和設置將會更快。最初,所有這些事情都將對準確性產生更大的影響,而不僅僅是堆疊幾層。

11、使用隱藏單元的數量不對

問題描述

在某些情況下,使用太多或太少的隱藏單元(hidden units)都可能使網路難以訓練。隱藏單元太少,可能沒有能力表達所需任務,而隱藏單元太多,可能會變得緩慢而難以訓練,殘差噪音很難消除。

怎樣解決?

從256至1024個之間的隱藏單元開始。然後,看看類似應用的其他研究使用多少,並參考使用。如果其他研究人員使用的與你使用的數字非常不同,那麼可能需要有一些具體的原因來解釋。

為什麼?

在決定隱藏單元的數量時,關鍵要考慮你認為對網路傳遞信息所需最少數量的真實值。你應該把這個數字弄大一點。對於使用更多冗餘表示的網路,dropout可以。如果你要做分類,可以使用五到十倍的class的數量,而如果你做回歸,可能需要使用輸入或輸出變數數量的兩到三倍。當然,所有這些都是高度依賴於環境的,沒有簡單的自動解決方案——擁有很好的直覺對於決定隱藏單元數量是最重要的。

還需要注意

實際上,與其他因素相比,隱藏單元的數量通常對神經網路性能影響很小,而在許多情況下,高估所需隱藏單位的數量不會使訓練變慢。一旦你的網路工作了,如果你仍然擔心,只需嘗試很多不同的數字,並測量準確性,直到找到最適合你的網路的數值。

原文鏈接:http://theorangeduck.com/page/neural-network-not-working

【號外】新智元正在進行新一輪招聘,飛往智能宇宙的最美飛船,還有N個座位

點擊閱讀原文可查看職位詳情,期待你的加入~

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 新智元 的精彩文章:

「跟蹤」是否在中國建AI團隊?谷歌不予置評,但這是它的必然選擇
Andrej Karpathy:監督學習、無監督學習、人腦模擬和AGI的未來(83 PPT下載)
「華為雲重磅發布智能EI」對標阿里雲ET,加入國內AI雲平台三國殺
DeepMind最新Nature論文:探索人類行為中的強化學習機制
「DeepMind最新Nature论文」探索人类行为中的强化学习机制

TAG:新智元 |