AI summary
type
status
date
slug
summary
category
tags
icon
password
Normalization

Batch Norm
为什么要进行 Batch Norm?
(1) 解决内部协变量偏移(Internal Covariate Shift)
- 问题:在深度神经网络中,每一层的输入分布会随着训练的进行而不断变化(因为前面层的参数在更新),导致后续层需要不断适应新的数据分布,影响训练效率。
- BN 作用:对每个 mini-batch 进行归一化,使得每一层的输入分布更加稳定,从而加速训练。
(2) 使梯度传播更加稳定
- 问题:如果输入数据的分布变化较大,可能会导致梯度消失或梯度爆炸,影响模型的收敛。
- BN 作用:通过归一化,使得数据分布更加稳定,梯度的变化范围也更加可控,从而提高训练的稳定性。
(3) 允许使用更大的学习率
- 问题:在深度网络中,较大的学习率可能会导致梯度更新过大,使得训练不稳定。
- BN 作用:由于 BN 归一化了数据分布,使得网络对学习率的选择更加鲁棒,可以使用更大的学习率,从而加快收敛速度。
(4) 具有一定的正则化效果
- 问题:深度网络容易过拟合,尤其是在数据量较小时。
- BN 作用:由于 BN 在 mini-batch 级别进行归一化,相当于对数据引入了一定的噪声(每个 batch 的均值和方差都略有不同),这类似于 Dropout 的正则化效果,可以提高模型的泛化能力。
Batch 是一个广义的概念,指的是一次训练所使用的样本数量。Mini-Batch 是 Batch 的一种特殊情况,指的是 小批量 训练,而不是使用整个数据集。
BN 的过程是什么?在什么位置使用?
BN的主要思想:针对每个神经元,使数据在进入激活函数之前,沿着通道计算每个 batch 的均值、方差,‘强迫’数据保持均值为 0,方差为 1 的正态分布。
具体来说,就是把第 1 个样本的第 1 个通道,加上第 2 个样本第 1 个通道...加上第 N 个样本第 1 个通道,求平均,得到通道 1 的均值(注意是除以 N×H×W 而不是单纯除以 N,最后得到的是一个代表这个 batch 第 1 个通道平均值的数字,而不是一个 H×W 的矩阵)。求通道 1 的方差也是同理。对所有通道都施加一遍这个操作,就得到了所有通道的均值和方差。
然后对每个像素点进行归一化,最后加入每个通道独立的可学习参数进行缩放和平移,用于恢复模型的表达能力。
BN的使用位置: 全连接层或卷积操作之后,激活函数之前。
通道(Channel)是什么?在深度学习中的 卷积神经网络(CNN) 里,通道(Channel) 指的是输入数据或特征图(Feature Map)的 深度维度。
- 对于彩色图片:
- 一张图片通常有 3 个通道(红 R、绿 G、蓝 B)。
- 形状为 (C, H, W),其中:
- C 是通道数(RGB 图像中 C=3)。
- H 是高度(Height)。
- W 是宽度(Width)。
- 对于 CNN 中的特征图:
- 经过卷积层后,数据的通道数可能会增加,比如 ResNet 里某一层的特征图可能是 (64, 32, 32),表示有 64 个通道,每个通道的大小是 32×32。
BN 存在的问题?
- 每次是在一个 batch 上计算均值、方差,如果 batch size 太小,则计算的均值、方差不足以代表整个数据分布。
- batch size 太大:会超过内存容量;需要跑更多 epoch,导致总训练时间变长;会直接固定梯度下降的方向,导致很难更新。
- 在 RNN 中效果较差:
RNN 是可以用 BN 的,只需要让每个 Batch 的长度相等,可以通过对每个序列做补长,截断来实现。
RNN 不适合用 BN 的原因:Normalize 的对象(position)来自不同分布。CNN 中使用 BN,对一个 batch 内的每个 channel 做标准化。多个训练图像的同一个 channel,大概率来自相似的分布(例如树的图,起始的 3 个 channel 是 3 个颜色通道,都会有相似的树形状和颜色深度)。而 RNN 中多个 sequence 的同一个 position,很难说来自相似的分布(例如都是影评,但可以使用各种句式,同一个位置出现的词很难服从相似分布)。所以 RNN 中 BN 很难学到合适的 和 ,将来自不同分布的特征做正确变换,甚至带来反作用,所以效果不好。
BN 是不适用于 RNN 这种动态结构的。如果将 BN 应用在 RNN 中,由于 BN 是以 batch 为单位统计归一化变量的,所以不同长度的样本的时间片如何计算将十分困难。在 BN 中我们需要根据训练数据保存两个统计量 和 ,如果在测试时一组样本的长度大于训练的所有样本,那么它的后面的时间片该怎么办?
可以理解为 channel=position
Layer Norm
怎么算的?
Layer Normalization(LN)是一种对单个样本的所有特征进行归一化的方法。与 Batch Normalization(BN)不同,LN不依赖 mini-batch 统计信息,而是在特征维度上计算均值和方差,适用于小 batch size 甚至 batch size = 1 的情况。LN用于RNN效果比较明显,但是在CNN上,效果不如BN。
这里结合 PyTorch 的 nn.LayerNorm 算子来看比较明白:
normalized_shape:归一化的维度,int(最后一维)list(list里面的维度),还是以(2,2,4)为例,如果输入是 int,则必须是 4,如果是 list,则可以是 [4], [2,4], [2,2,4],即最后一维,倒数两维,和所有维度。
eps:加在分母方差上的偏置项,防止分母为 0。
elementwise_affine:是否使用可学习的参数 和 ,前者开始为 1,后者为 0,设置该变量为 True,则二者均可学习随着训练过程而变化。
如果输入是 2D(如
(batch_size, num_features)):normalized_shape=num_features,即对 每个样本的所有特征 进行归一化。
如果输入是 3D(如
(batch_size, seq_len, hidden_dim)):normalized_shape=hidden_dim,即对 每个时间步的隐藏层维度 进行归一化。
如果输入是 4D(如
(batch_size, channels, height, width)):normalized_shape=(channels, height, width),即对 每个样本的所有通道和空间维度 进行归一化。
Instance Norm
用于什么?怎么算的?
IN 针对图像像素做 normalization,最初用于图像的风格化迁移。在图像风格化中,生成结果主要依赖于某个图像实例,feature map 的各个 channel 的均值和方差会影响到最终生成图像的风格。所以对整个 batch 归一化不适合图像风格化中,因而对H、W做归一化。可以加速模型收敛,并且保持每个图像实例之间的独立。
Group Norm
用于什么?怎么算的?
GN 是为了解决 BN 对较小的 mini-batch size 效果差的问题。
GN 适用于占用显存比较大的任务,例如图像分割。对这类任务,可能 batch size 只能是个位数,再大显存就不够用了。而当 batch size 是个位数时,BN 的表现很差,因为没办法通过几个样本的数据量,来近似总体的均值和标准差。GN 也是独立于 batch 的,它是 LN 和 IN 的折中。
具体方法: GN 计算均值和标准差时,把每一个样本 feature map 的 channel 分成 G 组,每组将有 C/G 个 channel,然后将这些 channel 中的元素求均值和标准差。各组 channel 用其对应的归一化参数独立地归一化。
RMS Norm
与 layerNorm 相比,RMS Norm 的主要区别在于去掉了减去均值的部分,也没有偏移参数 。
计算量比 LN 稍低;在某些情况下,均值的变化可能会影响模型的稳定性,RMSNorm 只依赖 RMS,避免了均值的影响,使得归一化更加稳定;
LLaMA 使用 RMSNorm 代替 LayerNorm,提高了训练稳定性。
Deep Norm
Motivation?method?
Deep Norm 是对 Post-LN 的的改进,具体的:

- DeepNorm 在进行 Layer Norm 之前会以 参数扩大残差连接
- 在 Xavier 参数初始化过程中以 减小部分参数的初始化范围
论文中,作者认为 Post-LN 的不稳定性部分来自于梯度消失以及太大的模型更新,同时,有以下几个理论分析
- 定义了“预期模型更新”的概念表示 模型更新的规模量级
- 证明了 和 不会改变注意力输出大小数量级的界限,因而 并没有缩小这部分参数
- 模型倾向于累积每个子层的更新,从而导致模型更新量呈爆炸式增长,从而使早期优化变得不稳定
- 使用 Deep Norm 的 "预期模型更新",在两个参数取值适当的时候,以常数为界
同时,作者通过实验证实了 Deep Norm 在训练深层 transformer 模型的时候具备近乎恒定的更新规模,成功训练了 1000 层 transformer 的模型,认为 Deep Norm 在具备 Post-LN 的良好性能 的同时又有 Pre-LN 的稳定训练
Post-LN 和 Pre-LN

左边是原版 Transformer 的 Post-LN,即将 LN 放在 addition 之后;右边是改进之后的 Pre-LN,即把 LN 放在 FFN 和 MHA 之前。
一般认为,Post-Norm 在残差之后做归一化,对参数正则化的效果更强,进而模型的收敛性也会更好;而 Pre-Norm 有一部分参数直接加在了后面,没有对这部分参数进行正则化,可以在反向时防止梯度爆炸或者梯度消失。大模型的训练难度大,因而使用 Pre-Norm 较多。
目前比较明确的结论是:同一设置之下,Pre Norm 结构往往更容易训练,但最终效果通常不如Post Norm。Pre Norm更容易训练好理解,因为它的恒等路径更突出,但为什么它效果反而没那么好呢?为什么Pre Norm的效果不如Post Norm?