BN的过程,具体是怎样计算均值和方差的?


对于一个小批次的图像样本,NCHW [128,3,10,10], BN的过程,具体是怎样计算均值和方差的?

下来找到部分相关代码如下:(\tensorflow\python\layers\normalization.py)
  def call(self, inputs, training=False):
    # First, compute the axes along which to reduce the mean / variance,
    # as well as the broadcast shape to be used for all parameters.
    input_shape = inputs.get_shape()
    ndim = len(input_shape)
    reduction_axes = list(range(len(input_shape)))
    del reduction_axes[self.axis]
    broadcast_shape = [1] * len(input_shape)
    broadcast_shape[self.axis] = input_shape[self.axis].value

    # Determines whether broadcasting is needed.
    needs_broadcasting = (sorted(reduction_axes) != list(range(ndim))[:-1])

    scale, offset = self.gamma, self.beta

    # Determine a boolean value for `training`: could be True, False, or None.
    training_value = utils.constant_value(training)
    if training_value is not False:
      # Some of the computations here are not necessary when training==False
      # but not a constant. However, this makes the code simpler.
      mean, variance = nn.moments(inputs, reduction_axes)

最后一行的 reduction_axes 去除的元素是在如下的代码:  axis = 1 if data_format == DATA_FORMAT_NCHW else -1
也就是del reduction_axes[self.axis] 中的self.axis 在channel_first的情况下为1,即reduction_axes为[0,2,3]
效果就是在C channel这一维 reduce计算 均值和方差!


另外一点小问题,本以为计算均值,方差会是 tf.mean, tf.std之类的方法,不知道还有 nn.moments这样的方法来计算.. 先搜了一下moments这个东东。。名字是矩? moment是动量?  其实 其原始含义是“to move"或者“移动”,这样就好理解了。不了解的同学也先自行了解吧。

其实在nn.moments的注释里有提示:
  When using these moments for batch normalization (see
  `tf.nn.batch_normalization`):

   * for so-called "global normalization", used with convolutional filters with
     shape `[batch, height, width, depth]`, pass `axes=[0, 1, 2]`.
   * for simple batch normalization pass `axes=[0]` (batch only).
  
  
  看一个例子:

import tensorflow as tf
a = []
for i in range(24):
    for j in range(5):
        a.append(float(i+1))

shape = [2,3,4,5]
b = tf.constant(a, shape=shape)

axis1 = list(range(len(shape)-1))  #从最后一维计算 均值方差
axis2 = list(range(len(shape)))  
del axis2[1]                       #模仿NCHW,从chanel维计算 均值方差

end_mean, end_var = tf.nn.moments(b, axis1)
cha_mean, cha_var = tf.nn.moments(b, axis2)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for temp in [b, end_mean, cha_mean]:
        print ('\n', sess.run(temp))

 

执行结果:

[[[[  1.   1.   1.   1.   1.]
   [  2.   2.   2.   2.   2.]
   [  3.   3.   3.   3.   3.]
   [  4.   4.   4.   4.   4.]]

  [[  5.   5.   5.   5.   5.]
   [  6.   6.   6.   6.   6.]
   [  7.   7.   7.   7.   7.]
   [  8.   8.   8.   8.   8.]]

  [[  9.   9.   9.   9.   9.]
   [ 10.  10.  10.  10.  10.]
   [ 11.  11.  11.  11.  11.]
   [ 12.  12.  12.  12.  12.]]]


 [[[ 13.  13.  13.  13.  13.]
   [ 14.  14.  14.  14.  14.]
   [ 15.  15.  15.  15.  15.]
   [ 16.  16.  16.  16.  16.]]

  [[ 17.  17.  17.  17.  17.]
   [ 18.  18.  18.  18.  18.]
   [ 19.  19.  19.  19.  19.]
   [ 20.  20.  20.  20.  20.]]

  [[ 21.  21.  21.  21.  21.]
   [ 22.  22.  22.  22.  22.]
   [ 23.  23.  23.  23.  23.]
   [ 24.  24.  24.  24.  24.]]]]

 [ 12.5  12.5  12.5  12.5  12.5]

 [  8.5  12.5  16.5]

 

解释:

从最后一维计算 均值方差: 结果[ 12.5  12.5  12.5  12.5  12.5]   这是每一个最后一维的值1+2+...+24 的结果除以24个数。

从chanel维计算 均值方差: 结果 [  8.5  12.5  16.5]    计算方法是 (1+2+3+4+13+14+15+16 )*5 / (4*5*2) ... 其他两个类推

 

 

 


19 年中 再来看 以前写的这篇BN 觉得太浅了,很多没说清楚。

BN是为了使深度学习中每一层神经网络的输入 保持相同的分布的,把不同的分布强行拉回到均值为0 方差为1的分布。

上面说的在channel这一维计算均值方差,是针对CNN场景的BN来说的。

对于DNN的BN来说,其求均值的对象 是一个Batch之内的n个样本 被同一个神经元 激活的激活值,所有(n个数加和)

对于CNN的BN来说,其求均值的对象 是一个Batch之内的n个样本 被同一个卷积核的输出通道 激活的激活值,所有(n个激活平面加和,比如 NCHW [128,3,10,10], 则为 128个样本 * 10 * 10)

建议大家 看张俊林老师写的BN相吧!
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在测试时,使用训练时统计的均值方差可以通过设置 `nn.BatchNorm1d` 中的 `training` 参数来实现。具体来说,当 `training` 参数设置为 `True` 时,`nn.BatchNorm1d` 会使用当前批次数据的均值方差来进行归一化;当 `training` 参数设置为 `False` 时,`nn.BatchNorm1d` 会使用训练时统计的均值方差来进行归一化。 下面是一个使用训练时统计的均值方差进行测试的示例代码: ```python import torch import torch.nn as nn # 假设你已经定义好了一个 BatchNorm 层 bn bn = nn.BatchNorm1d(num_features) # 训练阶段 bn.train() for inputs, labels in train_loader: # 前向传播 outputs = bn(inputs) # 计算均值方差 batch_mean, batch_var = torch.mean(outputs, dim=0), torch.var(outputs, dim=0) # 更新全局均值方差 bn.running_mean = bn.momentum * bn.running_mean + (1 - bn.momentum) * batch_mean bn.running_var = bn.momentum * bn.running_var + (1 - bn.momentum) * batch_var # 测试阶段 bn.eval() with torch.no_grad(): for inputs, labels in test_loader: # 前向传播 outputs = bn(inputs, training=False) # 设置 training=False,使用训练时统计的均值方差 # ... ``` 在上述代码中,`bn.running_mean` 和 `bn.running_var` 记录了训练过程中统计的全局均值方差,`bn.momentum` 是一个超参数,用于控制全局均值方差的更新速度。在训练阶段,我们需要遍历所有训练数据来计算均值方差,并通过 `bn.running_mean` 和 `bn.running_var` 更新全局均值方差;在测试阶段,我们可以通过 `training=False` 来使用训练时统计的均值方差进行归一化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值