Spring把「手动」的复杂裹成了「自动」的温柔
竞墩促儆主流开源大模型架构对比报告一、主流开源大模型 对比目前开源大模型比较经典的有国外LLaMA、BLOOM、Falcon、Mixtral、T5国内Qwen、DeepSeek、ChatGLM、模型核心架构注意力机制位置编码归一化层激活函数关键创新/特点LLaMA (3)Decoder-onlyGQA (分组查询)RoPERMSNormSwiGLU现代高效 Decoder 架构的事实标准BLOOMDecoder-onlyMHA (标准多头)ALiBiLayerNormGELU纯粹的多语言设计ALiBi 位置编码FalconDecoder-onlyMQA (多查询) / GQARoPERMSNormGeLUMQA 提升推理效率并行注意力MixtralMoE (专家混合)GQARoPERMSNormSwiGLU开源 MoE 模型的标杆稀疏激活T5Encoder-DecoderMHA相对位置偏置LayerNormGeLUSeq2Seq 任务框架适用于翻译、摘要Qwen (通义千问)Decoder-onlyGQA / MHARoPERMSNormSwiGLU超大词汇表 (多语言)、长上下文支持DeepSeekMoE (专家混合)MHARoPERMSNormSwiGLU对标 Mixtral代码和推理能力突出ChatGLM (3)GLM (通用语言模型)GQA / MHARoPEDeepNormSwiGLU独特的 GLM 框架双向注意力二、大模型架构LLaMA(Large Language Model Meta AI)研发机构: Meta AI架构: LLaMA 系列模型采用了经典的 仅解码器Decoder-only的 Transformer 架构。Llama 3.1架构是经过高度优化的实现包含了当前业界公认的高性能组件 RMSNorm SwiGLU RoPE GQA? 归一化 采用前置归一化Pre-normalization并使用RMSNorm来保证训练过程的稳定性。? 激活函数使用SwiGLU激活函数相较于标准的ReLU它能提供更好的性能表现。? 位置编码采用旋转位置编码Rotary Positional Embeddings, RoPE来为序列中的token注入位置信息。? 注意力机制在所有尺寸的模型8B、70B和405B中均采用了分组查询注意力Grouped-Query Attention, GQA。GQA通过让多组查询头Query heads共享同一份键Key和值Value头显著减少了推理过程中键值缓存KV cache的内存占用这是实现模型可扩展性尤其是在处理长序列时的一项关键优化。相关论文:? LLaMA: “LLaMA: Open and Efficient Foundation Language Models”https://arxiv.org/abs/2302.13971image图 LLaMA-3 模型结构三、细节结构解释1. 核心结构Decoder-only (解码器架构)这是当前主流生成式 LLM 的选择包括 LLaMA、BLOOM、Falcon、Qwen、Kimi。这种架构非常适合自回归的文本生成任务如对话、写作、问答等。模型根据已经生成的文本预测下一个词。Encoder-Decoder (编码器-解码器架构)T5 是该架构的典型代表。它拥有一个完整的编码器来理解输入文本源序列和一个解码器来生成输出文本目标序列。这种结构天然适用于序列到序列 (Seq2Seq) 任务如机器翻译、文本摘要、问题生成等。MoE (Mixture-of-Experts / 专家混合架构)Mixtral、DeepSeek、悟道 采用了这种高效扩展架构。其核心思想是模型包含大量“专家”即前馈网络但在处理每个 token 时只通过一个“路由器”动态选择激活一小部分专家。优势: 可以在保持计算量FLOPs相对稳定的情况下将模型总参数量扩展到极大万亿级别从而增强模型的容量和知识储备。这是实现“大而快”的关键。GLM (General Language Model / 通用语言模型)ChatGLM 采用的独特架构。它通过自回归填空的目标进行预训练并采用特殊的注意力掩码使其能够同时处理双向和单向的上下文信息。这使得它在理解NLU和生成NLG任务上都有较好的表现。Transformer目前大模型的基本架构是基于Transformer的。image图 transformer架构MoE 专家混合模型MoE 并不是一个特定的模型而是一种架构范式 (Architectural Paradigm)。它的核心思想是通过条件计算 (Conditional Computation) 来扩大模型规模而不是简单地增加模型密度。想象一下你不需要在解决每个问题时都动用整个大脑而是根据问题的类型只激活大脑中特定领域的专家区域。这就是 MoE 的直觉。核心思想稀疏激活 (Sparse Activation)在一个稠密模型Dense Model中对于任何输入所有参数都会被激活和使用。而在 MoE 模型中输入 token 只会被路由到一小部分“专家”Experts那里进行处理。专家网络 (Experts)每个专家通常是一个独立的前馈神经网络 (FFN)。一个 MoE 层包含多个这样的专家。门控网络/路由器 (Gating Network / Router)这是一个小型的神经网络它的作用是“决策者”。它接收输入的 token然后决定应该将这个 token 发送给哪些专家处理。它会为每个专家生成一个权重通常只选择权重最高的 Top-k 个专家k 通常是 1 或 2。组合输出各个被激活的专家的输出会根据门控网络给出的权重进行加权求和形成最终的输出。MoE 的优势巨大的参数规模可以在不显著增加计算成本FLOPs的情况下将模型的总参数量扩展到数万亿级别。因为每次前向传播只使用了总参数的一小部分。训练和推理更快对于给定的参数总量MoE 模型的计算量远小于同等规模的稠密模型。例如一个 1.8T 参数的 MoE 模型如 Mixtral 8x7B其每次前向传播的计算量只相当于一个 14B 的稠密模型因为每个 token 只激活 2 个 7B 的专家。专业化不同的专家可以在训练过程中学会处理不同类型的数据或模式实现某种程度的专业化。MoE 的挑战训练不稳定门控网络的决策可能导致负载不均衡某些专家被过度使用某些专家几乎不用需要引入额外的损失函数如 Load Balancing Loss来鼓励均匀分配。通信开销大在分布式训练中不同专家可能位于不同的 GPU 上token 在专家之间的路由会引入显著的通信延迟。推理复杂需要更多的 VRAM 来容纳所有专家参数即使每次只使用一小部分。这使得模型部署变得困难。imageGLM参考资料 :复制的 DataWhale happyllm项目 chapter3 https://github.com/datawhalechina/happy-llm/blob/main/docs/chapter3/%E7%AC%AC%E4%B8%89%E7%AB%A0%20%E9%A2%84%E8%AE%AD%E7%BB%83%E8%AF%AD%E8%A8%80%E6%A8%A1%E5%9E%8B.md#333-glmGLM 最初是由清华计算机系推出的一种通用语言模型基座其核心思路是在传统 CLM 预训练任务基础上加入 MLM 思想从而构建一个在 NLG 和 NLU 任务上都具有良好表现的统一模型。在整体模型结构上GLM 和 GPT 大致类似均是 Decoder-Only 的结构仅有三点细微差异使用 Post Norm 而非 Pre Norm。Post Norm 是指在进行残差连接计算时先完成残差计算再进行 LayerNorm 计算而类似于 GPT、LLaMA 等模型都使用了 Pre Norm也就是先进行 LayerNorm 计算再进行残差的计算。相对而言Post Norm 由于在残差之后做归一化对参数正则化的效果更强进而模型的鲁棒性也会更好Pre Norm相对于因为有一部分参数直接加在了后面不需要对这部分参数进行正则化正好可以防止模型的梯度爆炸或者梯度消失。因此对于更大体量的模型来说一般认为 Pre Norm 效果会更好。但 GLM 论文提出使用 Post Norm 可以避免 LLM 的数值错误虽然主流 LLM 仍然使用了 Pre Norm使用单个线性层实现最终 token 的预测而不是使用 MLP这样的结构更加简单也更加鲁棒即减少了最终输出的参数量将更大的参数量放在了模型本身激活函数从 ReLU 换成了 GeLUs。ReLU 是传统的激活函数其核心计算逻辑为去除小于 0的传播保留大于 0的传播GeLUs 核心是对接近于 0的正向传播做了一个非线性映射保证了激活函数后的非线性输出具有一定的连续性。2预训练任务-GLMGLM 的核心创新点主要在于其提出的 GLMGeneral Language Model通用语言模型任务这也是 GLM 的名字由来。GLM 是一种结合了自编码思想和自回归思想的预训练方法。所谓自编码思想其实也就是 MLM 的任务学习思路在输入文本中随机删除连续的 tokens要求模型学习被删除的 tokens所谓自回归思想其实就是传统的 CLM 任务学习思路也就是要求模型按顺序重建连续 tokens。GLM 通过优化一个自回归空白填充任务来实现 MLM 与 CLM 思想的结合。其核心思想是对于一个输入序列会类似于 MLM 一样进行随机的掩码但遮蔽的不是和 MLM 一样的单个 token而是每次遮蔽一连串 token模型在学习时既需要使用遮蔽部分的上下文预测遮蔽部分在遮蔽部分内部又需要以 CLM 的方式完成被遮蔽的 tokens 的预测。例如输入和输出可能是Plain Text输入Ibecause you输出- love you;- are a wonderful person通过将 MLM 与 CLM 思想相结合既适配逐个 token 生成的生成类任务也迫使模型从前后两个方向学习输入文本的隐含关系从而适配了理解类任务。不过GLM 预训练任务更多的优势还是展现在预训练模型时代迈入 LLM 时代后针对于超大规模、体量的预训练CLM 展现出远超 MLM 的优势。通过将模型体量加大、预训练规模扩大CLM 预训练得到的生成模型在文本理解上也能具有超出 MLM 训练的理解模型的能力因此ChatGLM 系列模型也仅在第一代模型使用了 GLM 的预训练思想从 ChatGLM2 开始还是回归了传统的 CLM 建模。虽然从 LLM 的整体发展路径来看GLM 预训练任务似乎是一个失败的尝试但通过精巧的设计将 CLM 与 MLM 融合并第一时间产出了中文开源的原生 LLM其思路仍然存在较大的借鉴意义。imageimage2. 归一化层LayerNorm: 经典归一化层BLOOM、T5 使用。RMSNorm: LLaMA、Falcon、Mixtral、Qwen、DeepSeek 等现代模型的标配。它简化了 LayerNorm移除了均值中心化步骤计算更快。DeepNorm: ChatGLM 使用的一种更复杂的归一化技术旨在让极深层网络的训练更加稳定。位置: 所有现代模型都采用了预归一化 (Pre-Normalization)即在每个子模块注意力和FFN的输入端进行归一化这已成为稳定训练的标准实践。image如何选择LayerNorm是一个非常安全和稳健的选择适用于绝大多数 Transformer 和其他需要样本内归一化的场景。RMSNorm如果你追求极致的训练和推理速度并且实验证明在你的任务上性能与 LayerNorm 无异那么 RMSNorm 是一个绝佳的替代品。现代很多大模型如 Llama 系列已经默认使用 RMSNorm。DeepNorm只有当你需要训练非常非常深例如几百上千层的模型时才需要考虑。对于常规深度例如 12-48 层的 Transformer标准的 Post-LN 或 Pre-LN 结构通常已经足够稳定。LayerNorm对单个样本或 token的所有特征进行归一化。LayerNorm 是为了解决 Batch Normalization (BN) 在循环神经网络 (RNN) 和小批量 (small batch size) 场景下的不足而提出的。与 BN 在批次维度上进行归一化不同LayerNorm 在单个样本的特征维度上进行归一化。核心思想对于每一个样本独立地计算其所有特征的均值和方差然后用这些统计量来归一化该样本的特征。这种方式有两个主要优点独立于批次大小每个样本独立计算即使批次大小为 1 也能正常工作。适用于序列数据对于变长的序列数据如文本可以在每个时间步上对特征向量进行归一化非常方便。imagePythonimport torchimport torch.nn as nnclass LayerNorm(nn.Module):def __init__(self, normalized_shape, eps1e-5):super().__init__()# 如果 normalized_shape 是整数则将其转换为元组if isinstance(normalized_shape, int):normalized_shape (normalized_shape,)self.normalized_shape normalized_shapeself.eps eps# 可学习的增益 gamma 和偏置 betaself.gamma nn.Parameter(torch.ones(self.normalized_shape))self.beta nn.Parameter(torch.zeros(self.normalized_shape))def forward(self, x):# 计算需要归一化的维度的均值和方差# keepdimTrue 保持维度以便进行广播计算mean x.mean(dim-1, keepdimTrue)var x.var(dim-1, unbiasedFalse, keepdimTrue)# 归一化x_normalized (x - mean) / torch.sqrt(var self.eps)# 缩放和平移output self.gamma * x_normalized self.betareturn output# 使用示例# 假设我们有一个批次为 4序列长度为 10特征维度为 20 的张量x torch.randn(4, 10, 20)ln LayerNorm(normalized_shape20)output ln(x)print(自定义 LayerNorm 输出尺寸:, output.shape)# 对比 PyTorch 内置的 LayerNormpytorch_ln nn.LayerNorm(normalized_shape20)pytorch_output pytorch_ln(x)print(PyTorch LayerNorm 输出尺寸:, pytorch_output.shape)RMSNormRMSNorm (Root Mean Square Layer Normalization) 是对 LayerNorm 的一种简化旨在减少计算开销。研究者发现LayerNorm 中的均值中心化减去均值 μ对性能的贡献不大但却占用了相当一部分计算量。核心思想移除均值中心化步骤只通过均方根 (Root Mean Square) 来对神经元的激活值进行缩放。这种简化的主要优点是计算效率更高在 GPU 上RMSNorm比 LayerNorm 快 7% 到 64% 不等。性能相当在多种任务上RMSNorm 的性能与 LayerNorm 相当。imageimageg是可学习参数Pythonimport torchimport torch.nn as nnclass RMSNorm(nn.Module):def __init__(self, dim, eps1e-6):super().__init__()self.eps eps# 增益参数 gammaself.gamma nn.Parameter(torch.ones(dim))def _norm(self, x):# 计算输入的均方根# rsqrt 是平方根倒数的快速计算return x * torch.rsqrt(x.pow(2).mean(-1, keepdimTrue) self.eps)def forward(self, x):# 归一化并应用增益return self._norm(x) * self.gamma# 使用示例# 假设我们有一个批次为 4序列长度为 10特征维度为 20 的张量x torch.randn(4, 10, 20)rms_norm RMSNorm(dim20)output rms_norm(x)print(RMSNorm 输出尺寸:, output.shape)优势更快的计算,RMSNorm 只计算平方和计算量减少数值稳定性LayerNorm 计算 μ 时可能出现小数精度问题而 RMSNorm 不涉及均值计算数值更稳定。避免均值归一化导致的梯度消失问题。适用于 Transformer在 GPT、Llama、Gemma 这类 超大规模 Transformer 语言模型 中RMSNorm 的高效计算可以显著减少训练时间。Google DeepMind 研究表明RMSNorm 可以替代 LayerNorm 而不损失性能特别是在 低精度训练FP16, BF16 场景下。DeepNormDeepNorm 并不是像 LayerNorm 或 RMSNorm 那样的一种具体的“归一化层”而是一种用于稳定极深 Transformer 模型训练的理论和方法。它通过结合特定的权重初始化和对残差连接的理论分析使得训练超过 1000 层的 Transformer 成为可能。DeepNorm 通常与 LayerNorm 结合使用。核心思想通过理论推导DeepNorm 认为模型训练不稳定的根源在于梯度消失或爆炸这与模型参数的初始化以及残差连接中的数值范围有很大关系。DeepNorm 的目标是限制模型前向传播和反向传播中数值的剧烈变化。它主要包含两个部分理论指导的初始化 对于 Transformer 的某些权重矩阵例如 FFN 的第二层线性层和注意力机制的输出投影层使用一个比标准初始化小得多的值进行初始化。修改残差连接 在标准的 x Sublayer(x) 残差连接中DeepNorm 引入一个常数缩放因子 αimage数学公式/伪代码在一个标准的 Transformer 块中残差连接的形式如下Plain Text# 标准 Transformerx x attention(LayerNorm(x))x x ffn(LayerNorm(x))使用 DeepNorm 后这个结构会变成Plain Text# 使用 DeepNorm 的 Transformerx LayerNorm(x \alpha * attention(x)) # 注意LayerNorm 放在了残差连接之后x LayerNorm(x \alpha * ffn(x))其中 α 是一个关键的超参数它的值由模型的深度 N编码器或解码器层数决定通常设置为 (2N)**1/4 或类似的值以保证数值范围的稳定。同时FFN 和 Attention 中的某些权重矩阵需要被初始化为一个较小的值例如用 c?N**?1/4 这样的因子进行缩放其中 c 是一个小的常数。DeepNorm 的实现不是一个独立的 nn.Module而是对 Transformer Block 结构的修改。Pythonimport torchimport torch.nn as nn# 这是一个概念性实现展示 DeepNorm 如何修改 Transformer 块class DeepNormTransformerBlock(nn.Module):def __init__(self, dim, num_layers, ffn_expansion_factor4):super().__init__()self.dim dimself.num_layers num_layers# 定义 alpha这是 DeepNorm 的核心self.alpha (2 * self.num_layers) ** 0.25self.norm1 nn.LayerNorm(dim)self.attn nn.MultiheadAttention(dim, heads8) # 示例self.norm2 nn.LayerNorm(dim)self.ffn nn.Sequential(nn.Linear(dim, dim * ffn_expansion_factor),nn.ReLU(),nn.Linear(dim * ffn_expansion_factor, dim))# DeepNorm 特定的初始化self.init_weights()def init_weights(self):# 论文中建议对 FFN 的第二层和 Attention 的输出层进行特殊初始化# 这里仅为示意具体初始化策略需参考原论文for name, param in self.ffn.named_parameters():if weight in name and 1.weight in name: # 第二个线性层nn.init.xavier_normal_(param, gain0.1) # 示意性的较小初始化for name, param in self.attn.named_parameters():if out_proj.weight in name:nn.init.xavier_normal_(param, gain0.1)def forward(self, x):# 残差连接的修改# 注意 LayerNorm 的位置和 alpha 的使用attn_output, _ self.attn(x, x, x)x self.norm1(x self.alpha * attn_output)ffn_output self.ffn(x)x self.norm2(x self.alpha * ffn_output)return x3. 位置编码imageRoPE 已成为当前大模型架构的黄金标准因为它在性能和外推能力上取得了最佳的平衡。ALiBi 是一个非常优雅且高效的替代方案它的简单性和强大的外推能力使其在特定场景下极具吸引力。相对位置偏置 是一个经典且有效的方法但其外推能力弱的缺点使其在需要处理超长文本的现代大模型中逐渐被 RoPE 和 ALiBi 取代。RoPE 旋转位置编码通过绝对位置来编码相对位置关系。 RoPE 的精妙之处在于它将位置信息融入到注意力计算中的 Query (查询) 和 Key (键) 向量中。它通过对 Q 和 K 向量进行“旋转”操作使得两个 token 的 Q 和 K 经过旋转后的内积即注意力分数只与它们的相对位置有关而与它们的绝对位置无关。1. 工作原理想象一个二维平面上的向量 v (x, y)。如果将它旋转 θ 角度会得到一个新的向量。RoPE 将高维的词向量两两配对看作是一系列的二维向量或者说复数然后根据其绝对位置 m 旋转一个特定的角度 mθ。位置为 m 的 token 的 Query 向量 q_m 会被旋转 mθ。位置为 n 的 token 的 Key 向量 k_n 会被旋转 nθ。当计算它们的注意力分数时即计算 (R_m * q_m) 和 (R_n * k_n) 的点积数学上可以证明这个结果等于原始向量 q_m 和 k_n 与一个只依赖于相对位置 (m-n) 的旋转矩阵 R_{m-n} 的运算结果。这样模型就自然地捕捉到了相对位置信息。原理解释 假设 q_m 和 k_n 是位置 m 和 n 的向量。RoPE 将它们乘以一个旋转矩阵 Rimage其中旋转矩阵 R_m 定义为image这里的 θ_i 10000^{-2i/d} 是预设的、不同维度上的旋转“角速度”d 是向量维度。关键在于内积注意力分数变为image这个结果只依赖于相对距离 n-m。2. 更详细的原理流程解释第一步 计算基础角速度 θ_iRoPE 的设计者不希望所有维度都以相同的速度旋转。他们希望低频部分 (low-frequency)对应向量的前几个维度旋转得慢波长长用于捕捉长距离的相对位置关系。高频部分 (high-frequency)对应向量的后几个维度旋转得快波长短用于捕捉短距离、精细的相对位置关系。为了实现这一点他们使用了一个几何级数 (geometric progression) 来生成这些角速度。对于一个维度为 d 的向量我们有 d/2 个角速度 θ_i其中 i 从 0 到 d/2 - 1。公式如下image。i维度对的索引i ∈ [0, 1, 2, ..., (d/2 - 1)]。b一个预设的基数 (base)通常是一个很大的数比如 10000。这个基数 b 控制了旋转波长的范围。第二步结合绝对位置 m现在我们有了基础速度 θ_i对于一个在序列中绝对位置为 m 的 token其在第 i 个二维平面上的最终旋转角度就是image这就像物理学中的 角位移 角速度 × 时间。这里m 扮演了“时间”的角色。第三步构建旋转矩阵 R_m有了每个维度对在特定位置 m 的最终旋转角度 mθ_i我们就可以构建完整的旋转矩阵 R_m 了。R_m 是一个 d x d 的块对角矩阵 (block-diagonal matrix)。这意味着它的大部分元素都是 0只有对角线上一系列 2x2 的小矩阵块有值。每个 2x2 的块负责旋转一对维度。对于第 i 个维度对即向量的第 2i 和 2i1 维其对应的 2x2 旋转矩阵是标准的二维旋转矩阵image