目錄
- 訓練集loss不下降
- 驗證集loss不下降
- 測試集loss不下降
- 實踐總結
loss不下降,分多種情況:訓練集不下降,驗證集不下降,本文結合其它博客,做個小的總結:
首先看看不同情況:train loss與test loss結果分析
train loss 不斷下降,test loss不斷下降,說明網絡仍在學習;
train loss 不斷下降,test loss趨於不變,說明網絡過擬合;
train loss 趨於不變,test loss不斷下降,說明數據集100%有問題;
train loss 趨於不變,test loss趨於不變,說明學習遇到瓶頸,需要減小學習率或批量數目;
train loss 不斷上升,test loss不斷上升,說明網絡結構設計不當,訓練超參數設置不當,數據集經過清洗等問題。
一、訓練集loss不下降
1.1 數據集本身的問題
使用簡單模型進行測試,比如機器學習的模型,較快能驗證。另外檢測數據集是否是亂序的。
- 數據本身以及label是否有異常
- 數據是否過於臟亂,沒有經過清洗
- 數據輸入是否有問題,比如圖片與label是否一致
- 數據經過預處理后,是否丟失特征或者因預處理而出現別的問題
- 數據量是否過少,網絡出現過擬合的現象
- loss等於87.33不變:查閱相關資料以后發現是由於loss的最大值由FLT_MIN計算得到,FLT_MIN是1.17549435e−38F1.17549435e−38F其對應的自然對數正好是-87.3356,這也就對應上了loss保持87.3356了。
- loss保持0.69左右:當p=0.5時,loss正好為0.693147
1.2 模型結構和特征工程存在問題
通過參考別人已經設計好並實現和測試過的結構,以及特征工程方案,進行改進和適應性修改,可以更快更好的完成目標任務。當模型結構不好或者規模太小、特征工程存在問題時,其對於數據的擬合能力不足,是很多人在進行一個新的研究或者工程應用時,遇到的第一個大問題。建議使用小的數據集進行測試下。這個問題應該比較容易發現,並且應該第一個排除掉。
調整BN,激活等的順序,不過這個估計只能調優,不能起到太大作用。
1.3 權重初始化方案有問題
初始化方式比較多樣化,可以參考我的其它文檔:《【pytorch-2-5-2】深度學習權值初始化的方法》。不過很多網絡,不使用初始化,也能進行訓練。
1.4 正則化過度
L1 L2和Dropout是防止過擬合用的,建議是訓練初期,不啟用任何正則化手段。
1.5 增加網絡層次
若是非常復雜的問題,比如成千上萬的分類問題。若使用單層的神經網絡,訓練起來肯定不好,loss也不會收斂。建議嘗試至少3層的網絡。
1.6 選擇合適的激活函數、損失函數
在神經網絡的激活函數、損失函數方面的選取,也是需要根據任務類型,選取最合適的。
比如,卷積神經網絡中,卷積層的輸出,一般使用ReLu作為激活函數,因為可以有效避免梯度消失,並且線性函數在計算性能上面更加有優勢。而循環神經網絡中的循環層一般為tanh,或者ReLu,全連接層也多用ReLu,只有在神經網絡的輸出層,使用全連接層來分類的情況下,才會使用softmax這種激活函數。
而損失函數,對於一些分類任務,通常使用交叉熵損失函數,回歸任務使用均方誤差,有自動對齊的任務使用CTC loss等。損失函數相當於模型擬合程度的一個評價指標,這個指標的結果越小越好。一個好的損失函數,可以在神經網絡優化時,產生更好的模型參數。
1.7 選擇合適的優化器和學習速率
神經網絡的優化器選取一般選取Adam,但是在有些情況下Adam難以訓練,這時候需要使用如SGD之類的其他優化器。另外減小學習率,使用lr_scheduler逐步降低學習率;這部分建議看看我的另外兩篇:《AdamOptimizer及各類優化器》《【pytorch-2-5-1】學習率調整-torch.optim.lr_scheduler》。
1.8 嘗試調整的batchsize
若出現上下震動不收斂時候,也有可能是batchsize太小導致的。所以建議增大batchsize試試。這樣可以增加訓練方向一致性。當然也可能因過大時,模型前期由於梯度的平均,導致收斂速度過慢。
1.9 使用normalization
這個能一定程度加快模型收斂,並起到正則化的作用。具體可見這篇:《【DL-0】》
1.10 數據初始的歸一化
數據歸一化/歸一化
def feature_normalize(data):
mu = np.mean(data,axis=0)
std = np.std(data,axis=0)
return (data - mu)/std
具體可見: https://blog.csdn.net/z_feng12489/article/details/89205558
1.11 訓練時間不足
計算量不同,訓練時間不同,若是沒有GPU加速,估計訓練就更慢了。這種就是等一等了,或者換多GPU加速試試。
1.12 模型訓練遇到瓶頸
這里的瓶頸一般包括:梯度消失、大量神經元失活、梯度爆炸和彌散、學習率過大或過小等。
梯度消失時,模型的loss難以下降,就像走在高原上,幾乎任何地方都是高海拔,可以通過梯度的檢驗來驗證模型當前所處的狀態。有時梯度的更新和反向傳播代碼存在bug時,也會有這樣的問題。
在使用Relu激活函數的時候,當每一個神經元的輸入X為負時,會使得該神經元輸出恆為0,導致失活,由於此時梯度為0,無法恢復。有一種解決方案是使用LeakyRelu,這時,Y軸的左邊圖線會有一個很小的正梯度,使得神經網絡在一定時間后可以得到恢復。不過LeakyRelu並不常用,因為部分神經元失活並不影響結果,相反,這種輸出為0還有很多積極的作用。因為Relu方程輸入為負時,輸出值為0,利用此特性可以很好地忽略掉卷積核輸出負相關信息,同時保留相關信息。
二、驗證集loss不下降
調整到本階段,默認是訓練集上的loss可以下降,但驗證集上的loss已經不降。大部分是從處理過擬合的手段進行的。
2.1 適當的正則化和降維
正則化是用來解決模型過擬合問題的一個很重要的手段,人為給定一個正則系數lambda,進行權重衰減,將一些相關性不大的特征項的參數衰減到幾乎為0,相當於去掉了這一項特征,這跟降維類似,相當於減少了特征維度。而去掉基本無關的維度,那么就避免了模型對於這一維度特征的過分擬合。還有在神經網絡兩個層之間增加Dropout和Normal等,也起到了抑制過擬合的作用。
2.2 適當降低模型的規模和數據復雜度
過擬合很重要的一個原因也是模型的復雜度太高,除了正則化手段以外,適當減小模型的規模也是很重要的,盡量讓神經網絡結構的假設空間與預期目標模型需要存儲的信息量相匹配。降低數據的維度,類似起到dropout的效果。
2.3 減小batchsize
由於批規范內部的標准化,較小的批大小在某種程度上對應較強的正則化。這是因為批處理的經驗平均值/std是完整平均值/std的更近似版本,所以規模和偏移量會使批處理更加"搖擺"。
2.4 使用early stop
停止基於驗證損失的訓練,在模型即將過度適應時抓住它。
大模型嘗試:我只是在早期停止后才提到這一點,但我發現在過去的幾次大的模型當然最終會過度適應,但它們的"早期停止"性能通常會比小的模型好得多。
2.5 獲取更多的數據集
深度學習就是在有大量數據的基礎上發展起來的。深度學習的三件套:數據、模型和硬件。增加數據量,能更好訓練模型。
2.6 對數據集做擾動和擴增
這個是直接對現有的數據集做擴容,一定程度上可以再次提高驗證集上的准確率,比如對圖像做旋轉,對聲音文件進行加噪處理等。最終的效果雖然比不上同等情況下的數據量的增加帶來的效果增益,但是在現有條件下,算是擴增數據量的一個有效的方案。
三、測試集loss不下降
測試集一般為模型之前訓練時從未見過的新數據,或者目標應用場景下的真實數據。由於訓練集和驗證集的loss不下降時,應歸為前兩節的內容,所以這一節中,我們默認訓練集和驗證集的loss情況是正常的。如果測試集的loss很高,或者正確率很低,那么一般是因為訓練數據的分布和場景與測試數據的分布和應用場景不一致。
3.1 應用場景不一致
比如,一個語音識別模型,輸入的數據集都是女性的錄音音頻,那么對於男性的聲音就不能很好的識別出來。這個也是博主之前做語音識別的時候遇到過的一個真實案例,解決方案就是增加含有大量男性錄音音頻的數據集來訓練。
3.2 噪聲問題
噪聲問題是實際應用場景下,頻繁遇到的問題。直接容易理解的案例就是,在語音識別中,標准語音數據集都是在安靜環境下采集的數據,但是在實際應用中,我們錄音時多多少少會有噪聲,那么我們需要專門去處理噪聲,比如進行一個降噪處理,或者在訓練數據中添加噪聲等。在圖像的識別中,那么就需要考慮圖片中的遮擋、霧霾、旋轉、鏡像和大小遠近等問題。
四、實踐總結
在實際工作中,訓練4000+的分類模型中,1.5 、1.7 、1.9在實際訓練中改善比較明顯。