Caffe訓練時Loss=87.3365問題


1. 問題分析


如圖,在開始訓練后, loss升高到87.3365后保持不變。這個問題是因為梯度爆炸導致的。


loss -= log(std::max(prob_data[i * dim + label_value * inner_num_ + j],
                     Dtype(FLT_MIN)));  

在softmax_loss_layer.cpp的原碼中,loss的最大值由FLT_MIN得到,FLT_MIN定義為1.17549435E-38F,這個數字的自然對數正好就是
-87.3356,算loss時需要取負值,結果就能了87.3356。

這說明softmax計算得到概率值出現了零(由於float類型所能表示的最小數值是10−3810−38,比這個值還小的無法表示,只能是零)
而softmax是用指數函數計算的,指數函數的值都是大於零的。因此,我們有理由相信,計算過程中出現了float溢出等異常,出現了inf,nan等異常數值導致softmax輸出為零
最后我們發現,當softmax之前的feature值過大時,由於softmax先求指數,會超出float數據范圍,成為inf。inf與其他任何數值的和都是inf,softmax在做除法時任何正常范圍的數值除以inf都會變為0。然后求loss時log一下就出現了87.3356這樣的值。


2. 解決辦法

1. 降低學習率,提高batchsize,這樣就能減小權重參數的波動范圍,從而減小權重變大的可能性
2. 輸入歸一化

用均值文件歸一化

  transform_param {
    mirror: true
    crop_size: 331
    mean_file: "lmdb_data/img_test_lmdb/mean.binaryproto"
3. 查看輸入數據、標簽是否有異常,

solver.prototxt中設置,debug_info: true

標簽仔細看了,從0到60,總分類個數也改成了61

數據都是嚴格按照預處理lmdb來的。

4. 數據shuffle

已經在lmdb數據生成時進行了shuffle。

5. batch normalization的設置

如果有BN(batch normalization)層,finetune時最好不要凍結BN的參數,否則數據分布不一致時很容易使輸出值變的很大.

我的問題

我這里碰到的問題,其實是通過第6點解決的。如圖,inception_resnet_v2是我從github上找的,其中use_global_stats值為true.應當進行修改,訓練階段是false,測試階段是true。


batch normaliztionuse_global_statstrue改成false.

batch_norm_param {
use_global_stats: false
}


參考鏈接

Caffe 訓練時loss等於87.3365且保持不變的原因及解決方法

Caffe訓練時Loss不下降問題


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM