Note-归一化层和前向源码

本专栏主要是深度学习/自动驾驶相关的源码实现,获取全套代码请参考

简介

深度学习中常见的归一化层包括批量归一化(Batch Normalization)、层归一化(Layer Normalization)、实例归一化(Instance Normalization)、组归一化(Group Normalization)。
在这里插入图片描述
批量归一化(Batch Normalization):BN专注于标准化任何特定层的输入(即来自先前层的激活)。标准化输入意味着网络中任何层的输入应具有大约为零的均值和单位方差。BN通过减去当前mini-batch中的输入均值并除以标准差来变换当前mini-batch中的每个输入。此外,BN引入了两个可学习的参数γ和β,用于缩放和平移归一化后的值,以保留原有学习来的特征,同时完成归一化操作,加速训练。
层归一化(Layer Normalization):LN在通道方向上对CHW进行归一化,主要对RNN作用明显。
实例归一化(Instance Normalization):IN在图像像素上对HW进行归一化,主要用于风格化迁移。
组归一化(Group Normalization):GN将通道分组,然后再进行归一化。
这些归一化层的作用主要包括提高优化效率、缓解内部协变量偏移问题、作为正则化方法和提高泛化能力等。但它们也有各自的缺点,例如BN需要较大的批量大小才能有效地逼近小批量的总体均值和方差,这使得BN在训练网络用于对象检测、语义分割等应用时较为困难。

BN层

计算过程

假设输入shape为[4,3,240,240]
BN归一化相当于作用在通道维度上,一共3次归一化,分别求通道1、2、3的4张240x240照片的均值和方差,也就是分别计算3次[4,240,240]数据的均值和方差。

参数说明

主要包含4个参数:均值μ和方差σ²,缩放和平移变量 γ 和 β
均值和方差在训练过程统计得到,可以通过设置momentum值,进行增量式统计,即
x n = ( 1 − m o m e n t u m ) ∗ x n − 1 + m o m e n t u m ∗ x x_n = (1-momentum)*x_{n-1} + momentum* x xn=(1momentum)xn1+momentumx
在测试过程:拿上面训练的结果使用
缩放和平移变量 γ 和 β通过学习得到

验证

def my_bn(input: torch.Tensor, weight=None, bia=None):
    channels = input.size(1)
    num = input.size(0) * input.size(2) * input.size(3)
    output = deepcopy(input)
    # c个均值 c个标准差 c维度gamma c维theta  前两个统计得到,后两个学习得到
    exs = []
    dxs = []
    gamma = torch.ones(size=(channels,))
    theta = torch.zeros(size=(channels,))
    if weight:
        gamma = weight
    if bia:
        theta = bia
    # 按照通道遍历计算
    for channel in range(channels):
        ex = input[:, channel, :, :].sum() / num
        exs.append(ex)
        dx = torch.pow(torch.pow(input[:, channel, :, :] - ex, 2).sum() / num, 0.5)
        dxs.append(dx)
        output[:, channel, :, :] = (output[:, channel, :, :] - ex) / (dx + 0.00001)  # 0.00001 for zero denominator
        output[:, channel, :, :] = gamma[channel] * output[:, channel, :, :] + theta[channel]
    return output


if __name__ == '__main__':
    bn = nn.BatchNorm2d(3)
    input = torch.randn(size=(2, 3, 5, 5))
    output = bn(input)
    output_mybn = my_bn(input)

输出结果一致,说明计算过程没有问题

问题:bn层前面的cov不需要bia的原因

每一个卷积核的bia会使得cov输出对应通道的x都变成x+bia
bn层计算当前通道时均值变成mean+bia,标准差不变
z = γ ∑ ( x + b i a − m e a n − b i a ) 2 v a r + θ z = γ ∑ ( x − m e a n ) 2 v a r + θ z=\gamma \frac{\sum (x+bia-mean-bia)^2}{var}+ \theta \newline z=\gamma \frac{\sum (x-mean)^2}{var}+ \theta \newline z=γvar(x+biameanbia)2+θz=γvar(xmean)2+θ
所以cov的bia没用作用

LN层

计算过程

Layer Normalization目前在transfomer框架中大量运用.
假设输入shape为[4,3,240,240]
LN归一化相当于作用在样本数量上,一共4次归一化,分别求照片1、2、3、4的均值和方差,也就是计算4次[3,240,240]数据的均值和方差。

参数说明

主要包含4个参数:均值μ和方差σ²,缩放和平移变量 γ 和 β
均值和方差在正向传播时统计得到,训练测试一样,无需momentum值
缩放和平移变量 γ 和 β通过学习得到

验证

def my_ln(input: torch.Tensor, weight=None, bia=None):
    batchs = input.size(0)
    num = input.size(1) * input.size(2) * input.size(3)
    output = deepcopy(input)
    # c个均值 c个标准差 c维度gamma c维theta  前两个统计得到,后两个学习得到
    exs = []
    dxs = []
    gamma = torch.ones(size=(batchs,))
    theta = torch.zeros(size=(batchs,))
    if weight:
        gamma = weight
    if bia:
        theta = bia
    # 按照batch遍历计算
    for batch in range(batchs):
        ex = input[batch,:, :, :].sum() / num
        exs.append(ex)
        dx = torch.pow(torch.pow(input[batch,:, :, :] - ex, 2).sum() / num, 0.5)
        dxs.append(dx)
        output[batch,:, :, :] = (output[batch,:, :, :] - ex) / (dx + 0.00001)  # 0.00001 for zero denominator
        output[batch,:, :, :] = gamma[batch] * output[batch,:, :, :] + theta[batch]
    return output


if __name__ == '__main__':
    ln = nn.LayerNorm((3, 5, 5))
    input = torch.randn(size=(2, 3, 5, 5))
    output = ln(input)
    output_myln = my_ln(input)

输出结果一致,说明计算过程没有问题

问题:transfomer用LN而不是BN的原因

CV使用BN是认为rgb维度的信息不具有关联性,如果对channel维度也归一化会造成信息损失;认为图片之间因为有物理意义的约束,样本之间具有相似性,所以使用BN。
而同理nlp领域认为不同句子直接不具有关联性,batch维度归一化导致句子信息丢失;而句子内部具有关联性,所以使用LN.
那么VIT呢?

如需获取全套代码请参考

  • 26
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Attention is all you

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

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

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

打赏作者

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

抵扣说明:

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

余额充值