批量归一化 讨论区

http://zh.diveintodeeplearning.org/chapter_convolutional-neural-networks/batch-norm.html

这一节的参数初始化阶段,使用nd.random.normal(),尝试使用nd.random_normal()报错,之前 卷积神经网络-从0开始 那里的参数初始化使用nd.random_normal(),这两者有区别呢?

其实是新版把 nd.random_normal重命名到了nd.random.normal,为了跟numpy一致。推荐使用后者

好的,非常感谢李沐大神的回答,感觉有您在很踏实啊,希望您多关注帖子,非常感谢~

加了批量归一化,train_acc训练结果很棒,但是test_acc始终在0.7附近徘徊
2017-10-24 15-24-32屏幕截图

batchnorm主要是让收敛变快,但对acc影响不大。后者需要靠教程里讨论的别的技术

4赞

"我们希望批量中的每一列都被归一化。结果符合预期。"
为什么对全连接层做BN时候只计算列方向的?

    if len(X.shape) == 2:
        # 每个输入维度在样本上的平均和方差
        mean = X.mean(axis=0)
        variance = ((X - mean)**2).mean(axis=0)
    # 2D卷积: batch_size x channel x height x width
3赞
` # 均一化
if is_training:
    X_hat = (X - mean) / nd.sqrt(variance + eps)
    #!!! 更新全局的均值和方差
    moving_mean[:] = moving_momentum * moving_mean + (
        1.0 - moving_momentum) * mean
    moving_variance[:] = moving_momentum * moving_variance + (
        1.0 - moving_momentum) * variance
else:
    #!!! 测试阶段使用全局的均值和方差
    X_hat = (X - moving_mean) / nd.sqrt(moving_variance + eps)

# 拉升和偏移
return gamma.reshape(mean.shape) * X_hat + beta.reshape(mean.shape)`

这段计算batch normal的代码是不是错了,应该 是训练的时候用全局的均值和方差,测试的时候用移动平均的方法,因为测试的时候不是一个batch一个batch往里送,有可能一下子送进来很多数据。

为什么用例子的代码,学习不收敛呢,调低了学习率,也没用。但是运行gluon 版,就可

这是数据的原因。当维度为2的时候,维度是(batch, num_features),每一列都认为是一列特征,不同特征间的分布、相关性都是未知的,所以一般不对所有特征做BN,但是可以认为相同的特征来自相同的分布,所以在一个batch里面每一个feature单独做BN。
当维度为4的时候,(batch, channel, height, weight),不同的channel数据的分布可能不同,所以不对不同通道的数据做BN,同时对于图像数据,都是像素点,会假设相同通道的像素点取自相同的分布,所以对于四维的数据,同一个batch 里面,每个通道单独做BN。

个人理解:不同的BN,基于不同的数据特征假设。

3赞

BN中使用的均值和方差最好是总体的均值和方差。总体是未知的,所以只能去估计总体的方差。
理论上来说,什么时候用哪个均值、哪个方差是两方面的考虑:1.对总体均值和反差的估计的置信度 2.计算的方便

当然实际上来说,就是哪个效果好用哪个。

至于为什么测试集的时候使用移动平均,教程里也有说明:

  • 不用的话,训练出的模型参数很可能在测试时就不准确了;
  • 用的话,万一测试的数据就只有一个数据实例就不好办了。

我根据教程训练的也是这样,尝试去掉net中的两个BN操作训练结果正常了;然后我尝试将batch_norm里的is_trainning 反置训练结构也正常了;看了评论区的其他帖子,这里应该要理解训练和测试时应该使用全局归一化还是移动平均归一化;具体也不是太理解,慢慢来吧。

我也遇到和你一样的问题,请问你解决了吗?

我表达有误,就是batch_norm里的is_trainning取反,训练集时用全局归一,测试时用移动平均归一。

按照教程代码运行一遍,也是出现了不收敛的情况

查看了运行中的params的变化,在进行梯度下降更新params时,W1出现了溢出NAN,把learning_rate调小后还是出现这种情况,不知道该怎么处理了~


输入是一个 A = nd.arange(12).reshape((3,4))
第一个红框的结果是仅有BatchNorm模块网络的输出,
第二个红框的结果用tutorial里的函数跑的结果

第一个红框,用net BatchNorm的输出应该是错的,它几乎对原始数据没有做任何改变。
一开始我以为是Moving_mean,Moving_Std的问题,然后我用更多的随机数据跑了1000次之后,发现Moving_mean和Moving_std还是 zeros & ones
image

所以想请问nn.BatchNorm内部是怎么实现的?为什么输出和原始数据一样

net(x)是用了预测模式

with autograd.record():
    net(x)

是训练模式。

两个模式下batchnorm行为不一样

2赞

十分感谢

我在训练的时候,也遇到这个问题。请问你是否已经解决了这个问题。