attention 输出的长度取决于注意力有多集中,不同 token 之间能差好几倍。LayerNorm 把每个 token 的向量拉回均值 0、方差 1,这一篇只说它怎么算、按什么方向统计。
上一篇我们讲了 Transformer(5) - multi-head attention。
通过多个 head,attention 让每个 token 根据上下文重新生成了自己的表示。
比如这句话:
I love machine learning经过 attention 之后,learning 这个 token 不再只是它自己的意思,还揉进了 machine、love 提供的信息。
但 attention 输出之后,结构图上还有一步:
Attention
↓
LayerNorm这就是 LayerNorm。
它到底做了什么?
先不看神经网络,只看一个普通向量。
假设某个 token 当前的表示是,这里 取 4:
x = [2, 4, 6, 8]LayerNorm 做的第一件事,是算它的平均值:
然后让每个数减去它:
[2-5, 4-5, 6-5, 8-5] = [-3, -1, 1, 3]这一步的作用,是把整个向量的中心挪到 0 附近。
但只减均值还不够。
因为不同向量的变化范围可能差很远。比如:
[-3, -1, 1, 3]
[-300, -100, 100, 300]这两个向量结构几乎一样,数值规模却差了 100 倍。
所以还要除以标准差:
这一步之后, 变成均值 0、方差 1 的向量。上面那个例子里,标准差是 ,结果是:
[-1.342, -0.447, 0.447, 1.342]这就是归一化。
看到这里可能会问:既然都归一化了,是不是所有输出都会变成同一种形式?
不会。
因为后面还有两个可学习参数:
完整公式:
归一化负责调整分布, 和 负责把结果拉回模型需要的范围。
初始化成全 1, 初始化成全 0,所以训练刚开始的时候,输出就是纯粹的归一化结果。之后由训练决定每个维度要不要放大、偏移多少。
所以 LayerNorm 不是把所有信息抹平,它只是帮模型把输入整理一下,让后续计算更稳。
顺带说一个边界情况。如果这 4 个数完全一样,比如 ,方差是 0,分母只剩 ,结果是全零,靠 拉回来。这也是 不能省的原因。
弄懂它做什么之后,再来看 Transformer 为什么需要它。
神经网络里每算一次,数据的表示就变一次。
比如某一层的输出:
[0.2, -0.5, 1.3, 0.8]再过几层,可能变成:
[8.5, -12.4, 20.1, 6.7]这两个向量可能表达类似的信息,数值范围却完全不同。后面的层就得不断适应这种变化,每次进来的分布都不一样,训练更难。
attention 的输出尤其容易这样。
它是所有 token 的 的加权和,权重加起来等于 1。加权和落在这些 围成的凸包里,注意力越分散,结果缩得越厉害。有的 token 注意力很集中,长度接近满值。
同一层里,两个 token 的向量长度能差好几倍。而它们接下来要乘同一套矩阵,矩阵没法给每个 token 单独配一个放大倍数。
LayerNorm 就是在中间不断把向量拉回稳定的分布,让后面那次乘法面对的东西是齐的。
一句话:
LayerNorm 不是让模型学得更多,而是让模型更容易学。
这里有个容易混的地方。既然叫 Normalization,为什么不用 BatchNorm?
因为归一化的对象不一样。
BatchNorm 看的是一批样本:
样本 A
样本 B
样本 C把它们在同一个维度上的值凑起来,算均值和方差。
LayerNorm 看的是一个样本内部的特征,也就是一个 token 的隐藏向量:
[0.2, -0.5, 1.3, 0.8]只根据这个向量自己的数据算均值和方差,跟别的 token、跟 batch 大小都没关系。
Transformer 里每个 token 都有自己的表示,训练时 batch 大小和句子长度又都在变。按 batch 统计的麻烦就出来了:推理时如果只有一条样本,没有 batch 统计量可用,只能拿训练时攒的滑动平均值。变长序列拼成一个 batch 要 padding,统计量会被填充出来的零污染。
所以这里用 LayerNorm 更合适。
LayerNorm 做的事其实很简单。给一个向量:
它解决的问题也很明确:数据经过一层层计算,分布会变,LayerNorm 让中间表示保持稳定,模型更容易训练。
到这里,attention 和它后面的归一化就说完了。