參考:http://theorangeduck.com/page/neural-network-not-working
My Neural Network isn't working! What should I do?
因此,你正在開發深度學習的下一個重大突破,但你遇到了一個不幸的挫折:你的神經網絡失靈了,你不知道該怎么辦。你去找你的老板/主管,但他們也不知道——他們和你一樣對這一切都是新手——那現在怎么辦?
幸運的是,我在這里列出了你可能做錯的所有事情,這些事情都是根據我自己實施神經網絡和監督其他學生完成項目的經驗整理而成的:
1.忘記對數據進行歸一化
1)what
在使用神經網絡時,准確地考慮如何將數據標准化是非常重要的。如果沒有這是一個不可協商的步驟-如果沒有正確並小心地做到這一點,你的網絡可能幾乎機會工作。由於這一步在深度學習社區中是如此重要和眾所周知,所以很少在論文中提及,所以幾乎總是讓初學者感到困惑。
2)how
一般歸一化意味着——從數據中減去均值,然后除以標准差。通常,這是針對每個輸入和輸出特性單獨完成的,但是你可能經常希望對一組特性執行此操作,或者特別注意某些特性的標准化。
3)why
我們需要對數據進行歸一化的主要原因是,神經網絡管道大部分都假設輸入和輸出數據都分布在標准差為1左右、均值約為0的地方。這些假設在深度學習文獻中隨處可見,從權重初始化到激活函數,再到訓練網絡的優化算法。
4)and
未經訓練的神經網絡通常輸出的值大致在-1到1之間。如果你希望它輸出其他范圍內的值(例如以字節形式存儲的RGB圖像在0到255之間),那么你將遇到一些問題。當開始訓練時,網絡將非常不穩定,因為當像255這樣的值被期望時,它將產生-1或1的值——大多數用於訓練神經網絡的優化算法都認為這是一個巨大的錯誤。這將產生巨大的梯度,很可能你的訓練錯誤將爆炸。如果你的訓練沒有爆炸,那么前幾個階段的訓練仍然是浪費,因為網絡首先要學習的是將輸出值擴展到所需的范圍。如果你將數據標准化(在本例中,你可以簡單地除以128並減去1),那么這些都不是問題。
一般來說,神經網絡中特征的規模也決定了它們的重要性。如果在輸出中有一個大規模的特性,那么與其他特性相比,它將生成更大的錯誤。同樣,輸入中的大規模特性將主導網絡,並在下游造成更大的變化。由於這個原因,僅僅使用許多神經網絡庫的自動歸一化是不夠的,這些神經網絡庫盲目地在每個特征偏差上減去均值並除以標准差。你可能有一個輸入特征一般范圍在0.0和0.001之間,這個特性的范圍如此之小,因為它是一個不重要的特性(在這種情況下,也許你不想 ),或因為它相比其他特性有一些小單元?同樣,要小心那些范圍非常小的特性,它們的標准偏差接近於,或者確切地說,等於零——如果你對它們進行標准化,這些特性將導致NaNs的不穩定性。仔細考慮這些問題是很重要的——考慮你的每個特性真正代表什么,並將標准化視為使所有輸入特性的“單元”相等的過程。我相信這是深度學習中為數不多的幾個在循環中每個人都需要的進行的操作的其中之一
2.忘記查看結果
1)what
你已經訓練了你的網絡幾輪了,你可以看到錯誤正在減少——這是否意味着你成功了?不幸的是,沒有——幾乎可以肯定,你的代碼仍然存在一些錯誤。它可能是數據預處理、訓練代碼甚至推理中的一個bug。僅僅因為錯誤減少了並不意味着你的網絡正在學習任何有用的東西。
2)how
在管道的每個階段檢查數據是否正確是非常重要的。通常這意味着找到某種方法來可視化結果。如果你有圖像數據,那么它很容易-動畫數據也可以可視化,不會有太多的麻煩。如果你有更奇特的數據,你必須找到一種方法來檢查它,以確保在預處理、訓練和推理的每個階段它看起來都是正確的,並將其與真實數據進行比較。
3)why
與傳統編程不同,機器學習系統幾乎在所有情況下都可能會無聲地失敗。在傳統的編程中,我們習慣了計算機在出錯時拋出一個錯誤,並以此作為返回並檢查錯誤的信號。不幸的是這一過程在機器學習應用程序中不工作,所以我們應該使用我們的眼睛非常小心檢查每個階段的過程,這樣我們才能知道什么時候一個錯誤已經產生,並且什么時候我們需要返回去更徹底地檢查代碼。
4)and
有很多方法可以檢查你的網絡是否正常工作。其中一部分是找出報告的訓練錯誤的確切含義。可視化應用於數據集中數據的網絡的結果——並與真實數據進行比較,結果如何?在訓練過程中,你可能會看到誤差從1.0上升到0.01,但是如果0.01的誤差在實踐中仍然是不可接受的結果,那么結果仍然是不可用的。如果它在訓練集上有效,那么在驗證集上檢查它——它是否仍然對以前沒有見過的數據有效?我的建議是從訓練一開始就進行可視化,不要只有當你的網絡不工作才開始,確保在你開始嘗試不同的神經網絡結構前,你已經准備好了到最終用戶的完整管道,並進行了完整性檢查。這是你能夠准確評估許多潛在的不同方法的唯一方法
3.忘記對數據進行預處理
1)what
大多數數據都很棘手,而且我們所知道的相似事物的數據往往具有截然不同的數值表示。舉個例子從角色動畫——如果我們使用角色相對於動作捕捉工作室的關節的3d位置來表示我們的數據,然后生成在一個位置或者面對一個方向的動作,可能會有大量不同的數值表示去生成在不同的位置,或者面對一個不同的方向的相同的動作。相反,我們需要做的是能夠不同地表示數據——例如在某個局部參照系中(例如相對於角色的質心),這樣我們知道的兩個運動是相似的,就可以得到相似的數值表示。
2)how
想想你的特性到底代表了什么——你是否可以對它們進行一些簡單的變換,以確保代表我們所知道的相似事物的數據點總是得到相似的數值表示?是否有一個局部坐標系可以用來表示數據,從而使事物更自然——也許是更好的顏色空間——以不同的格式表示?
3)why
神經網絡僅對他們作為輸入的數據做幾個基本假設——這些基本假設之一是數據的空間是連續的——即對於大部分的空間,兩個數據點之間的點至少是有點這兩個數據點的“混合”,並且兩個鄰近的數據點在某種意義上代表“相似”的事物。因此在數據空間中如果存在較大的不連續點,或者表示相同事物的大量分離數據集群,將會使學習任務變得更加困難。
4)and
另一種考慮數據預處理的方法是嘗試減少可能需要的數據變化的組合爆炸。例如,如果一個訓練角色動畫數據的神經網絡必須在每個位置和方向上為角色學習相同的一組動作,那么網絡的大量容量就會被浪費,大量的學習過程就會被重復。
4.忘記使用任何正則化方法
1)what
正則化——通常以dropout、噪聲或注入網絡的隨機過程的形式出現,是訓練現代神經網絡的另一個重要方面。即使你認為你有比參數多得多的數據,或者你有一些過擬合無關緊要或看起來不可能的情況,添加dropout或其他形式的噪聲通常仍然是有幫助的。
2)how
正則化神經網絡最基本的方法是在網絡的每個線性層(卷積層或稠密層)之前添加dropout。從中等到高的保留率開始,比如0.75或0.9。根據你認為過度擬合的可能性,以及你是否發現了任何證據來進行調整。如果你認為過擬合是非常不可能的,考慮設置保留的概率非常高,如0.99。
3)why
正則化不僅僅是控制過度擬合。通過在訓練過程中引入一些隨機過程,你在某種意義上“平滑”了成本前景。這可以加快訓練速度,幫助處理數據中的噪音或異常值,並防止網絡的極端權重配置。
4)and
數據增強或其他類型的噪聲也可以像dropout一樣充當正則化的角色,有時,如果有足夠的數據增強,dropout就不再需要了。雖然將dropout看作是一種結合許多隨機子網絡預測的技術,但也有可能將dropout看作是數據增強的一種形式——在訓練期間生成許多類似的輸入數據變體。正如我們所知,避免過度擬合的最好方法是擁有如此多的數據,以至於神經網絡永遠不會看到相同的東西兩次!最后,就像訓練神經網絡的所有方面一樣,你需要小心使用正則化。記住,在預測過程中要關閉它,並且要注意,一旦關閉它,你通常可以得到稍微不同的結果。在需要非常精確的數字預測的情況下,某些形式的正則化有時會使這一點變得困難。
5.使用了過大的batch size
1)what
在訓練過程中使用過大的批處理大小會對網絡的准確性產生負面影響,因為它會降低梯度下降的隨機性。
2)how
找出你能夠容忍訓練時間的最小批處理大小。當涉及到精度時,最優利用GPU並行性的批處理大小可能不是最好的,因為在某些情況下,更大的批處理大小將需要對網絡進行更多的訓練,以達到相同的精度水平。不要害怕從非常小的批處理大小開始,比如16、8甚至1。
3)why
使用更小的批處理大小會產生更不穩定、更隨機的權重更新。這有兩個積極的影響。首先,它可以幫助訓練“跳出”以前可能陷入的局部極小值;其次,它可以使訓練穩定在“平坦”的極小值中,這通常意味着更好的泛化性能。
4)and
數據中的一些其他元素有時可以有效地發揮批處理大小的作用。例如,以兩倍於以前的分辨率處理圖像可以產生與使用四倍於以前批處理大小的效果類似的效果。為了直觀地理解這一點,考慮一下在CNN中,每個過濾器的權值更新將在輸入圖像中應用它的所有像素以及批處理中的每個圖像上取平均值。將圖像分辨率增加兩倍將產生超過四倍的像素的平均效果,這與將批處理大小增加四倍非常相似。總的來說,重要的是要考慮最終的梯度更新在每次迭代中平均會有多少,並確保在其的有害影響和使用盡可能多的GPU潛在並行性的需求之間取得平衡。
6.使用不正確的學習率
1)what
學習速度會對訓練網絡的難易程度產生巨大影響,如果你是新手,幾乎可以肯定你的設置是錯誤的,這要感謝常用深度學習框架中使用的各種默認選項。
2)how
關閉梯度裁剪。找到學習率的最大值,這樣在訓練過程中不會出現錯誤爆炸。將學習率設置為比這個低一個數量級——這可能非常接近最優學習率。
3)why
許多深度學習框架在默認情況下都啟用了梯度裁剪。這個選項通過強制在每個步驟中改變最大權重來防止在訓練中使用的優化發生爆炸。這可能很有用——特別是如果你的數據包含許多異常值,這些異常值會產生較大的錯誤,因此會產生較大的梯度和權重更新——但是默認啟用它也會使手工查找最佳學習率變得非常困難。我發現大多數初學深度學習的人都把學習率設置得太高,並且用梯度剪裁來解釋這一點,使得整體訓練行為變慢,改變學習率的效果無法預測。
4)and
如果你正確地清理了數據,刪除了大部分異常值,並正確地設置了學習率,那么你真的不應該需要梯度裁剪。如果沒有它,你發現你的訓練錯誤偶爾會爆發,那么無論如何,打開梯度裁剪,但要記住,看到你的訓練錯誤爆發幾乎總是一個跡象,表明你的一些數據有其他問題——裁剪是一個臨時的修復。
7.在最后一層使用了錯誤的激活函數
1)what
在最后一層使用激活函數有時可能意味着你的網絡無法生成所需的全部值。最常見的錯誤是在最后一層使用ReLU——導致網絡只能產生正值作為輸出。
2)how
如果要進行回歸,那么通常不希望在最后一層使用任何類型的激活函數,除非你對希望生成的輸出值有特定的了解。
3)why
再想想你的數據值實際表示的是什么,以及規范化之后它們的范圍是什么。輸出值很可能是無界的正數或負數——在這種情況下,不應該在最后一層使用激活函數。如果你的輸出值只在某個范圍內有意義,例如,它由0-1范圍內的概率組成,那么很有可能在最后一層使用一個特定的激活函數,比如sigmoid激活函數。
4)and
在最后一層使用激活函數有許多微妙之處。也許你知道你神經網絡生成的系統最終將剪輯輸出到范圍- 1,1后。這樣,添加這個剪切過程作為最后一層激活似乎是有意義的,因為這將確保網絡錯誤函數不會懲罰大於1或小於-1的值。但是沒有錯誤意味着這些值大於或小於1沒有梯度——在某些情況下,這將使你的網絡無法訓練。或者你可能想在最后一層使用tanh激活函數,因為這個激活函數輸出值范圍在1到1 ——但是這也可能會導致問題,因為這個函數的梯度接近1或-1時增長很小,從而導致你的權重增長巨大,以生成-1或1。一般來說,你最好的選擇是在最后一層完全不使用激活函數,而不是嘗試做一些可能適得其反的事情。
8.網絡包含糟糕的梯度
1)what
使用ReLU激活函數的深層網絡常常會受到所謂的“死神經元”的影響,這是由糟糕的梯度造成的。這可能會對網絡的性能產生負面影響,或者在某些情況下完全不可能進行訓練。
2)how
如果你發現你的訓練錯誤沒有隨着時間的推移而改變,那可能是因為你所有的神經元都因使用ReLU激活函數而死亡。嘗試切換到另一個激活函數,如leaky ReLUs或ELUs,看看是否會發生相同的事情。
3)why
ReLU激活函數的梯度為正1,負0。這是因為在輸入小於零的情況下,輸入中很小的變化不會影響輸出。因為正值的大梯度,這可能不會立即正為一個問題;但與許多層堆疊在彼此之上,和負權值能夠將帶有強梯度的大正值變為零梯度的負值的作用下,它可能經常會導致一些甚至是所有的網絡權值在成本函數中的梯度為零,不管輸入是什么。在這種情況下,我們說網絡是“死的”,因為權重完全無法更新。
4)and
任何梯度為零的操作,如裁剪、舍入或取最大值/最小值,如果用於計算成本函數對權重的導數,也會產生不好的梯度。如果它們出現在符號圖中的任何地方,請非常小心,因為它們常常會導致無法預見的困難,例如,如果它們用於作為成本函數的一部分提供的自定義錯誤度量中。
9.錯誤地初始化網絡權重
1)what
如果你沒有正確初始化你的神經網絡的權重,那么你的神經網絡就不太可能進行訓練。神經網絡中的許多其他組件都假定某種形式的正確或標准化的權重初始化,並將權重設置為零,或者使用你自己的自定義隨機初始化將不起作用。
2)how
“he”、“lecun”或“xavier”權重初始化都是流行的選擇,在實際的任何情況下都可以很好地工作。只要選擇一個(我最喜歡的是“lecun”),但是一旦你的神經網絡開始工作,你就可以自由地進行實驗,直到你找到最適合你任務的初始化方法。
3)why
你可能聽說過可以使用“小隨機數”初始化神經網絡權值,但事情並沒有那么簡單。上述所有初始化都是使用復雜而詳細的數學發現的,這些數學解釋了為什么它們是最優的。更重要的是,其他神經網絡組件是圍繞這些初始化構建的,並使用它們進行了經驗測試——使用你自己的初始化可能會使復制其他研究人員的結果變得更加困難。
4)and
其他層可能也需要小心初始化。網絡偏差被初始化為零,而其他更復雜的層,如參數化激活函數可能帶有它們自己的初始化,這些初始化的正確也同樣很重要。
10.使用的網絡太深
1)what
網絡越深越好嗎?嗯,不總是……當我們玩基准游戲並試圖擠出比其他任務多1%的准確性時更深的通常是更好,但是如果你的小3,4,5層網絡沒有學到任何東西,那么我可以向你保證,一個100層的龐然大物的效果即使不是更糟,也會是一樣糟糕。
2)how
從一個淺層的3到8層的神經網絡開始。只有當你已經把事情做得很好並開始研究如何提高准確度時,才可以開始嘗試更深層次的網絡。
3)why
雖然看起來像這樣,但是當某人決定將數百層疊加起來時,神經網絡並不會突然開始獲得突破性的結果。在過去的十年里,所有對神經網絡的改進研究都是一些小的、根本性的變化,這些變化同樣適用於小型網絡和深度網絡的性能。如果你的網絡不工作,除了深度之外,更有可能是其他問題。
4)and
從小處着手也意味着訓練你的網絡會更快,推理會更快,迭代不同的設計和設置也會更快。最初,所有這些東西對你的網絡的准確性的影響都比簡單地疊加幾層要大得多。
11.使用錯誤的隱藏單元的數目
1)what
在某些情況下,使用過多或過少的隱藏單元會使你的網絡難以訓練。太少的單元可能沒有能力表達所需要的任務,而太多的單元可能會變得緩慢和笨拙,難以消除殘留的噪聲。
2)how
從256到1024個隱藏單元開始。然后,看看其他從事類似應用的研究人員所使用的數字,並以此作為靈感。如果其他研究人員使用的數字與上面給出的數字有很大的不同,那么其中可能有一些特定的原因,這對你理解可能很重要。
3)why
在決定使用多少隱藏單元時,關鍵是粗略地考慮你認為表達你希望通過網絡傳遞的信息所需的實際值最少是多少。你應該把這個數字放大一點。這將允許dropout,為網絡使用一個更冗余的表示,並為你的估計留有一些余地。如果你在做分類,你可以使用5到10倍的類數作為一個好的初始猜測;而如果你在做回歸,你可以使用2到3倍的輸入或輸出變量的數量。當然——所有這些都高度依賴於上下文,並且沒有簡單的自動解決方案——一個好的直覺仍然是決定隱藏單元數量的最重要因素。
4)and
在現實中,與其他因素相比,隱藏單元的數量對神經網絡性能的影響往往相當小,而且在許多情況下,高估所需隱藏單元的數量除了會使訓練變慢外,幾乎不會產生負面影響。一旦你的網絡開始工作,如果你還在擔心,就試着用一大堆不同的數字來測量准確度,直到你找到最合適的。