本人使用的是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没问题的话,要么是过拟合,要么就是测试过程的网路结构和参数就有问题。


推荐阅读:
相关文章