大模型"智慧骨架",LLaMA 架构介绍

LLaMA 为代表的模型,是大模型主流架构 Decoder-only 的典型代表。

相对于基础 Transformer 中的 decoder 模块,本文主要围绕 LLaMA 结构的核心组成和主要变化点,介绍以下内容:

  • LLaMA 架构的核心组成部分:MHA 和 FFN 模块的结构拆解
  • 每个模块的归一化和激活函数相对于基础 Transformer 的变化原因
  • LLaMA 系列模型发展及衍生模型介绍

1. LLaMA 架构介绍

**LLaMA(Large Language Model Meta AI)**是 Meta 发布的一款开源模型。

和 GPT 系列一样,LLaMA 模型也是 Decoder-only 架构,其主要的改进如下:

  • Pre-Norm:为了提高训练稳定性,LLaMA 对每个 Transformer 子层的输入进行归一化,使用 RMSNorm 归一化函数,好处是不用计算样本的均值,速度提升了 40%。
  • SwiGLU 前馈网络(FFN):结构上使用门控线性单元,且为了保持 FFN 层参数量不变,将隐藏单元数量调整为 4d 的三分之二(而非 Transformer 论文中的 4d),同时将 ReLU 替换为 SiLU 激活,以提高性能。
  • Rotary Embeddings:模型的输入不再使用 positional embeddings,而是在网络的每一层注入位置信息(RoPE)。

架构图如下:

LLaMA 模型架构图

2. 归一化:位置和类型的变化

2.1. 由 Post-Norm 到 Pre-Norm

图中的 post 和 pre 是指归一化相对于残差的位置。

post 是指在残差之后做归一化,而 pre 是在残差之前做归一化。

一般认为,Post-Norm 在残差之后做归一化,对参数正则化的效果更强,进而模型的收敛性也会更好

Pre-Norm 有一部分参数直接加在了后面,没有对这部分参数进行正则化,可以在反向传播时防止梯度爆炸或梯度消失,因此更适合训练难度大的大模型。

Post-Norm 与 Pre-Norm 结构对比

在相同深度条件下,Post-Norm 的效果要优于 Pre-Norm,因为 Pre-Norm 实际上相当于一个更浅却更宽的网络。

然而 LLaMA 中却采用了 Pre-Norm,或许是因为模型够深(7B、13B、33B、65B 的模型 Transformer 层数分别为 32、40、60、80),Pre-Norm 的恒等分支更加明显,有利于梯度的传播。

2.2. 由 LayerNorm 到 RMSNorm

层归一化 LayerNorm 通过对输入进行重新中心化和重新缩放(re-centering 和 re-scaling),即减均值和除方差(分别对应平移不变性和缩放不变性),来帮助稳定训练并加速模型收敛。

其计算公式为:LayerNorm(x) = γ · (x − μ) / √(σ² + ε) + β

  • LayerNorm

作用:对特征张量按照某一维度或某几个维度进行均值为 0,方差为 1 的归一化操作。

其中 μ 表示均值,σ² 表示均方值,ε 为一个极小值,防止分母为 0;γ 和 β 为可学习的缩放与平移参数。

LayerNorm 的作用方式可以理解为:对张量中指定维度的所有元素进行归一化。

比如对于 shape 为 (2, 2, 8) 的张量 input,若指定归一化的操作为第三维(最后一维,共 8 个元素),则 2×2=4 个切片会各进行一次上述计算。

nn.LayerNorm(normalized_shape, eps=1e-05, elementwise_affine=True, bias=True, device=None, dtype=None)
"""
- normalized_shape:归一化的维度,int(最后一维)或 list(list 里面的维度)。以 (2, 2, 4) 为例,如果输入是 int,则必须是 4;如果是 list,则可以是 [4]、[2, 4]、[2, 2, 4],即最后一维、倒数两维和所有维度
- eps:加在分母方差上的偏置项,防止分母为 0
- elementwise_affine:是否使用可学习参数,包括缩放参数 γ(初始为 1)和平移参数 β(初始为 0),设置为 True 时二者均可随训练过程更新
"""
  • RMSNorm

**RMSNorm(Root Mean Square Layer Normalization)**是 LayerNorm 的一种变体,可以在梯度下降时令损失更加平滑。

与 LayerNorm 相比,RMSNorm 的主要区别在于去掉了减去均值的部分(re-centering),只保留方差缩放部分(re-scaling),从归一化的表达式上可以直观地看出。

其中均方值表示为 MS(x) = (1/n) · Σxᵢ²,RMSNorm 的计算式为 RMSNorm(x) = (x / √(MS(x) + ε)) · γ

一个直观的猜测是,center 操作类似于全连接层的 bias 项,储存的是关于数据的一种先验分布信息,而把这种先验分布信息直接储存在模型中,反而可能会导致模型的迁移能力下降。

所以 T5 模型中不仅去掉了 LayerNorm 的 center 操作,还把每一层的 bias 项也都去掉了。

3. FFN:激活函数

**前馈网络 FFN(Feed Forward Network)**原版的激活函数为 ReLU,引入激活函数的目的是增加神经网络的非线性拟合能力。

3.1. ReLU 线性整流函数

**ReLU(Rectified Linear Unit)**通常指代数学中的斜坡函数,即:ReLU(x) = max(0, x)

在神经网络中使用 ReLU 激活函数作为非线性变换,得到的输出结果是:y = max(0, xW + b)

Transformer 架构中采用 ReLU 的 FFN 表达式如下:FFN(x) = max(0, xW₁ + b₁)W₂ + b₂

  • ReLU 死亡单元问题

一般参数的更新公式为 w ← w − η · ∂L/∂w。当学习率过大时,参数更新后的值可能变为负值;此时输入网络的正值与权重相乘后也会变为负值,负值通过 ReLU 后就会输出 0。

如果权重 w 在后期有机会被更新为正值也不会出现大问题,但是当 ReLU 函数输出值为 0 时,其导数也为 0,因此会导致后续的 Δw 一直为 0,权重 w 无法再被更新,这个神经元就会永久性死亡。

3.2. Sigmoid 逻辑函数和 Swish 激活函数

  • Sigmoid 逻辑函数

Sigmoid 是常用的连续、平滑的 S 型激活函数,也被称为逻辑(Logistic)函数,可以将一个实数映射到 (0, 1) 区间,用来做二分类。

其函数定义为:σ(x) = 1 / (1 + e^(-x))

Sigmoid 存在一定的梯度消失问题

即在训练深度神经网络时,随着反向传播过程的深入,当输入值过大或过小时,函数的导数(梯度)会变得非常小(接近零),导致梯度在向网络前层传播时逐渐变小,网络的前层几乎无法更新。

注意:死亡单元和梯度消失不是同一个问题,具体解释参考 [4]。

  • Swish 激活函数

Swish 又被称为 SiLU(Sigmoid Linear Unit),是 Sigmoid 和线性函数的组合Swish(x) = x · σ(βx),其中 x 是输入值,β 是一个可学习参数。

Swish 激活函数具有以下优点:

  1. 在某些情况下,Swish 的梯度更加平稳,可以减少梯度消失问题
  2. Swish 可以通过学习参数 β 来适应不同的问题,从而提高模型的泛化能力,在图像分类、自然语言处理等领域表现优秀。

3.3. GLU 及其变体

**GLU(Gated Linear Units)**其实不算是一种激活函数,而是一种神经网络层:它是一个线性变换后面接门控机制的结构,其中门控机制是一个 sigmoid 函数,用来控制信息通过的多少。

GLU 中的激活函数就是 sigmoid 函数,通过改变激活函数可以得到 GLU 的各种变体。比如 SwiGLU 就是采用 Swish 作为激活函数的 GLU 变体

SwiGLU 本质上是对 Transformer 的 FFN 前馈传播层的第一层全连接和 ReLU 进行了替换。原生的 FFN 中采用两层全连接,第一层升维,第二层降维回归到输入维度,两层之间使用 ReLU 激活函数。

SwiGLU 也是全连接配合激活函数的形式,不同的是 SwiGLU 采用两个权重矩阵分别对输入进行变换,再配合 Swish 激活函数做哈达马积的操作。

因为 FFN 本身还有第二层全连接,所以带有 SwiGLU 的 FFN 模块一共有三个权重矩阵,用公式表达如下:FFN_SwiGLU(x) = (Swish(xW₁) ⊙ xV) · W₂

其中 W₁ 和 V 为 SwiGLU 模块的两个权重矩阵,W₂ 为原始 FFN 的第二层全连接权重矩阵。

这种方式使得 FFN 中的权重矩阵从 2 个变为了 3 个,为了使模型的参数量大体不变,中间层的隐藏维度需要缩减为原来的三分之二。

SwiGLU 前馈网络结构示意

4. 位置编码

在 Transformer 等序列模型中,位置编码用于向模型注入词元的位置信息,以帮助模型理解序列的顺序关系。

4.1. Sinusoidal 位置编码

定义:基于正弦和余弦函数的数学公式生成位置编码。

  • 偶数维度PE(pos, 2i) = sin(pos / 10000^(2i/d))
  • 奇数维度PE(pos, 2i + 1) = cos(pos / 10000^(2i/d))

其中,pos 为词元位置,i 为维度索引,d 为词向量维度。

优势

  • 天然的长度外推性:正弦和余弦函数的周期性使其可生成任意长度的位置编码,无需预定义最大长度,适合处理超长序列。
  • 隐含相对位置信息:通过三角函数的性质,两个位置的编码差值可部分反映相对位置关系,缓解了绝对位置编码对相对位置感知的不足。
  • 计算高效:无需训练,直接通过公式生成,节省显存和训练成本。

4.2. RoPE(Rotary Position Embedding)

定义:通过对词向量进行旋转操作注入绝对位置信息,同时实现对相对位置的感知。

其核心是使位置为 m 的查询向量与位置为 n 的键向量的内积,仅依赖于相对位置 m−n。

优势

  • 兼顾绝对位置编码的简洁性和相对位置编码的有效性:通过绝对位置旋转的方式,自然引入相对位置信息,解决了传统绝对位置编码无法感知词元间距离的问题。
  • 支持长度外推优化:旋转角度的周期性与 base 参数相关,通过调整 base(如放大至 1000000)可扩展序列长度。
  • 数学性质稳定:旋转操作不改变向量模长,避免了位置编码对词向量本身的干扰。

5. 总结

LLaMA 架构作出的主要改变有三点:归一化采用 Pre-Norm 位置并使用 RMSNorm,FFN 中的激活函数最终选择了 SwiGLU,位置编码选择了稳定性更强的 RoPE

LLaMA 模型架构取得成功,为其变体提供了可参考的范式,目前国内流行的 Qwen 架构基本为 LLaMA 架构。

千问 Qwen 大模型与标准 Transformer 的主要区别如下

  • 使用 untied embedding 嵌入
  • 使用旋转位置嵌入,即 RoPE 相对位置编码
  • 归一化实现:RMSNorm 代替 LayerNorm
  • FFN 激活函数:SwiGLU 代替 ReLU
  • attention 中除 QKV 外无 bias,并采用 Flash Attention 加速训练

5.1. 参考