這是我在訓練模型時的一個十分疑惑的問題:

我使用pytorch構建使用 BatchNormalization 層的分割模型。我發現在測試中設置 model.eval() 時,測試分割結果為0。如果不設置 model.eval() ,它將運行良好。我試圖搜索相關問題,但得出的結論是 model.eval() 可以固定BN的參數,但是我仍然對如何解決此問題感到困惑。我的batchsize設置為1,是否有此影響呢?


一般來說,Segmentation/Detection的模型,在訓練的時候,需要對backbone的網路,比如ResNet50之類的batchnorm層設置為eval mode...特別是當你的batchsize很小的時候...不確定是不是因為這個原因...當然inference的時候也要eval mode...寫的時候要特別注意...


在訓練模型時會在前面加上:

model.train()

在測試模型時會在前面使用:

model.eval()

雖然不適用這兩個語句程序也能運行,但運行的細節不一樣。比如Batch Normalization 和 Dropout。

Batch Normalization

BN的作用主要是對網路中間的每層進行歸一化處理,並且使用變換重構Batch Normalization Transform保證每層提取的特徵分佈不會被破壞。

訓練時是針對每個mini-batch的,但是測試是針對單張圖片的,即不存在batch的概念。由於網路訓練完成後參數是固定的,因此每個batch的均值和方差是不變的,因此直接結算所以batch的均值和方差。

Dropout

Dropout能夠克服Overfitting,在每個訓練批次中,通過忽略一半的特徵檢測器,可以明顯的減少過擬合現象。

詳細見文章:《Dropout: A Simple Way to Prevent Neural Networks from Overtting》

eval()就是保證BN和dropout不發生變化,框架會自動把BN和DropOut固定住,不會取平均,而是用訓練好的值,不然的話,一旦test的batch_size過小,很容易就會被BN層影響結果!!!


會不會可能是BN在模型中位置的問題?

我用 Dropout 的時候也出現過這個問題,就是 train mode 下得到的結果要比 eval mode 下要好很多。後來發現是因為我的 Dropout 放在了卷積層,將 Dropout 放到 FC 層後就正常了。

作為常用的防止過擬合的手段,Dropout 和 BN 都能起到比較好的結果,但不是在任意位置都奏效。我瞭解到的是,Dropout 通常在 FC 層有效,而在卷積層就不推薦用了。至於 BN,至少我用在卷積層是 ok 的。

或者你可以在 BN 操作那行設置一個斷點,debug 到那行的時候分別測試在同樣輸入下 train mode 和 eval mode 的輸出,然後分析比較二者的差別,或許能給解決你的問題帶來靈感。


我遇到過這個問題,折騰了好久發現是兩個地方用了同一個bn,太蠢了


請問你現在解決了嗎?我遇到了和你相同的問題,inference使用eval()準確率下降很多,是什麼原因呢


是不是訓練的時候每個batchsize很小導致的?一般小於8的話,泛化就會不理想,可以多gpu用同步版bn,增加batch size的實際大小,可以有效解決這個問題


inference肯定要啟動eval模式啊...


先檢查一下程序上有沒有錯誤,我曾經有過一次訓練和推理都用model.train()模式能出好的結果,推理換成model.eval()反倒效果很差,查了半天發現推理階段的數據歸一化和訓練階段不一致...


推薦閱讀:
相關文章