理解CNN中的Batch Normalization

批归一化处理(Batch Normalization, BN层)通常用于深层的神经网络中,其作用是对网络中某层特征进行标准化处理,其目的是解决深层神经网络中的数值不稳定的问题,是的同批次的各个特征分不相近,网络更加容易训练。

BN层一般是放在仿射变换,FC或CONV,层后,在非线性激活单元之前(也有一些实现放在线性激活单元后,但是普遍用法是前者)。

深层网络的数值不稳定的问题是,随着网络层数加深,训练过程中参数的更新容易造成靠近输出层的特征输出产生剧烈地变化,不利于训练出有效的神经网络。

BN层原理

BN层常见有针对1d特征(全连接层后面的)以及针对2d特征(2d卷积层后面的)两种(这里暂不讨论3d卷积)。 依照管理,我们从1d开始理解。

BatchNorm1d

假设在训练过程中,一批次的全连接层输出的特征为 x , 张量的shape为 (batch size=m, feature dim=d),我们如下表示输入:
x = [ x ( 1 ) , x ( 2 ) , . . . , x ( m ) ] x = [x^{(1)}, x^{(2)}, ..., x^{(m)}] \\ x=[x(1),x(2),...,x(m)]

  • 首先,我们需要沿着batch的维度 对该小批量的特征求其均值和方差:

μ B = 1 m ∑ i = 1 m x ( i ) σ B 2 = 1 m ∑ i = 1 m ( x ( i ) − μ B ) 2 \mu_{B} = \frac{1}{m}\sum_{i=1}^{m}{x^{(i)}}\\ \sigma_B^2 = \frac{1}{m}\sum_{i=1}^{m}{(x^{(i)} - \mu_B)^2} μB=m1i=1mx(i)σB2=m1i=1m(x(i)μB)2

上式中,需要注意的是,求方差时的平方符号是针对逐元素求平方,而非求范数。所以,特征的每个channel的均值和方差时独立的,均值和方差的shape应该是feature dim = d,或者为便于计算可以认为是(1, d)。

  • 接着,我们要对特征进行标注化,并且计算BN层的输出。

x ^ ( i ) = x ( i ) − μ B σ B 2 + ϵ \hat{x}^{(i)} = \frac{x^{(i)} - \mu_{B}}{\sqrt{\sigma_B^2+\epsilon}} x^(i)=σB2+ϵ x(i)μB

上式这一步是对特征进行标准化,式中的epsilon为一个很小的常量,为了避免初零的异常。 然后,就需要计算BN层的输出了。在训练过程中,BN层有两个可以训练的参数,gamma和beta,通过这两个参数与归一化特征计算得到输出:
y ( i ) = γ ⊙ x ^ ( i ) + β   y = [ y ( 1 ) , y ( 2 ) , . . . , y ( m ) ] y^{(i)} = \gamma\odot\hat{x}^{(i)}+\beta \\ \space y = [y^{(1)},y^{(2)},...,y^{(m)}] y(i)=γx^(i)+β y=[y(1),y(2),...,y(m)]
于是,BN层的一个forward过程就结束了,其输出特征与输入特征shape相同。并且,一个BN层的可训练参数量与fearure dim有关,为 2*d ,即gamma和beta的参数。

BatchNorm2d

在卷积层后面的BN与1d情况的BN层是很类似的,同样是沿着batch的维度求均值和方差。并且,它的参数大小也仅仅与feature dim有关,也为2*d。 但是,有一点需要注意的是,在求均值和方差的时候,实际上其不仅是沿着batch的维度求取,在每个channel上的宽度和高度方向也求取均值。

img

假设,BN层上一层的卷积层的输出特征为shape [b, c, h, w] 为 [2, 2, 2, 2],如上图。我们可能会以为,按照1d的情形推理,在求均值时沿着batch的维度进行求取,那么它的均值和方差的shape应该是[1, 2, 2, 2],得到如下图的结果:

img

但是,实际上,均值和方差的shape是[1, 2, 1, 1]。也就是说,求取均值和方差时,是沿着batch, h, w三个维度进行的,只保证每个channel的统计值是独立的,所以求得均值和方差:

img

笔者期初也困惑其原因,觉得这样会破坏输入特征的拓扑结构。但是查看了一些框架的源码,确实是按照上文描述的方式。注意到这一点,详细其他地方大家可以按照1d的情形进行推演。

预测时的均值和方差

在模型预测时,我们往往希望得到稳定的输出。所以,无论预测的输入batch size为多少,我们都希望BN层始终用同一个mean和var,而不该根据输入进行变化。在实现的时候,一般采用一阶指数平滑算法实现,其原理如下。

假设一个时间序列的长度为n(在此处,每个序列的时刻为训练的一个最小步骤),我们定义一个时间序列 S = s1, s2, …, sn; 拟合序列T = t1, t2, …, tn. 这里的时间序列是每个训练迭代计算得到的mean和var,拟合序列是每个迭代,通过平滑算法计算的mean和var。那么,对于一阶指数平滑,有下式:
t i = α s i + ( 1 − α ) t i − 1 t_i = \alpha s_i +(1-\alpha)t_{i-1} ti=αsi+(1α)ti1
在进行算法前,要定义初始值t0,一般可以定义时间序列前三项的均值,也可初始为其他值。利用该算法,在每次迭代时,可以计算一个mean和var值,BN层需要将改值保存,用于预测的时候使用。 这两个值的参数量也分别与feature dim一致,它们是不可训练的参数。

利用torch自定义BN层

了解原理后,我们可以基于pytorch提供的框架,自己定义BN层,熟悉其操作过程,代码如下:

import torch
import torch.nn as nn

"""
barch normalization 操作
"""
def batch_norm(is_training, X, gamma, beta, moving_mean,
                 moving_var, eps, momentum):
    if not is_training:
        X_hat = (X - moving_mean) / torch.sqrt(moving_var + eps)
    else:
        feature_shape = len(X.shape)
        assert feature_shape in (2, 4)  
        
        if feature_shape == 2:
            # 全连接层后面的BN
            mean = X.mean(dim=0)
            var = ((X - mean) ** 2).mean(dim=0)
        else:
            # 卷积层后面的BN
            mean = X.mean(dim=(0, 2, 3), keepdim=True)
            var = ((X-mean) ** 2).mean(dim=(0, 2, 3), keepdim=True)
        X_hat = (X-mean) / torch.sqrt(var + eps)
        print(mean.shape)
        print(var.shape)
        print(X.shape)

        # 一阶指数平滑
        moving_mean = momentum * moving_mean + (1. - momentum) * mean
        moving_var = momentum * moving_var + (1. -momentum) * var

    Y = gamma * X_hat + beta
    return Y, moving_mean, moving_var


class _BatchNorm(nn.Module):
    """
    BN层
    """
    def __init__(self, num_features, num_dims, momentum):
        super(_BatchNorm, self).__init__()
        assert num_dims in (2, 4)
        if num_dims == 2:
            shape = (1, num_features)
        else:
            shape = (1, num_features, 1, 1)
        self.gamma = nn.Parameter(torch.ones(shape))
        self.beta = nn.Parameter(torch.zeros(shape))
        self.moving_mean = torch.zeros(shape)
        self.moving_var = torch.zeros(shape)
        self.momentum = momentum
    
    def forward(self, X):
        Y, self.moving_mean, self.moving_var = batch_norm(
            self.training, X, self.gamma, self.beta, self.moving_mean,
            self.moving_var, eps=1e-5, momentum=self.momentum
        )
        return Y


class BatchNorm1d(_BatchNorm):
    def __init__(self, num_features, momentum=0.9):
        super().__init__(num_features, 2, momentum)


class BatchNorm2d(_BatchNorm):
    def __init__(self, num_features, momentum=0.9):
        super().__init__(num_features, 4, momentum)

测试一下代码:
在这里插入图片描述
在这里插入图片描述

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
### 回答1: Batch Normalization是一种用于加速神经网络训练的技术。在神经网络,输入的数据分布可能会随着层数的增加而发生变化,这被称为“内部协变量偏移”问题。Batch Normalization通过对每一层的输入数据进行归一化处理,使其均值接近于0,标准差接近于1,从而解决了内部协变量偏移问题。 具体地,对于一个Mini-Batch的一组输入数据,Batch Normalization将这组数据进行标准化处理,使得其均值为0,标准差为1。这样做的好处是,可以使得每一层的输入数据分布更加稳定,从而加速神经网络的训练过程。此外,Batch Normalization还具有一定的正则化效果,可以减少过拟合问题的发生。 Batch Normalization被广泛应用于深度学习的各种网络结构,例如卷积神经网络(CNN)和循环神经网络(RNN)。它是深度学习一种非常重要的技术,可以提高网络的训练速度和准确度。 ### 回答2: Batch Normalization(批归一化)是一种用于训练深度神经网络的技术。深度神经网络的层数较多,容易出现梯度消失或梯度爆炸的问题,导致训练困难。Batch Normalization通过在神经网络的每个层对输入进行归一化处理,从而缓解了这个问题。 具体而言,Batch Normalization将每个输入特征进行标准化,使其均值为0,方差为1,然后再通过缩放和平移操作进行线性变换,将归一化后的特征重新映射回原来的数据范围。这个归一化操作是在每个batch的样本上进行的,因此称为批归一化。 批归一化有以下几个优点。首先,它使得模型更加稳定,通过减少不同层之间的协变量偏移(covariate shift),加速了网络的收敛速度。其次,批归一化减少了对初始参数选择的敏感性,使得网络参数更易于初始化。再次,批归一化还可以起到正则化的作用,减少模型的过拟合。 批归一化可以应用于深度神经网络各个层的输入。在训练时,对每个batch的输入进行归一化处理,并记录归一化所使用的均值和方差。在预测时,使用训练过程得到的均值和方差对输入进行归一化处理,以保持模型的稳定性。 综上所述,Batch Normalization是一种用于处理深度神经网络输入的技术,可以加速网络的训练收敛速度,增强模型的稳定性,并提供正则化的效果。它在深度学习领域得到了广泛的应用。 ### 回答3: Batch Normalization是一种常用的深度学习的技术,用于加速神经网络的训练和提高模型的稳定性。深度神经网络,每层的输入数据分布会随着训练过程参数的更新而发生变化,这使得网络学习变得困难,难以收敛。Batch Normalization通过在每个训练小批量对数据进行标准化处理,使得各层的输入数据分布基本稳定,有利于网络训练。 具体来说,Batch Normalization的过程分为两步。首先,对于每个小批量的数据,计算其均值和方差,然后对数据进行标准化处理,使得数据的均值接近0,方差接近1。该过程可以通过调整两个可学习参数——缩放因子(scale factor)和位移因子(shift factor)来实现,从而保留数据的表达能力。其次,将标准化后的数据通过一个仿射变换,恢复为网络层的输出。 Batch Normalization的优点包括:首先,可以加速模型的训练,因为对数据的标准化可以减少数据间的相关性,使得优化过程更快收敛;其次,可以增强模型的泛化能力,减少过拟合的风险;还可以对网络的激活函数的输出进行归一化,从而避免了梯度爆炸或消失的问题,提高了网络的稳定性和学习效率。 总之,Batch Normalization是一种通过对每个小批量的数据进行标准化处理的技术,旨在加速神经网络的训练和提高模型的稳定性,被广泛应用于深度学习

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蔡逸超

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值