神经网络不学习的原因
Neural Network Check List
聲明:
?
- Neural Network Check List
- 如何使用這個指南
- 數據問題
- 檢查輸入數據
- 試一下隨機輸入
- 檢查數據加載單元
- 確保輸入和輸出是一一對應的
- 輸入和輸出之間的關系映射的隨機性會不會太強了
- 數據集中的噪聲
- 打亂數據集
- 控制類別不平衡現象
- 會不會是訓練數據不足
- 盡量你的訓練批次中的樣本標簽多樣化
- 減小batch size
- 嘗試經典數據集MNISTCIFAR10
- 數據歸一化正則化
- 特征向量的標準化
- 過量的正則化
- 使用預訓練網絡時注意數據處理方式
- 檢查訓練驗證測試集的預處理
- 網絡的構建問題
- 先嘗試解決當前問題的簡單版本
- 搞定損失函數
- 檢查損失函數
- 核查損失函數的輸入
- 調整損失權重
- 注意其他的模型評價標準
- 測試自定義層
- 檢查frozen層和變量
- 增加網絡規模
- 檢測隱藏層的維度錯誤
- 檢查梯度
- 訓練問題
- 先處理小數據集
- 檢查權重初始化
- 調整超參數
- 減少正則化
- 多多迭代
- 注意訓練和測試模式之間的切換
- 可視化訓練過程
- 試一下不同的優化算法
- 梯度爆炸和梯度彌散
- 調整學習率
- 空值問題
?
有一個訓練了12個小時的神經網絡,各方面看起來都不錯:梯度緩慢下降、損失也在逐漸降低,但是預測結果卻不好:輸出全是0值(全都預測為背景),沒有檢測出任何標簽。“到底是什么地方出錯了?”——叫天天不應叫地地不靈╮(╯▽╰)╭
對于上述情況,或者另一種垃圾輸出的情況——預測值只是所有標簽的平均值,再或者更差的情況,模型準確率非常低…我們應該從什么地方開始檢查模型呢?
如何使用這個指南
網絡訓練效果差,問題可能出在很多很多地方,但有些地方出問題的概率較大。所以,通常我會從以下幾點開始:
數據問題
1 檢查輸入數據
保證你提供給網絡的輸入數據是有意義的。比如:我有時候弄混了圖片的高和寬;或者不小心用全零的數據來訓練網絡;或者一直使用了同一個batch來不停的迭代訓練。所以,你應該打印一組(輸入,輸出)并確保它們沒有問題。
2 試一下隨機輸入
如果網絡對隨機輸入的預測結果跟之前真實數據的預測結果差不多,那多半是網絡某一層除了問題。這時,你需要一層一層的debug自己的網絡。
3 檢查數據加載單元
可能你的數據集沒有問題,但是在數據的讀取和預處理中除了問題,所以要檢查網絡第一層的輸入。
4 確保輸入和輸出是一一對應的
也就是說,訓練集中的輸入不能(或者盡可能少的)有錯誤的標定。同時記得在打亂數據集的時候,輸入和輸出的打亂方式相同。
5 輸入和輸出之間的關系映射的隨機性會不會太強了?
用機器學習里的術語來說就是,y=f(x)y=f(x)中ff的假設空間(模型空間)太大了。
比如說股票數據,想學習這個太難了。因為股票的隨機性太大了,雖然通過數據獲得的股票走勢有一定的參考意義,但因為隨機性大于數據內部的規律,光憑數據很難做出正確的預測。
6 數據集中的噪聲
數據集不是完美的,比如對于MNIST手寫數字識別數據集來說,可能有50%的樣本時正確的可以學習的,而另外的50%的樣本亂標定的噪聲,那么這些亂標定的噪聲會干擾網絡的學習,應該實現被剔除。
當用網上爬來的數據進行機器學習或深度學習的時候,很容易出現這種問題。
7 打亂數據集
不打亂數據集的話,會導致網絡在學習過程中的偏向問題。
8 控制類別不平衡現象
對于類別不平衡的分類問題,常規武器有:過采樣、欠采樣(不太好用)、調整損失函數等。
9 會不會是訓練數據不足?
小樣本學習時深度學習應用的一個重要問題。常規武器有遷移學習和生成網絡(如GAN、VAE)法。如果是因為訓練數據不足造成的網絡學習效果不好,那將需要很大的精力來解決這個問題。
10 盡量你的訓練批次中的樣本標簽多樣化
如果一個訓練批次中只有一類的樣本,網絡將很難收斂到最優。一般來說只要隨機打亂的訓練集就不會出現這個問題。再保險一點可以將batch_size搞大一點,比如128,但不要太大。
我在實驗中,就經常會出現用同一數據集和網絡得到的準確率忽高忽低,比如70%-90%。所以,時間允許的話,建議每次實驗過程中多訓練幾次。
11 減小batch size
(?◇?)?上面剛說batch size可以搞大一點,這里又要調小????
研究表明:太大的batch size會降低模型的泛化能力。詳見論文——戳我跳轉
12 嘗試經典數據集(MNIST,CIFAR10)
當使用一種新型的網絡結構式,應該先用經典數據集測試一下,而不是直接應用于自己的真實數據。因為這些經典數據集都有參考標準(baseline,或者說是準確率的最低要求),而且沒有數據方面的問題(如噪聲、不平衡、隨機性過大導致難以學習的問題等等)
數據歸一化/正則化
13 特征向量的標準化
記得以下二選一:
- 標準化:均值為0方差為1
- 歸一化:數據大小位于0~1之間
14 過量的正則化
正則化可以防止模型過擬合,但過量的正則化會導致欠擬合。
15 使用預訓練網絡時注意數據處理方式
預處理的方式要跟你加載的預訓練的網絡一致,比如圖片像素的大小是[0, 1], [-1, 1]還是[0, 255]?
16 檢查訓練/驗證/測試集的預處理
引用斯坦福課程CS231n:
… any preprocessing statistics (e.g. the data mean) must only be computed on the training data, and then applied to the validation/test data. E.g. computing the mean and subtracting it from every image across the entire dataset and then splitting the data into train/val/test splits would be a mistake.
也就是說,預處理方法下面二選一:
- 先對訓練集預處理,再將該預處理函數應用到驗證/測試集中。
- 對全部數據做預處理,再將全部數據集合劃分為訓練/驗證/測試集。
網絡的構建問題
17 先嘗試解決當前問題的簡單版本
比如說,如果目標輸出是object class and coordinates, 先試一下解決object class。
18 搞定損失函數
引用斯坦福課程CS231n:
Initialize with small parameters, without regularization. For example, if we have 10 classes, at chance means we will get the correct class 10% of the time, and the Softmax loss is the negative log probability of the correct class so: -ln(0.1) = 2.302.
損失函數一般包括兩部分:誤分類的懲罰項和正則化項。我們應該先根據問題選擇合適的懲罰項,然后在嘗試正則化項
19 檢查損失函數
如果你自定義了損失函數,一定要檢查它,還要進行單元測試。因為自定義的損失函數經常會有細小的錯誤,導致網絡出現學習問題,而且這通常很難發現。
20 核查損失函數的輸入
使用神經網絡框架中的損失函數時,一定要注意損失函數的輸入。比如,在PyTorch中,我經常會弄混NLLLoss和CrossENtropyLoss,前者的輸入是一個softmax輸入(即在0到1之間),而后者不是。
21 調整損失權重
如果你的損失函數由多個子損失加權而成,那就要注意它們的關聯關系和權重。
22 注意其他的模型評價標準
有時候,損失函數的值并不是評價網絡訓練好壞的最好方式。如果可以的話,可以使用其他的評價標準,如準確率。
23 測試自定義層
如果網絡中有你自定義的網絡層,多檢查幾遍…
24 檢查frozen層和變量
可能你無意間關閉了某些層的權重更新。
25 增加網絡規模
有時候網絡訓練效果不好是因為網絡的容量太小,增加全連接層數或隱藏層神經元數目。
26 檢測隱藏層的維度錯誤
如果你的輸入數據維度(k, H, W) = (64, 64, 64),那確實很容易在維度上弄混。如果不放心維度上的問題,可義用幾個容易分辨的數值試一下,檢查一下它們在各個網絡層中傳遞時的變化。不過這里一般不會出問題。
27 檢查梯度
如果反向傳遞的求導是你自己算的,確實需要反復檢查。
訓練問題
28 先處理小數據集
從當前數據集中選擇極其少量的數據,用自己的網絡模型過擬合這些數據,確定網絡沒有問題。
例如,先用2個樣本訓練,觀察你的網絡能否學到這兩個樣本之間的不同,然后逐步擴展到更多數據。
29 檢查權重初始化
保險起見,可以使用Xavier或He初始化。有時候,不好的初始化確實會是網絡的學習陷入一個局部最優解,所以也可以試一下其他的初始化方法,看看是否有用。
30 調整超參數
超參數的最優值可以通過經驗或多次實驗獲得。如果時間允許的話,還可以通過交叉驗證選擇最優超參數。
31 減少正則化
過多的正則化會導致網絡欠擬合。Dropout,?batchnormalization, L2正則化作為正則化手段,當網絡欠擬合時候應該先去掉這些方法。
32 多多迭代
可能你的網絡需要更多的迭代次數才能獲得有意義的預測。如果網絡的損失函數值還在下降,務必讓它繼續迭代下去;如果網絡的損失函數不再下降,也應該繼續觀察幾輪確保訓練沒有卡在局部最小點。
33 注意訓練和測試模式之間的切換
有些網絡層如BatchNormalization和Dropout層在訓練模式和測試模式下是不一樣的。
34 可視化訓練過程
- 監視每一層的權重和輸出,確保激活函數和每一層的權重更新正常。
- 可以使用Tensorboard或Crayon等可視化庫
- 如果有一層激活函數后的平均值遠大于0,可以嘗試BatchNormalization或ELU激活函數
- 權重和偏執的數值分布:權重應該近似服從標準高斯分布,偏執應該從0開始逐漸過渡到近似高斯分布(除了個別網絡外,如LSTM)。也就是說權重的正負分布應該相似,偏執一般不會過大,要不然可能就是網絡的訓練除了問題。
For weights, these histograms should have an approximately Gaussian (normal) distribution, after some time. For biases, these histograms will generally start at 0, and will usually end up being approximately Gaussian (One exception to this is for LSTM). Keep an eye out for parameters that are diverging to +/- infinity. Keep an eye out for biases that become very large. This can sometimes occur in the output layer for classification if the distribution of classes is very imbalanced
35 試一下不同的優化算法
一般來說優化器的選擇不會導致網絡訓練的結果太差,除非你選擇的優化器超參數太糟了。當然,合適的優化器可以是網絡訓練的更快。常用的優化器有Adam,SGD,?RMSprop。
36 梯度爆炸和梯度彌散
梯度爆炸和梯度彌散產生的根本原因是深度學習中多層梯度累積。如1.1的n次方無窮大,0.9的n次方無窮小。
- 網絡中某些層過大的輸出會造成梯度爆炸,此時應該為該輸出取一個上界。
- 激活函數的梯度應該在0.5到2之間。
37 調整學習率
學習率決定了網絡訓練的速度,但學習率不是越大越好,當網絡趨近于收斂時應該選擇較小的學習率來保證找到更好的最優點。
一般學習率的調整是乘以/除以10的倍數。
空值問題
首先訓練集中不能有空值!!其次,網絡訓練過程中也不能出現空值,幾點建議:
- 降低學習率,尤其是在前100次迭代中出現了NAN
- 分母上的空值或者非正數的對數會導致NAN出現
- 一層一層的檢查空值是否出現,比如通過Python中的assert
總結
以上是生活随笔為你收集整理的神经网络不学习的原因的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java HashMap问题
- 下一篇: 通过组策略找回“网上邻居”