LLM 学习笔记——大模型的训练流程
这份笔记关注大模型是怎样训练和部署出来的。
这里我们以 decoder-only 自回归语言模型 为主,也就是 GPT、LLaMA、Qwen 这一类的主流路线,描述一个典型现代大语言模型的训练周期。从随机初始化权重开始,到最终变成可聊天、可编程、可工具调用的模型。
训练过程大致分成两段:
- 预训练:让模型形成能力上限。
- 后训练与部署:让模型更像一个可用产品。
一个更详细的流程如下:
flowchart TD;
A[随机初始化]
B[分词器]
C[预训练(得到 Base Model)]
D[监督微调(SFT)]
E[偏好学习]
F[安全对齐]
G[专项能力训练]
H[评测 / 蒸馏 / 压缩 / 量化]
I[部署]
A --> B --> C --> D --> E --> F --> G --> H --> I
模型结构设计
在真正训练前,先要定下模型结构。
常见要素包括:
- 参数规模:7B、14B、32B、70B……
- 层数:例如 32 层、48 层、80 层
- hidden size:例如 4096、8192
- attention heads 数量
- 上下文长度:4k、32k、128k……
- 是否使用 MoE(Mixture of Experts),不使用 MoE 时称为 Dense 模型
- 激活函数、归一化方式、位置编码方式
这一步决定:
- 模型容量上限
- 训练显存需求
- 推理成本
- 长上下文能力上限
- 之后能否高效扩展
一个极简结构示意
1 | Token Embedding |
初始化权重
我们需要把模型里所有参数初始化为某种小随机数。
为什么初始化不能直接全部设为 0?如果所有权重都相同,那么
- 每个神经元的梯度相同
- 模型无法打破对称性
- 学不到有区别的表示
对各个参数都要随机初始化,例如:
- embedding 矩阵随机初始化
- attention 的 Q/K/V/O 权重随机初始化
- MLP 层权重随机初始化
常见的随机初始化方式:
- Xavier / Glorot
- Kaiming
- 正态分布小方差初始化
- 针对 Transformer 的专门缩放规则
分词器(Tokenizer)
分词器负责把原始文本切成 token,这是大模型处理数据的基本单位。不是简单按“词”切,而往往是 子词(subword)、字节或字符片段。之所以要分词,是因为神经网络只能处理数值张量,因此需要先把文本离散化为 token,再通过 embedding 层映射为浮点向量。
常见分词方法:
- BPE
- SentencePiece
- Unigram
- byte-level BPE
例如原始文本:
1 | User: Write a Python function for quicksort. |
分词后可能变成:
1 | ["User", ":", " Write", " a", " Python", " function", " for", " quick", "sort", "."] |
再映射成整数 id:
1 | [6312, 25, 4512, 264, 13325, 734, 369, 9121, 4503, 13] |
分词器会影响:
- 词表大小
- 序列长度
- 多语言效率
- 代码建模效果
- 稀有词表示能力
分词器训练使用的是大规模文本样本,但相比主模型训练要轻得多。典型情况例如:
- 训练语料采样:GB 到 TB 级文本中的一部分
- 词表:32k、50k、100k、150k 等
- 时间:几小时到几天
注意:
- 分词器不负责把 token id 转换为高维浮点向量(token vector),这是主模型 embedding 层(词嵌入层)的工作。
- 分词器训练通常不被视作大模型训练的一部分。
- 不同大模型的分词器不一样,但是对于同一家厂商,同一个模型的不同版本可能会使用相同的分词器。
预训练数据准备
收集、清洗、去重、过滤海量文本和代码数据。来源可能包括:
- 网页文本
- 书籍,论文
- 问答社区
- 文档
- 代码仓库
- 数学题
- 多语言语料
然后需要对原始数据做一系列处理:
- 去 HTML 噪声
- 去重
- 去模板垃圾内容
- 去低质量文本
- 去脏词/非法内容的一部分
- 文档切片
- 长短控制
- 语言识别
- 质量打分
很多时候,数据质量比结构微调更重要。垃圾数据会直接带来:
- 胡言乱语
- 重复模式
- 错误知识
- 风格污染
- 训练不稳定
预训练本质是在“模仿文本分布”,所以给预训练提供的海量数据分布几乎决定模型学到什么。
预训练需要的数据量通常极大,粗略量级:
- token 数:几十亿、几百亿、几千亿、上万亿 token
- 当前主流开源中,常见是 trillion-token 级别
例如:
- 小模型:几十 B token 到数百 B token
- 中大型模型:数百 B 到数 T token
如果把整个项目算上,预训练的数据准备的工程成本非常高,甚至接近训练本身。但如果只关注 GPU 算力消耗,主要还是后面的预训练。
预训练(Pretraining)
这是整个模型能力形成的主体阶段,目标是让大模型学会预测下一个 token。
例如输入:
1 | The capital of France is |
目标是预测:
1 | Paris |
更精确地说,模型在每个位置都预测下一个 token。
输入序列:
1 | [t1, t2, t3, t4] |
训练目标:
- 在位置 1 预测
(t_2) - 在位置 2 预测
(t_3) - 在位置 3 预测
(t_4) - …
损失函数一般是交叉熵:
$$ \mathcal{L} = - \sum_t \log P_\theta(x_t \mid x_{<t}) $$
预训练过程中也可能需要不断进行调整,例如调整学习率等。
例如提供一个训练样本:
1 | The capital of Japan is Tokyo. |
希望把模型训练成:
- 看到
The预测capital - 看到
The capital预测of - …
- 看到
The capital of Japan is预测Tokyo
为了正确预测后续 token,模型必须学会:
- 语法
- 语义
- 实体关系
- 世界知识
- 文风
- 推理模式
- 代码结构
- 数学表达模式
例如要预测:
1 | The derivative of sin(x) is |
它若要预测出 cos(x),就必须捕捉某些知识模式。
预训练步骤是算力黑洞,占全过程对 GPU 算力需求的 80% 以上。常见量级大约为:
- 参数:7B / 13B / 34B / 70B / 100B+
- token:几百 B 到数 T
- 训练设备:成百上千张 GPU/TPU
- 时间:数周到数月
预训练结束后得到的模型通常称为 Base Model。
预训练结束后得到的模型可以做到
- 续写文本
- 一定程度答题
- 一定程度写代码
- 有初步推理能力
但通常还不能很好做到
- 按指令回答
- 安全
- 对话稳定
- 风格固定
有时也可以选择在预训练的通用语料基础上,再加上特定领域的语料(医学、法律等),以强化在特定领域的能力。
预训练结束之后,直到部署之前的步骤都属于后训练。
换句话说,预训练之后的大模型只是“会续写”,经过 SFT 之后才更像“会执行任务”。
后训练(Post-training)
预训练结束之后,直到部署之前的步骤都属于后训练。它们更关心“行为方式”和“产品可用性”。
(1)监督微调(SFT)
监督微调是指使用指令-回答格式的数据,让模型学会“用户问,助手答”。
输入不是纯文本续写,而是结构化样本,例如
1 | User: ... |
或
1 | <system>... |
也可以是多轮对话。
SFT 的训练目标通常仍然是优化交叉熵损失,但只对 assistant 回复部分计入损失。
数据示例:
1 | Instruction: |
1 | Instruction: |
Base Model 经过 SFT 得到的模型通常称为 Instruct Model 或 Chat Model。
经过 SFT 之后,模型更像一个助手,主要变化包括:
- 学会遵循指令
- 学会问答格式
- 学会多轮对话格式
- 输出更稳定
- 更像一个助手
相比预训练,SFT 的数据规模会小很多。耗时和成本占比相对于预训练也非常小,很多时候可能只占总训练算力的几个百分点。
(2)偏好学习(Preference Learning)
SFT 后模型能回答,但回答未必最符合人类偏好。偏好学习负责教会模型“哪个答案更好”。
因为很多实际问题并没有唯一正确答案,但有明显更合适的答案。更好的答案通常具有:
- 更清晰
- 更完整
- 更安全
- 更少编造
- 更符合用户意图
常见方法包括:
- RLHF
- DPO
数据形式通常是:
1 | Prompt |
数据示例:
1 | Prompt: |
Instruct Model 经过偏好学习得到的模型通常称为 Aligned Model。
这一步的成本不在算力,而是数据和人工标注成本。
(3)安全对齐(Safety Alignment)
安全对齐有时会并入 SFT 或偏好学习,有时单独做。
这个环节专门训练模型在敏感、高风险请求下采取合适行为,例如:
- 拒答危险内容
- 不生成违法指导
- 避免明显有害建议
- 在医学/法律等高风险场景更加保守
若不做安全对齐,模型可能:
- 直接给出攻击步骤
- 生成危险操作指导
- 模仿仇恨/歧视文本
- 对高风险问题过度自信
预训练模型学到的是互联网上存在的分布,其中包含大量不该模仿的内容。
数据示例:
1 | User: |
或者医疗风险提示:
1 | User: |
(4)专项能力训练
这个环节就是让通用模型更像用户需要的定制产品,通常包括:
- 代码能力训练
- 数学能力训练
- 工具调用训练
- Agent 能力训练
评测、蒸馏、压缩与部署优化
还有一些较后阶段的环节:
- 蒸馏(Distillation):可选,但现在非常常见,通常发生在较后阶段。蒸馏就是用大模型当 teacher,生成高质量数据,训练更小的 student。
- 压缩、量化、部署优化:这不是让模型学能力,而是让它能跑,更适合线上服务。
训练流程小结
整个训练过程可以粗分成两部分:
- 预训练:
- 需要海量语料,耗费大量计算资源
- 决定模型大部分的能力上限
- Pretraining → capability
- 后训练:
- 包括监督微调、偏好学习、安全对齐、专项能力训练等
- 决定模型大部分行为方式和可用性
- Post-training → alignment
补充内容
训练 vs 推理
大语言模型开发的软件栈通常分为两个阶段:
- 训练阶段(Training) → 使用大量数据训练,不断调整大模型权重,最终形成模型权重数据
- 推理阶段(Inference) → 使用固定的大模型权重数据,对外提供服务,接收输入并输出
两者关注的问题不同,实际使用的工具也不同。
训练阶段的目标:从大量数据中训练模型,不断调整大模型的权重,最终训练完成,得到大模型权重数据。
训练阶段的主要流程如下:
1 | forward → loss → backward → optimizer step |
推理阶段的主要流程如下:
1 | 输入 token → Transformer forward → logits → sampling → next token |
然后循环往复,直到生成 EOS token 或者达到最大长度。
训练阶段的目标是优化权重,需求主要是分布式训练:
- 模型并行:将大模型拆分到多个 GPU。
- 通信效率:大量梯度同步(如 all-reduce)。
- 显存管理:需要存储 activation、gradient 和 optimizer 状态。
常见的开源训练工具包括:
- PyTorch:主流深度学习框架,提供 tensor 运算和自动求导。
- JAX:Google 生态框架,结合 XLA 编译器用于大规模训练。
- Megatron-LM:Transformer 训练框架,提供 tensor parallel 与 pipeline parallel。
- DeepSpeed:分布式训练优化库,核心技术是 ZeRO 显存优化。
推理阶段的目标非常简单明确:在已有模型权重数据的情况下,如何在服务端部署大模型,低延迟高并发地生成 token,从而对外提供大模型服务。
推理过程没有反向传播,不需要计算梯度,因此虽然训练阶段使用的工具框架也能运行大模型,但是效率非常低,需要为推理阶段设计专门的工具。
在接收到用户 prompt 对应的 tokens 之后,实际推理过程包括两个阶段:
- Prefill:将整段 prompt 对应的 tokens 输入模型,得到每个位置的 logits,只使用最后一个位置的 logits 进行 sampling,得到回答的第一个 token。
- Decode:输入一个 token,获得下一个 token,继续将其输入。循环直到 EOS token 或者达到最大长度。
我们需要引入推理阶段的一个重要概念——KV cache。合理且普遍采用的优化方法是用空间换时间:缓存之前所有 token 在每一层 attention 中产生的 K/V,达到加速计算的目的,代价则是 KV cache 的空间开销。
- 假设 prompt 只有一个 token 输入:
- 此时整个推理过程看起来像逐 token 的输入输出:输入一个 token,获得一个 token,再将其输入,获得下一个 token。
- 但实际上,前面出现的所有 token 都会参与到生成下一个 token 的计算中。
- 我们当然可以每次把它们全部重新输入计算,但这种做法开销太大。
- 因此通常采用 KV cache,把之前 token 在每一层 attention 中产生的 K/V 缓存起来。
- 同样,如果提供了一大段 prompt,虽然 Prefill 阶段只截取最后一个位置的 logits 来采样第一个回答 token,但 prompt 的信息实际上会以 KV cache 的形式保留在各层 attention 中,并影响后续每一个 token 的生成。
推理系统(LLM inference engine)的目标是高效运行,需求主要包括:
- KV cache 管理
- 显存管理
- batch 调度
- GPU kernel 优化,例如 FlashAttention
常见的开源推理工具包括:
- vLLM:高并发推理服务器,核心是 PagedAttention 和 KV cache 动态管理。
- Text Generation Inference:HuggingFace 官方推理服务,支持 streaming 和动态 batching。
- llama.cpp:轻量本地推理引擎,支持 CPU 或小 GPU 运行量化模型。
- TensorRT-LLM:NVIDIA GPU 推理框架,重点优化 GPU kernel 性能。
- Ollama:更偏向本地模型运行与管理工具,可以简单理解为对 llama.cpp 的封装,使得整个部署过程更加简单,因此对个人在本地尝试部署大模型非常友好。
模型规模与 GPU 需求
大模型的规模通常用参数数量(parameters)表示,常见单位是 B(Billion,十亿参数)。例如 7B 表示约 70 亿参数。
需要注意的是,参数规模只反映模型容量,并不能完全决定资源需求;模型架构(Dense / MoE)、上下文长度、量化方式等都会显著影响训练和部署成本。
常见大模型规模层级如下表:
| 规模级别 | 模型定位 | 示例 |
|---|---|---|
| 7B–14B | 小型开源模型 | Qwen2.5-7B |
| 32B | 中型 dense 模型 | Qwen2.5-32B |
| 70B | 主流 dense 大模型 | Qwen2-72B |
| 200B | 中型 MoE 模型 | DeepSeek-V2 / V2.5 (236B,激活21B) |
| 600B+ | 大型 MoE 模型 | DeepSeek-V3 / R1 (671B,激活37B) |
| 1T+ | 超大模型 | GPT-4 / Gemini(业界猜测/未公开) |
MoE(Mixture of Experts)模型通常具有大量总参数,但推理时只激活其中一部分专家,因此实际计算量可能远小于总参数规模。例如 DeepSeek-V3 / R1 总参数约 671B,但在推理时,每 token 仅激活约 37B。
对于同一模型,训练显存通常远大于推理显存,常见经验估计约为 5–10 倍。该比例会受到 batch size、上下文长度、并行策略、优化器和显存优化技术等因素影响。
输出不确定性
即使 temperature=0,大模型输出也不一定严格复现。常见原因:
- 浮点数和并行计算的不确定性。
- 多个候选 token 概率接近时,微小扰动会改变结果。
- MoE 模型在动态 batching 下可能走不同专家路径。
- 服务端动态调度、推理图优化、多副本部署也会引入差异。
工具层面现在也不一定只暴露 temperature,更多是 reasoning effort、speed、mode、profile 这类参数。稳定性主要靠测试、校验和审查,不靠同一个 prompt 逐字复现。
