大模型训练流程与微调技术
SFT
标准公式就一个
假设训练数据为:
1 | User: 1 + 1 = ? |
模型接收到问题后,预测下一个 Token 的概率:
| Token | 模型预测概率 |
|---|---|
| 2 | 0.8 |
| 3 | 0.1 |
| 4 | 0.1 |
正确答案是 2,所以:
如果模型认为正确答案 2 的概率只有 $0.1$,则:
因此,模型给正确 Token 分配的概率越高,Loss 就越小。
通过反向传播更新参数 $\theta$,使模型更倾向于生成正确答案。
八股
1. 详细描述从 txt 文本预处理到 SFT 训练的全流程(包括 Tokenize、Forward、Loss 计算、参数更新)
流程如下
1 | 文本预处理 -> Tokenization -> 构建输入 -> Forward -> Loss 计算 -> 参数更新 |
1. 文本预处理
首先去除无关字符,比如说乱码,html标签等。
然后质量过滤,目的是把烂文本拿出来丢掉,分两种:
- 基于规则:长度,重复行多
- 基于模型:如困惑度打分,计算PPL,低说明是人写的,可以保留
通常先基于规则,再基于模型
接着统一编码和格式,比如全转为UTF-8
最后是结构化,统一为json或message格式,如
1 | {"instruction": "...", "input": "...", "output": "..."} |
目的也很简单,为了分清 prompt 和 response,才能只对回答算 loss
2. Tokenization
首先把文本套chat模版,目的是让模型区分角色和轮次边界,然后进行分词并映射为id,最后加特殊token,如开头,结尾,pad
3. 构建输入
把 tokenize 得到的 id 序列整理成模型训练要的三个张量
首先是截断 + padding,得到 input_ids。超过max_length的裁剪,不到的pad,让同一个 batch 里的序列一样长
然后是attention_mask,真实 token 记 1,PAD 记 0,告诉模型 PAD 位置不用看
最后是labels:prompt 和PAD部分设成 -100,response 部分就是对应的 token id
PS:
让同一个 batch 里的序列一样长是为了拼为[B, T]放进GPU,矩阵乘法要求每一行长度相同
attention_mask负责输入,负责模型能看到哪些地方,labels负责输出,哪些位置的预测拿来算 loss、给模型打分
4. Forward
把 input_ids 和 attention_mask 输入模型,得到 logits,形状是 [batch_size, seq_len, vocab_size](本质embedding)
1 | input_ids [B,T] |
logits就是对每个位置,模型都会给词表里每一个 token 打一个分数,表示”下一个 token 是它”的可能性
5. Loss计算
用交叉熵损失,并且要 shift:用当前 token 预测下一个 token,即取 logits[:, :-1, :] 和 labels[:, 1:] 计算损失,忽略 labels 中为 -100 的位置
1 | 位置 t 的输入 它要预测的下一个 token(labels[t+1]) |
然后算交叉熵,先对 logits 做 softmax 得到概率,取正确 token 的概率 p,loss = -log p。最后对所有算 loss 的 token 取平均:
1 | L = -(1/L_a) · Σ log P(y_t | x, y_<t) L_a = 回答 token 的数量 |
6. 参数更新
Adam等
2. Pretrain、SFT、RLHF 的区别是什么?(目标、任务定位和解决的问题)
| Pretrain | SFT | RLHF | |
|---|---|---|---|
| 目标 | 学通用语言能力和世界知识 | 学会遵循指令、按任务格式回答 | 和人类偏好对齐(有用、无害、诚实) |
| 任务定位 | 自监督,预测下一个 token | 有监督的条件生成 | 强化学习,最大化奖励信号 |
| 解决的问题 | 模型会说话 | 模型听指令 | 纠正人不喜欢的行为 |
| 数据 | 海量无标注文本(网页、书、代码) | 精选指令-回答对(几十万到百万条) | 偏好数据(同一问题的多个回答排好坏) |
| Loss | 全部 token 的交叉熵 | 只算回答 token 的交叉熵 | PPO / DPO 等策略优化 |
用 Gemma 举例:Gemma 发布时有两个版本,gemma-3-xx-pt 是预训练完的 base 模型,gemma-3-xx-it 是经过 SFT + RLHF 的指令版。给它们同一个输入 “帮我写一首关于秋天的诗”:
- 只做了 Pretrain:它只会续写文本,可能接着输出 “帮我写一首关于春天的诗,帮我写一首…”。它会说话,但不知道你在给它下指令。
- 做了 SFT:输出一首诗。它听得懂指令了。
- 做了 RLHF:在多种写法里,更倾向于人们觉得更好的那种(意境好、长度合适)。遇到有害请求时,也会拒绝。
3. Pretrain 和 SFT 在优化目标上的区别是什么?
核心区别:两者都是交叉熵,但建模的概率不同。Pretrain 是无条件的,SFT 是有条件的。
Pretrain:对整段文本建模
最大化每一个 token 的似然。原文称之为无条件的密度估计:学的是”一段文本本身出现的概率有多大”,相当于学习语言的分布。
SFT:给定 prompt,对回答建模
$x$ 是 prompt,$y$ 是回答,只对回答的 $L_a$ 个 token 求和。原文称之为条件生成:学的是”给定这个问题,应该怎么回答”。prompt 只作为条件,本身不算 loss。
用 Gemma 例子对比
1 | <start_of_turn>user 翻译hello <end_of_turn> |
- Pretrain 的做法:每个 token 都要预测,包括 “user”、”翻译”、”hello”,等于连问题也要学着生成。
- SFT 的做法:只预测 “你好
“,问题只是条件。
4. SFT 的核心流程及数据集构建策略是什么?如何保证样本多样性和质量?
**核心流程:**文本预处理 -> tokenization -> 构建模型输入 -> forward -> 计算Loss -> 参数更新反向传播
数据集构建策略: 首先要求多样性,覆盖各种领域和任务类型,其次是质量,最后是难度,回答短,中,长和简单中等难
多样性和质量: 多样性控制比例,质量添加人工审核,如大模型生成答案后分层抽样一些
5. SFT 的 Loss 是什么?若 Target 有 10 或 100 个 Token,Loss 如何计算?
交叉熵不解释了,$L_a$ 是回答的 token 数,prompt 部分全部忽略
每个位置算一次 $-\log p$($p$ 是模型给正确 token 的概率),加起来,再除以 token 数
- 10 个 token:$\mathcal{L} = \frac{1}{10}\sum_{t=1}^{10} -\log p_t$
- 100 个 token:$\mathcal{L} = \frac{1}{100}\sum_{t=1}^{100} -\log p_t$
追问:一个 batch 里长短样本混在一起时怎么平均:按 token 平均(PyTorch CrossEntropyLoss 的默认行为,所有有效 token 放在一起取平均)
6. SFT 样本(含 Prompt)与预训练样本在计算 Loss 时的区别?如何屏蔽 Prompt 的 Loss?
预训练是所有 token 都算 loss,SFT是只有 responss的 token 算 loss
怎么屏蔽 prompt 的 loss:把 prompt 位置的 label 设成 -100,再在交叉熵里设置 ignore_index=-100
1 | token : <bos> <start_of_turn>user 翻译hello <end_of_turn> <start_of_turn>model | 你好 <end_of_turn> |
7. 手写 SFT 的 loss 计算代码(注意 shift right)
略,和代码一起
8. SFT 之后常见的 Post-Training(如 RLHF)有哪些?它们的目的有何区别?
| 方法 | 做法 | 目的 |
|---|---|---|
| RLHF | 先用人类偏好数据训练奖励模型,再用 PPO 优化策略 | 深度对齐人类价值观 |
| DPO | 不训练奖励模型,直接用偏好对(好回答、坏回答)优化 | 高效对齐:流程更简单,训练更稳定 |
| RLAIF | 和 RLHF 相同,只是偏好反馈由 AI 来打,替代人工标注 | 目的同 RLHF,但成本更低、更自动化 |
| RLVR | 用可验证的规则当奖励,答对得 1,答错得 0(比如数学答案比对、代码跑测试) | 用明确的反馈提升推理、数学、代码等能力 |
| 拒绝采样 / RFT | 让模型对同一问题采样多个回答,筛出好的,再拿去做 SFT | 用模型自己生成的高质量数据继续提升 |
9. 为什么 SFT 之后还要做 RL?为什么偏好对齐不能直接用偏好数据做 SFT,而要用 RL?
SFT 只能模仿,不会比较,只能学习token的分布,且上线收到质量限制
偏好对齐想要的是
1 | 训练后:P(A)=0.6 P(B)=0.1 ← 抬高 A,同时压低 B,拉开差距(margin) |
loss 里必须同时出现 A 和 B,并且对它们方向相反,但SFT只能给一个答案,把它的概率往上推。它没有办法表达”这个答案不好,把它的概率压下去”。
LoRA
本质目标是:不更新原始权重,而是学习一个规模小得多的权重变化量
先给定一个普通linear layer
其中,$x\in\mathbb R^{k}$:输入向量;$W\in\mathbb R^{d\times k}$:原始权重矩阵;$h\in\mathbb R^{d}$:输出向量
全参数微调会直接更新 $W$,LoRA 则固定 $W$,引入两个小矩阵:
用乘积近似权重增量
得
- $W$:预训练权重,冻结,不更新。
- $A,B$:LoRA 新增的可训练参数。
- $r$:低秩维度(Rank)。
- $\alpha$:缩放系数。
八股
1. 介绍一下 LoRA 的核心原理。秩 r 的选择会对模型表现产生什么影响?如何选择 rank 值?
原理:冻结原始权重,只用两个低秩小矩阵去学习权重的增量。
训练时只更新AB,
初始化用$A$ 用高斯分布初始化,$B$ 初始化为 0。这样训练刚开始时 $BA=0$,模型和原模型完全一致,不会一上来就被破坏。
参数量可以从 $d\times k$ 降到 $r(d+k)$。
PS:
为什么不把 A 和 B 都初始化成 0? 两个都是 0 时梯度也全是 0
缩放因子 α:实际实现是 $h=W_0x+\frac{\alpha}{r}BAx$。原文第 13 节提到,α 常取 $r$ 或 $2r$
r的选取,越大越接近全量微调
| r | 效果 |
|---|---|
| 太小(1 到 4) | 表达能力不够,欠拟合,复杂任务学不会 |
| 适中(8 到 32) | 表达能力和效率比较平衡,适合大多数任务 |
| 太大(32、64 以上) | 参数变多,过拟合风险上升,还可能学进噪声 |
网格搜索:在 {4, 8, 16, 32} 里分别训练,看验证集上哪个最好。
按任务复杂度:简单任务(比如固定格式输出、分类)用 4 到 8;复杂任务(比如推理、学习新领域知识)用 16 到 32。
2. LoRA 是否只能嵌入 Linear 层?为什么不能插在 LayerNorm 之后?对训练稳定性有什么影响?
理论上任何可训练的权重矩阵都能加 LoRA,比如 Embedding、Attention 的 Q/K/V/O 投影、MLP 层。但实际最常用的还是线性层。
LayerNorm 的输出是归一化过的,而 LoRA 加进去的增量没有经过归一化,会破坏归一化后的统计特性和 LayerNorm 的缩放不变性。
对稳定性的影响:可能导致梯度爆炸或梯度消失,训练变得不稳定。
加在 Linear 上之所以稳定,是因为 $B$ 初始化为 0,训练开始时 $BA=0$,模型等于原模型,后面再慢慢学增量
3. LoRA 微调推理时是否要挂着 Adaptor?合并 Adapter 权重时有没有遇到梯度爆炸?
看项目有没有,暂时忽略
4. QLoRA 降低资源成本的机制、量化方式、NF4 和 FP16 组合原因及 NF4 分布拟合逻辑
看项目有没有,暂时忽略
5. 训练 LoRA 模型时,如何选择冻结层?依据是什么
| 配置 | 适用场景 | 可训练参数 |
|---|---|---|
| 只在 Attention 和 FFN 的线性层加 LoRA | 通用指令微调 | 约 0.1% 到 1% |
| 再解冻 Norm | 数据少、需要快速收敛 | 只多约 0.01% |
| 再解冻 Embedding | 扩词表、多语言 | 明显变大 |
| 分层学习率 | 底层小、顶层大 | 参数量不变 |
各模块负责什么
- Attention:承载语义和句法,优先加 LoRA。
- FFN:存储事实知识,迁移到新领域时要加。
- Norm:参数很少,解冻它有助于训练更稳定。
推荐起点:所有线性层都加 LoRA,r=8,然后根据验证集的表现再调整。
其他八股
1. Tokenizer 是怎么做的?有哪些实现方式?
Tokenizer 是将原始文本(字符串)转换为模型可以处理的整数序列(token IDs)的组件。
主要步骤包括:文本规范化(如大小写转换、Unicode 归一化)、预分词(如按空格、标点切分)、基于词表的子词切分或字符切分,最后映射到 ID。
常见实现方式:
- 基于词(Word-based):直接按空格和标点分词,每个词一个 token。词表极大,存在 OOV(未登录词)问题。
- 基于字符(Character-based):每个字符作为一个 token。序列过长,缺乏语义信息。
- 基于子词(Subword-based):平衡词和字符,常见算法有:
- BPE(Byte Pair Encoding):从字符开始,逐步合并出现频率最高的相邻字节对,形成子词词表。GPT、BERT 等使用。
- WordPiece:类似 BPE,但合并依据是最大化训练数据似然,而非频率。BERT 使用。
- Unigram Language Model:从一个较大的词表开始,逐步剪枝保留概率最高的子词,最终得到词表。SentencePiece 支持。
- SentencePiece:将文本视为 Unicode 字符序列,可直接处理多语言,无需预先分词,支持 BPE 和 Unigram。
2. Embedding 是怎么做的?从 ID 到 Embedding 有哪些实现方式?
看项目有没有,暂时忽略
3. 控制模型生成多样性的参数有哪些?如何控制
分三种方式
- 调整分布形状:Temperature T
| $T$ | 概率 | 效果 |
|---|---|---|
| 0.5 | [0.87, 0.12, 0.02] | 分布更尖,接近贪心,更稳定、更保守 |
| 1.0 | [0.67, 0.24, 0.09] | 原始分布 |
| 2.0 | [0.51, 0.31, 0.19] | 分布更平,冷门词更容易被选中,更多样、更发散 |
- 限制候选范围
- Top-k:只保留概率最高的 $k$ 个 token,重新归一化后再采样。$k$ 越大越多样。
- Top-p(核采样):按概率从高到低累加,直到累计概率达到 $p$,只在这些 token 里采样。候选数量随分布动态变化:模型很确定时可能只剩 1 到 2 个候选,不确定时会有很多个。$p$ 越大越多样。
- 防止重复
如重复惩罚(repetition penalty):降低已经出现过的 token 的分数
4. top-k 与 top-p 的区别?
- top-k:固定选取概率最高的 k 个 token 作为候选,然后重新归一化采样。缺点:k 固定,可能在某些分布下(如平坦分布)截断过多,或尖锐分布时引入低概率词。
- top-p:动态选择累积概率达到 p 的最小 token 集合,适应不同分布。比如,如果 p = 0.7,那么就贪心选择概率最大的 token 加入候选集合,直到集合内 token 的概率累加 ≥ 0.7。当分布尖锐时,候选集小;平坦时,候选集大。更灵活。
5. 介绍一下常见的优化算法优缺点。为什么 Adam 不一定最优而 SGD 最优?怎么理解分析?
看项目有没有,暂时忽略
6. 怎么解决模型的冷启动问题?LLM 在冷启动方面能够起到什么作用?
冷启动:新模型或新系统上线时缺乏历史数据,导致无法提供有效服务。常见于推荐系统、对话系统等。
看项目有没有,暂时忽略
7. 大模型幻觉是什么?怎么缓解大模型幻觉?
- 检索增强生成(RAG):在生成前从外部知识库检索相关文档,作为上下文输入,让模型基于事实生成。
- 强化学习与人类反馈(RLHF):通过人类反馈训练奖励模型,优化生成内容的事实性(如 InstructGPT)。