Table 1:模型规格与训练超参数
| 参数量 | Hidden size | 注意力头数 | 层数 | 学习率 | Batch size | 训练 Token 数 |
|---|---|---|---|---|---|---|
| 1.8 B | 2048 | 16 | 24 | 3.0 × 10⁻⁴ | 4 M | 2.2 T |
| 7 B | 4096 | 32 | 32 | 3.0 × 10⁻⁴ | 4 M | 2.4 T |
| 14 B | 5120 | 40 | 40 | 3.0 × 10⁻⁴ | 4 M | 3.0 T |
💡 三个版本学习率和 Batch size 完全一致,仅靠增大模型宽度(Hidden size)和深度(Layers)来 scale up;14B 是 over-training 版本,token 数最多。
BPE Tokenizer(Section 2.2)
Tokenizer4what
Tokenizer 的任务是把一段文本切成一个个 token(模型实际处理的最小单位)。切法不同,同一段话产生的 token 数就不同。
BPE = Byte Pair Encoding,Qwen 使用的分词算法,基于 tiktoken 库实现(与 GPT-4 同款框架)。
核心思路
从「单个字节」出发,反复合并出现频率最高的相邻字节对,直到词表达到目标大小。
初始:每个字符/字节单独一个 token
迭代:统计所有相邻 pair 的频率 → 合并频率最高的 pair → 加入词表
直到词表大小达到预设值(Qwen: 151,851)Qwen Tokenizer 的关键设计
-
词表大小:151,851(远大于 LLaMA 的 32,000,GPT-3 的 50,257)
-
数字单独成 token:每个数字 0–9 独立编码,有利于数学和代码任务
-
空格不合并:参考 GPT-4 处理方式,避免歧义
-
多语言覆盖:词表中显式加入中文、日文、韩文、阿拉伯文等高频字符,不依赖字节回退
为什么词表大 → 压缩比低(更高效)?
词表越大 → 能合并的「字节对」组合越多 → 常见词/字直接映射为单个 token
Important
对中文来说:LLaMA 词表小,很多汉字要拆成 2–3 个 UTF-8 字节 token;Qwen 词表大,大多数汉字直接一个 token 搞定 → 这就是压缩比图里 Qwen 最低的原因。
与其他 Tokenizer 的对比
| 模型 | Tokenizer | 词表大小 | 中文处理 |
|---|---|---|---|
| Qwen | BPE (tiktoken) | 151,851 | 汉字直接入词表 |
| LLaMA | BPE (SentencePiece) | 32,000 | 字节回退,效率低 |
| GPT-4 | BPE (tiktoken) | ~100,000 | 较好 |
| ChatGLM2 | SentencePiece | 64,789 | 中文优化 |
Pre-RMSNorm 归一化
为什么需要归一化?
Transformer 每一层做完 Attention / FFN 后,输出的数值分布会漂移——均值偏移、方差膨胀。根源在于激活函数破坏了正负对称性(如 ReLU 把负值砍为 0,SiLU/GELU 大幅压缩负值),导致每层输出分布不再均衡,层数一多漂移不断累积。
归一化的本质:每一层都把数值分布拽回稳定区间,让后续层永远看到”干净”的输入。
LayerNorm vs RMSNorm
LayerNorm(标准形式):
-
减均值(centering)+ 除标准差 + 可学习的缩放 和偏置
-
这一步把分布拉到均值 0、方差 1;后面的 让模型自己决定最终分布
RMSNorm(Qwen 使用):
-
去掉了减均值和偏置 ,只保留缩放
-
分母用 RMS(均方根)代替标准差
-
原论文(Zhang & Sennrich, 2019)发现:归一化起作用的主要原因是缩放不变性(归一向量”长度”),不是均值平移。去掉 centering 对效果几乎无影响,但计算更快、参数更少
| LayerNorm | RMSNorm | |
|---|---|---|
| 减均值 | ✅ | ❌ |
| 除以标准差/RMS | ✅ | ✅ RMS |
| 可学习偏置 | ✅ | ❌ |
| 可学习缩放 | ✅ | ✅ |
Pre-Norm vs Post-Norm(归一化放在哪里)
Post-Norm(原始 Transformer):
x → Attention → Add(x) → Norm → FFN → Add → NormPre-Norm(Qwen 使用):
x → Norm → Attention → Add(x) → Norm → FFN → Add(x)关键区别:Pre-Norm 中残差路径完全畅通,梯度可以不经过任何 Norm 直接从最后一层回传到第一层,训练更稳定。Post-Norm 的残差路径上叠了 Norm,梯度要穿过多层 Norm,深层模型容易训崩。
Important
Qwen 的选择:Pre-Norm + RMSNorm。 归一化放在子层前面 + 用更轻量的 RMSNorm 代替 LayerNorm。效果几乎一样,但训练更稳、计算更快。这也是当前大模型的标配组合(LLaMA、Mistral 等同样采用)。
RoPE 位置编码与 FP32 精度经验点
Qwen 使用 RoPE(Rotary Position Embedding) 作为位置编码方案。其中一个关键工程细节:逆频率矩阵(inverse frequency matrix)必须用 FP32 精度计算和存储。
逆频率是什么?
RoPE 的核心是给每个维度分配一个旋转频率:
这组 就是 inverse frequency(逆频率)。实际代码中会一次性算好存成一个向量。
为什么必须用 FP32?
-
高维度时 的值会变得极小(如 )
-
BF16 只有 7 位尾数,FP16 有 10 位尾数,对这些小值的精度都不够
-
位置编码精度一旦损失 → 模型对长距离位置关系的感知出错 → 长文本能力受损
Important
经验点: 即使模型整体用 BF16/FP16 训练,RoPE 的逆频率向量也要单独用 FP32 保精度。这是一个容易被忽略但影响显著的工程细节。BF16 虽然数值范围与 FP32 一致(都是 8 位指数),但 7 位尾数对于位置编码中的小数值来说精度不足。
长上下文推理技术消融实验(Table 3)
通过逐步叠加三种技术(dynamic NTK + logn scaling + window attention),模型在超出训练长度时的困惑度(perplexity)大幅下降,说明这些技术对长文本理解和生成能力至关重要。
| Model | 1024 | 2048 | 4096 | 8192 | 16384 |
|---|---|---|---|---|---|
| Qwen-7B | 4.23 | 3.78 | 39.35 | 469.81 | 2645.09 |
| • dynamic_ntk | 4.23 | 3.78 | 3.59 | 3.66 | 5.71 |
| • dynamic_ntk + logn | 4.23 | 3.78 | 3.58 | 3.56 | 4.62 |
| • dynamic_ntk + logn + window_attn | 4.23 | 3.78 | 3.58 | 3.49 | 4.32 |
| Qwen-14B | - | 3.46 | 22.79 | 334.65 | 3168.35 |
| • dynamic_ntk + logn + window_attn | - | 3.46 | 3.29 | 3.18 | 3.42 |
Important
解读: 裸模型(无任何技术)在超过训练长度(2048)后 perplexity 爆炸(Qwen-7B: 39→69→2645)。加上 dynamic NTK 后短序列不受影响,长序列大幅修复。logn scaling 和 window attention 进一步压低了 16K 长度下的 perplexity,最终 7B 模型在 16K 长度下从 2645 降到 4.32。
RLHF / PPO 后训练
四个模型的分工
| 模型 | 初始化来源 | 参数状态 | 作用 |
|---|---|---|---|
| Policy Model | SFT 模型 | 🔓 可训练 | 生成回答,接受 PPO 更新 |
| Value Model | Reward Model | 🔓 可训练 | 估计基准值 V(s),用于算 Advantage |
| Reference Model | SFT 模型 | 🧳 冻结 | 计算 KL 散度,防止 Policy 跑偏 |
| Reward Model | 预训练好的 RM | 🧳 冻结 | 给回答打分,提供奖励信号 |
PPO 训练的关键工程细节
-
Value Model 预热 50 步:正式 PPO 开始前,先单独训 Value Model 50 步,让它学会大致靠谱的基准估计。否则初始 Advantage 全是噪声,Policy 会被误导。
-
每个 prompt 采样 2 个回答:提供更丰富的对比信号,让 Advantage 估计更准确。
-
top-p < 1.0 采样:砸掉尾部低概率 token,让生成质量更稳定,奖励信号噪声更小。
Alignment Tax(对齐税)与 Pretrained Gradient
对齐税:RLHF 让模型更“听话”,但通用能力(数学、代码等 benchmark 分数)可能下降。本质是 PPO 梯度全往“对齐”方向推,导致模型“忘掉”预训练时学到的通用知识(灾难性遗忘)。
缓解策略: Qwen 在 PPO 训练时同时混入预训练数据,用语言建模损失产生的梯度(pretrained gradient)来拽住通用能力:
每步梯度 = PPO 梯度(对齐方向)+ λ × 预训练梯度(保通用能力)Important
关键经验点:
对于常识、阅读理解等“软”能力,光靠 KL 惩罚就能基本保住,不太需要预训练梯度
对于代码、数学等“硬”能力,KL 不够,必须加预训练梯度
预训练数据量要远大于 PPO 数据,否则拽不住
系数 λ 太大 → 压过 PPO 梯度,对齐效果变差;太小 → 拽不住通用能力,对齐税仍然很高
预训练数据处理流程(Section 2.1)
数据规模:最终构建了 3 trillion tokens 的数据集,覆盖网页、百科、书籍、代码等,中英文为主。
整体流程
原始网页爬取
↓ HTML 解析 + 语言识别
↓ 精确去重(归一化 + 完全匹配)
↓ 模糊去重(MinHash + LSH)
↓ 质量过滤(规则 + LM 打分 + 人工抽查)
↓ 有害内容过滤
↓ 高质量来源上采样
↓ 混入指令数据
↓ 13-gram 测试集污染过滤
↓
最终:~3T tokens 预训练语料
SFT Loss Masking(Section 3.1 & 5.1)
SFT 训练时,一次 forward 把整个序列 [system][user][assistant] 所有位置的 next token prediction 都算出来(teacher forcing + causal mask 保证每个位置只看到自己和前面的 token),但在算 loss 时 只对 assistant 部分的 token 计算 cross-entropy,system 和 user 部分的 loss 权重设为 0。
logits = model(input_ids) # 所有 token 都过 forward
loss = cross_entropy(logits, labels)
# mask 掉 system + user 的 token
loss_mask = torch.zeros_like(loss)
loss_mask[assistant_token_positions] = 1.0
loss = (loss * loss_mask).sum() / loss_mask.sum()梯度只从 assistant 回答部分回传,模型不会浪费 capacity 去学”预测题目里的随机数字”。
Important
数学场景效果尤其明显: Math-Qwen 的 user input 基本都是考试题,数字和条件是随机的,预测它们毫无意义。论文实验证明 mask 掉 user input 的 loss 后收敛更快。这在通用 SFT 中也是标准做法。
Code-Qwen vs Math-Qwen:两条不同的专精路径(Section 4 & 5)
| Code-Qwen | Math-Qwen | |
|---|---|---|
| 路径 | base → continue pretrain(90B code tokens) → multi-stage SFT | base → 直接 math SFT(无 continue pretrain) |
| 为什么 | 代码需要大量领域知识(语法、API、库),base 模型预训练时代码占比不够,必须补 | 数学更依赖 reasoning pattern 而非领域知识量,SFT 就能激活推理能力 |
| Context length | 8192(代码/tool use 场景需要长上下文) | 1024(数学数据平均长度短,省算力) |
| 学习率 | 14B: 2e-6 / 7B: 1e-5 | 2e-5(比通用 SFT 大 10 倍) |
Important
启发: 是否需要 continue pretrain 取决于「目标领域的知识密度」。代码是知识密集型(海量 API/语法),pretrain 补知识;数学是推理密集型,SFT 调 pattern 就够。
Reward Model 的 PMP(Preference Model Pretraining)(Section 3.2.1)
Reward Model 不是直接在人工标注数据上从零训的,而是分两步走,跟 LLM 的 pretrain → SFT 思路完全对称:
-
PMP(Preference Model Pretraining):在大规模但质量一般的比较数据上预训练 RM,让它先学会”什么是好回答”的粗粒度判断
-
RM Finetuning:在高质量人工标注的比较数据上精调,提升判断精度
RM 训练中的数据工程
-
Prompt 多样性保障:建立了约 6600 个细粒度标签 的分类体系,用平衡采样算法同时考虑多样性和复杂度
-
Response 多样性:用不同大小的 Qwen 模型 + 不同采样策略生成回答,多样的回答降低标注难度、提升 RM 质量
-
架构:在 Qwen base 模型基础上加一个 pooling 层,从特定 end token 提取整句的 reward 标量
Important
PMP 的价值: Table 4 显示 PMP 模型在 OOD 数据集(Anthropic、OpenAI、Stanford)上泛化能力很强,说明大规模预训练确实帮 RM 学到了通用的偏好判断能力,而不仅仅是拟合特定标注数据。
-
📚 各步骤详细说明
1. 数据来源 & 提取
-
公开网页数据:从 HTML 中提取文本,用语言识别工具判断语种
-
多样化来源:网页文档、Wiki、书籍、代码等
2. 去重(Deduplication)
两层去重,缺一不可:
-
精确去重(Exact-match):文本归一化后做完全匹配,删除重复条目
-
模糊去重(Fuzzy):用 MinHash + LSH 找近似重复(如同一新闻被多站转载)
💡 MinHash 把文本压成”指纹”,LSH 让相似指纹聚在一起,避免 暴力比较,把复杂度降到接近 。
3. 质量过滤
规则 + 模型两种方式结合:
-
语言模型(LM)打分:用语言模型评估文本是否自然流畅
-
文本质量打分模型:专门训练的质量评估器
-
有害内容过滤模型:识别并剔除色情、暴力等不良内容
-
人工抽查:对各来源随机采样,人工审核保底
4. 上采样(Up-sampling)
对高质量来源(如学术论文、维基百科)选择性地多复制几份放入训练集,提升数据多样性和质量分布。
本质:用训练频率补偿数据量的稀缺,和处理类别不平衡问题的上采样逻辑一致。
5. 混入指令数据(Multi-task Instructions)
参考 Zeng et al. (2022)、FLAN 等工作的做法,在预训练数据中混入高质量指令数据,增强模型的 zero-shot / few-shot 泛化能力。
效果:让模型在预训练阶段就接触任务格式,SFT 阶段收敛更快,零样本能力更强。
6. 测试集污染过滤(Contamination Filtering)
参考 GPT-3(Brown et al., 2020)的方法:
-
用 13-gram overlap 检测训练数据与 benchmark 测试集的重叠
-
凡有重叠的指令数据全部删除,防止模型”背答卷”
-
由于下游任务数量庞大,仅对已报告的 benchmark 做了此过滤
-