本人使用的是tensorflow框架,生成tfrecord的數據集進行訓練,網路是mobile_netV1的卷積網路,訓練的時候batch_size也是32,網路訓練完時的準確率達到90%左右

但是當我將batchsize的大小改為1,然後用訓練好的模型測試,準確率下降到了20%!而把batch_size回調到32,使用訓練好的模型測試時,準確率就回升了

在這裡,將m=1(batch_size=1)代入,最後的y=beta,輸入x失效了。

但是實際上代碼中會將mean/var記錄下來。

def batchnorm_forward(x, gamma, beta, bn_param):
"""
Input:
- x: (N, D)維輸入數據
- gamma: (D,)維尺度變化參數
- beta: (D,)維尺度變化參數
- bn_param: Dictionary with the following keys:
- mode: train 或者 test
- eps: 一般取1e-8~1e-4
- momentum: 計算均值、方差的更新參數
- running_mean: (D,)動態變化array存儲訓練集的均值
- running_var:(D,)動態變化array存儲訓練集的方差

Returns a tuple of:
- out: 輸出y_i(N,D)維
- cache: 存儲反向傳播所需數據
"""
mode = bn_param[mode]
eps = bn_param.get(eps, 1e-5)
momentum = bn_param.get(momentum, 0.9)

N, D = x.shape
# 動態變數,存儲訓練集的均值方差
running_mean = bn_param.get(running_mean, np.zeros(D, dtype=x.dtype))
running_var = bn_param.get(running_var, np.zeros(D, dtype=x.dtype))

out, cache = None, None
# TRAIN 對每個batch操作
if mode == train:
sample_mean = np.mean(x, axis = 0)
sample_var = np.var(x, axis = 0)
x_hat = (x - sample_mean) / np.sqrt(sample_var + eps)
out = gamma * x_hat + beta
cache = (x, gamma, beta, x_hat, sample_mean, sample_var, eps)
running_mean = momentum * running_mean + (1 - momentum) * sample_mean #&

希望能夠幫助到樓主。

參考自:

【AlexeyAB DarkNet框架解析】十一,BN層代碼詳解(batchnorm_layer.c)?

cloud.tencent.com


昨天我也遇到這種問題,後來發現是訓練好之後,你去「測試」訓練集,如果你改了batch size的同時還是讓is_training=True,BN層計算出來的mean和var肯定與訓練時不同了,效果肯定會很差,所以要設置is_training=False,滑動平均的mean和var(這樣得出來的在訓練集的性能有可能也會比訓練時差一點點)


batchnorm其實是需要使用全局數據的均值和方差,這樣會更好的做歸一化變換,當你的size=1時,均值和方差無法準確的計算,自然你的loss會很震蕩,當你的loss值震蕩時,會較大範圍的影響各層的參數,使得性能下降,針對此在2017年2018年提出了很多分組歸一化等改進方法,可以去參考下。


這種問題99%出在batchnorm層上。。。可以嘗試把batchnorm層調到train/val的狀態試試看


學習率怎麼設置的?

你把訓練集的loss 一起列印出來。。可能是過擬合了


最好把tensorboard 打開debug,然後把training loss for列印出來debug,一般很少有人會把batch size設為1,波動性太大很容易造成大的偏移,這樣到達不了最優點


訓練loss沒問題的話,要麼是過擬合,要麼就是測試過程的網路結構和參數就有問題。


推薦閱讀:
相關文章