第四部分:大模型后训练与微调
摘要 :本部分聚焦于如何"定制"你的大模型。我们将学习 SFT(有监督微调) 让模型听懂指令,掌握 LoRA 技术以极低成本适配垂直领域,并深入 RLHF(人类反馈强化学习) 的数学原理与代码实现------这是 DeepSeek-R1 等推理模型能产生强大逻辑思维的关键技术。
第11章 【后训练】有监督微调 (SFT)
11.1 什么是 SFT (Supervised Fine-Tuning)?
预训练模型本质上是个"续写机"。如果你问它:"中国的首都在哪里?",它可能会续写:"这个问题的答案很简单..."而不是直接回答"北京"。 SFT 的目的就是通过 (指令, 回答) 数据对,教会模型遵循对话格式。
-
数据格式 :
json{ "instruction": "请解释量子纠缠。", "input": "", "output": "量子纠缠是指两个或多个粒子处于一种纠缠态..." } -
训练差异 :
- 预训练:对所有 Token 计算 Loss。
- SFT :通常只对 Output(回答部分) 计算 Loss,忽略 Instruction 部分(Masking)。
11.2 强大的微调框架:LLaMA-Factory
手写训练循环虽然有助于理解,但在工程实践中,我们通常使用成熟框架。LLaMA-Factory 是目前最流行的开源微调框架,支持 DeepSeek、Qwen、Llama 等几乎所有主流模型。
【实战】使用 LLaMA-Factory 进行 LoRA 微调
-
安装:
bashgit clone https://github.com/hiyouga/LLaMA-Factory.git cd LLaMA-Factory pip install -e .[metrics] -
启动 Web UI(小白友好模式):
bashllamafactory-cli webui- 在网页中选择模型路径(如
deepseek-llm-7b-chat)。 - 选择微调方法(LoRA)。
- 选择数据集(可以是自定义的 json 文件)。
- 点击"开始训练"。
- 在网页中选择模型路径(如
-
命令行启动(服务器模式):
bashllamafactory-cli train \ --stage sft \ --do_train \ --model_name_or_path deepseek-ai/deepseek-llm-7b-base \ --dataset my_custom_data \ --finetuning_type lora \ --output_dir ./saves/deepseek_lora \ --per_device_train_batch_size 4 \ --gradient_accumulation_steps 4 \ --lora_rank 8 \ --fp16
11.3 思维链 (CoT) 数据构造
DeepSeek 的强大在于推理。普通 SFT 数据只给结果,CoT 数据给过程。
- 普通数据 :
问:1+1等于几? 答:2 - CoT 数据 :
问:1+1等于几? 答:思考过程:这是一个基本的算术加法。1代表一个单位... 结论:2实战技巧 :利用 GPT-4 或 DeepSeek-V3 生成带有<thinking>标签的数据来蒸馏小模型。
第12章 【后训练】参数高效微调 (PEFT)
全参数微调(Full Fine-tuning)需要消耗的显存是推理的 4 倍以上。对于 7B 模型,全参数微调至少需要 80GB A100。而 PEFT 让你可以用 RTX 3090/4090 在家微调大模型。
12.1 LoRA (Low-Rank Adaptation) 原理与实战
核心原理 : 不需要更新巨大的权重矩阵 <math xmlns="http://www.w3.org/1998/Math/MathML"> W W </math>W(例如 <math xmlns="http://www.w3.org/1998/Math/MathML"> 4096 × 4096 4096 \times 4096 </math>4096×4096),而是学习两个极小的矩阵 <math xmlns="http://www.w3.org/1998/Math/MathML"> A A </math>A 和 <math xmlns="http://www.w3.org/1998/Math/MathML"> B B </math>B(例如 <math xmlns="http://www.w3.org/1998/Math/MathML"> 4096 × 8 4096 \times 8 </math>4096×8 和 <math xmlns="http://www.w3.org/1998/Math/MathML"> 8 × 4096 8 \times 4096 </math>8×4096)。 <math xmlns="http://www.w3.org/1998/Math/MathML"> W ′ = W + Δ W = W + A × B W' = W + \Delta W = W + A \times B </math>W′=W+ΔW=W+A×B 其中 <math xmlns="http://www.w3.org/1998/Math/MathML"> r r </math>r (rank) 远小于 <math xmlns="http://www.w3.org/1998/Math/MathML"> d d </math>d。训练时冻结 <math xmlns="http://www.w3.org/1998/Math/MathML"> W W </math>W,只更新 <math xmlns="http://www.w3.org/1998/Math/MathML"> A A </math>A 和 <math xmlns="http://www.w3.org/1998/Math/MathML"> B B </math>B。
【实战】手撸 LoRA 层逻辑 (PyTorch)
python
import torch
import torch.nn as nn
class LoRALayer(nn.Module):
def __init__(self, in_dim, out_dim, rank=8, alpha=16):
super().__init__()
# 1. 原始的预训练权重 (冻结)
self.linear = nn.Linear(in_dim, out_dim, bias=False)
self.linear.weight.requires_grad = False
# 2. LoRA 旁路矩阵 (A和B)
# B通常初始化为0,A高斯初始化 -> 初始状态下 LoRA 不影响原模型
self.lora_a = nn.Parameter(torch.randn(in_dim, rank) / rank)
self.lora_b = nn.Parameter(torch.zeros(rank, out_dim))
self.scaling = alpha / rank
def forward(self, x):
# 原始路径
original_out = self.linear(x)
# LoRA 路径: x @ A @ B * scaling
# 注意维度匹配: (Batch, in) @ (in, r) @ (r, out) -> (Batch, out)
lora_out = (x @ self.lora_a @ self.lora_b) * self.scaling
return original_out + lora_out
# 测试
layer = LoRALayer(in_dim=1024, out_dim=512, rank=8)
x = torch.randn(1, 1024)
print(f"LoRA输出: {layer(x).shape}") # torch.Size([1, 512])
12.2 QLoRA
LoRA 解决了参数量问题,但原模型 <math xmlns="http://www.w3.org/1998/Math/MathML"> W W </math>W 还要占显存。 QLoRA :将 <math xmlns="http://www.w3.org/1998/Math/MathML"> W W </math>W 量化为 4-bit 加载,进一步将 7B 模型的微调门槛降低到 6GB 显存。
第13章 【后训练】强化学习基础
为什么 SFT 不够?因为有些东西很难写出标准答案(比如"写一个好笑的笑话")。强化学习(RL)允许我们定义"什么是好的",让模型自己去探索如何达到。
13.1 RL 核心概念映射
- Agent (智能体):大模型本身。
- Environment (环境):用户(Prompt)和 奖励模型。
- Action (动作):模型生成的每一个 Token。
- State (状态):当前的上下文(Prompt + 已经生成的 Token)。
- Reward (奖励):生成的文本有多好(由 Reward Model 打分)。
13.2 策略梯度 (Policy Gradient)
我们要优化的是策略 <math xmlns="http://www.w3.org/1998/Math/MathML"> π \pi </math>π(即模型参数),使得期望奖励最大化。 <math xmlns="http://www.w3.org/1998/Math/MathML"> ∇ J ( θ ) ≈ E [ ∇ log π θ ( a ∣ s ) ⋅ R ] \nabla J(\theta) \approx \mathbb{E} [\nabla \log \pi_\theta(a|s) \cdot R] </math>∇J(θ)≈E[∇logπθ(a∣s)⋅R] 通俗理解:如果动作 <math xmlns="http://www.w3.org/1998/Math/MathML"> a a </math>a 获得了高分 <math xmlns="http://www.w3.org/1998/Math/MathML"> R R </math>R,就增加产生 <math xmlns="http://www.w3.org/1998/Math/MathML"> a a </math>a 的概率;如果分低,就降低概率。
第14章 【后训练】人类反馈式强化学习 (RLHF)
这是 ChatGPT 和 DeepSeek-R1 能够实现逻辑飞跃的关键。
14.1 RLHF 三阶段流水线
- SFT:先训练一个稍微懂事的模型(如果不懂事,RL 很难探索出来)。
- Reward Model (RM) 训练 :
- 人工标注:给模型的两个回答排序(A 比 B 好)。
- 训练 RM:让 RM 给 A 的打分比 B 高。
- 损失函数:Pairwise Ranking Loss。
- PPO (Proximal Policy Optimization) 训练 :
- 用 RM 给模型生成的回答打分。
- 用 PPO 算法更新模型参数。
14.2 深入 PPO 算法与 KL 散度
在强化学习中,为了防止模型为了拿高分而"胡言乱语"(Hacking the reward),我们需要约束它不能偏离原始 SFT 模型太远。 这就是 KL 散度 (KL Divergence) 的作用。
总奖励计算公式 : <math xmlns="http://www.w3.org/1998/Math/MathML"> R t o t a l = R m o d e l ( x , y ) − β ⋅ log π R L ( y ∣ x ) π S F T ( y ∣ x ) R_{total} = R_{model}(x, y) - \beta \cdot \log \frac{\pi_{RL}(y|x)}{\pi_{SFT}(y|x)} </math>Rtotal=Rmodel(x,y)−β⋅logπSFT(y∣x)πRL(y∣x)
- <math xmlns="http://www.w3.org/1998/Math/MathML"> R m o d e l R_{model} </math>Rmodel:奖励模型给的分。
- <math xmlns="http://www.w3.org/1998/Math/MathML"> β ⋅ log . . . \beta \cdot \log ... </math>β⋅log...:KL 惩罚项。如果 RL 模型生成的概率分布和 SFT 差太多,就扣分。
【实战】手撸 Reward Model 评分代码片段
python
from transformers import AutoModelForSequenceClassification, AutoTokenizer
import torch
# 加载奖励模型 (通常基于 BERT 或 Llama 修改了最后一层)
rm_model_name = "deepseek-ai/deepseek-reward-model-dummy" # 伪代码示例
# model = AutoModelForSequenceClassification.from_pretrained(rm_model_name, num_labels=1)
def get_reward_score(prompt, response):
# 构造输入: [CLS] Prompt [SEP] Response [SEP]
text = f"{prompt} {response}"
inputs = tokenizer(text, return_tensors="pt")
with torch.no_grad():
# 输出是一个标量分数
score = model(**inputs).logits[0].item()
return score
# 示例
prompt = "如何学好Python?"
res_A = "多写代码,多看源码。" # 好回答
res_B = "去睡觉吧。" # 坏回答
# print(f"A得分: {get_reward_score(prompt, res_A)}")
# print(f"B得分: {get_reward_score(prompt, res_B)}")
14.3 DeepSeek 的 GRPO (Group Relative Policy Optimization)
DeepSeek-R1 的创新 : 传统的 PPO 需要一个巨大的 Critic 模型(和 Actor 一样大),显存占用翻倍。 DeepSeek 提出了 GRPO:
- 不需要 Critic 模型。
- 对同一个 Prompt 生成一组(Group)回答。
- 计算这组回答的平均奖励,以相对优劣作为优势函数(Advantage)。
- 效果:极大降低了 RLHF 的计算资源消耗,使得大规模强化学习成为可能。我们将在第16章详细实战 GRPO。
第四部分总结: 如果说预训练是"九年义务教育",后训练就是"大学专业课"。通过本部分,你掌握了 SFT 来规范模型输出,利用 LoRA/QLoRA 降低微调成本,并初步触达了让模型产生高级智能的 RLHF/PPO 技术。
下期预告 : 下一部分我们将深入解密 DeepSeek 的核心黑科技 ------第五部分:DeepSeek核心技术解密与逻辑推理 。我们将详细剖析 MLA (多头潜在注意力) 如何压缩 KV Cache,以及 DeepSeek-R1 是如何通过纯强化学习涌现出思维链(Chain-of-Thought)能力的,并手把手带你复现 GRPO 算法。敬请期待!