预训练、后训练、微调与对齐:大模型训练流水线工程解读
2026/9/7 5:05:06 网站建设 项目流程

预训练、后训练、微调与对齐,是当前大语言模型(LLM)从“会写字”变成“会听话”的核心工序。很多人把这几件事混为一谈:以为“微调”就是“对齐”,以为“预训练”结束模型就能聊天,以为“后训练”只是换个数据集继续训练。实际上,每一阶段解决的问题、使用的数据、损失函数和计算成本都完全不同。

这篇文章从工程视角拆解这条流水线:先讲预训练如何让模型学会语言;再讲后训练和指令微调如何让模型学会“回答问题”而不是“续写文本”;接着讲对齐如何让回答符合人类偏好;然后对比全量微调、Freeze 微调和 LoRA 三种微调方式的差异,并给出最小可运行示例;最后提供验证方法和一份可以直接拿来用的排查清单。

适合读者:刚接触大模型应用开发的工程师、想系统理解 LLM 训练流程的技术负责人、以及准备做模型微调实验但还没有完整脉络的初学者。

1. 先从整体理解:预训练、后训练、微调、对齐到底在解决什么问题

1.1 四个阶段分别解决什么问题

用最简单的话说:

  • 预训练:让模型学会“语言”。它输入海量文本,目标是根据前面的词预测下一个词。训练结束后,模型具备了语言知识、世界常识和一定推理能力,但它只会“续写”,不会“回答”。
  • 后训练:让模型学会“交互”。在预训练模型基础上,用高质量的指令-回复数据继续训练,让模型学会遵循指令、以问答形式输出。当前工程中常说的 SFT(监督微调)就是后训练的核心环节。
  • 微调:让模型适应“特定任务或领域”。在通用模型基础上,用领域数据继续训练,使模型在某一场景表现更好,比如法律问答、代码修复、客服意图识别。微调是后训练的一种实际操作方式,但“微调”这个词更强调参数更新手段。
  • 对齐:让模型的回答符合人类偏好、价值观和安全要求。对齐不单纯是“让模型更聪明”,而是让模型知道什么该说、什么不该说、怎么说更符合人类期望,常见技术路线是 RLHF 和 DPO。

一句话概括四者的分工:预训练给模型知识,后训练和微调给模型能力,对齐给模型行为的边界。

1.2 执行顺序不是固定的“四步走”

在实际工程中,这四个阶段有相对固定的主顺序,但也存在分支:

预训练(Pretraining) -> 后训练:SFT / 指令微调 -> 对齐:RLHF / DPO / RLAIF -> 领域微调 / 应用场景适配

但“对齐”之前不一定必须做大规模 SFT,某些模型也会先做少量高质量 SFT,再用偏好优化完成对齐。领域微调也可以在 SFT 后直接做,不一定需要走完 RLHF。所以更准确的理解是:

  • 预训练是地基。
  • SFT 负责“人话能力”和“指令理解”。
  • 对齐负责“偏好和边界”。
  • 领域微调负责“业务场景适配”。

1.3 最容易混淆的三个边界

第一,后训练不等于微调。后训练是一个更大的概念,SFT、RLHF 都属于后训练;微调则更偏向“用标注数据更新模型特定能力”的参数更新动作。两者在中文技术语境里经常互换,但讨论训练流程时应区分开。

第二,SFT 出来的模型并不等于完成对齐。SFT 主要解决格式和指令跟随问题,模型可能仍然会输出有害内容或不合理答案。对齐需要额外使用偏好数据优化模型行为。

第三,预训练模型直接微调业务数据,不一定能获得“会对话”的能力。如果基座模型本身没有经过 SFT 和对话训练,直接丢进领域数据,模型输出的格式可能是续写,而不是标准问答。

2. 预训练:让模型先学会“语言”而不是“听话”

2.1 预训练的核心目标和数据形态

预训练的目标是让模型掌握语言的统计规律、语法、常识和世界知识。它不需要人工标注,数据是互联网上的海量文本,经过清洗、去重、过滤后,切成 token 序列。

当前主流的自回归语言模型使用因果语言建模(Causal Language Modeling,CLM)。对于一个 token 序列 x1, x2, ..., xn,模型通过之前所有 token 预测下一个 token,最大化整个序列的概率:

L = -1/n * sum(log P(x_t | x_1, x_2, ..., x_{t-1}))

这个公式看起来简单,但代价非常高:需要大量 GPU、数月训练时间、数 TB 文本数据。这也是为什么普通团队不会从头预训练模型,而是基于开源基座继续训练。

2.2 训练目标为什么选“预测下一个词”

预测下一个词看起来简单,实际是在强迫模型做多任务学习。为了准确预测下一个 token,模型必须理解句法、语义、指代、常识、逻辑关系、甚至一部分写作意图。这也是预训练模型具备“能力涌现”的根源。

但“会预测下一个词”不等于“会回答问题”。例如给定输入“中国的首都是”,模型能续写出“北京”;如果输入是“请回答:中国的首都在哪里?”,模型如果只在预训练阶段,输出可能是继续罗列问题相关文本,而不是规范回答“中国的首都是北京”。这就是必须进入后训练的原因。

2.3 常见预训练模型怎么选

模型特点适合场景
GPT 系列基座通用语言能力,对话需后续 SFT对话、生成、通用任务
LLaMA 系列开源生态好,社区适配多科研、私有化部署
Qwen 系列中文能力强,有对应 SFT 版本中文业务、Agent
BERT / RoBERTa编码器架构,适合理解任务分类、NER、语义匹配
ResNet(预训练)视觉模型,图像特征提取CV 迁移学习

注意:图像领域的“预训练模型”和 LLM 的“预训练”思想一致,都是用大数据集训练通用特征,再迁移到下游任务。区别在于视觉预训练模型可以直接加载权重做特征提取,LLM 基座则通常要经过 SFT 才能用于对话。

2.4 预训练阶段容易忽略的问题

预训练数据质量直接决定模型能力上限。常见坑包括:

  • 重复数据过多,模型产生复读机现象。
  • 语料清洗不彻底,混入大量 HTML 标签、代码碎片、非目标语言。
  • 测试集混入预训练数据,导致评估指标虚高。
  • 分词器词表与下游任务语言不匹配,中文场景尤其明显。

如果只是应用层开发,主力工作不在预训练,但选基座时要确认它的词表覆盖、上下文长度和许可证是否满足业务要求。RoBERTa、ResNet 这类“预训练模型”在传统 NLP 和 CV 里使用方式接近:加载权重后做特征提取或下游任务微调;LLM 则还要多走一步“对话能力”训练。

3. 后训练与指令微调:让模型从“续写”变成“回答”

3.1 为什么要单独区分“后训练”

后训练(Post-training)是预训练之后所有提升模型可用性训练步骤的统称。它的核心目标是把基座模型变成一个真实可用的助手。

工业界常见的后训练流程:

  1. SFT:用人类编写的指令-回复对,教会模型基本的问答格式。
  2. 偏好优化:用偏好数据训练奖励模型,再用 RLHF 或 DPO 调整行为。
  3. 安全对齐:加入安全规则、红队测试、敏感内容过滤。

SFT 是后训练的第一站,也是微调实操中接触最多的环节。

3.2 指令微调数据集长什么样

指令微调数据集的基本结构是:

{ "prompt": "解释什么是闭包。", "response": "闭包是指一个函数捕获并记住了其外部作用域变量的能力。例如在 JavaScript 中,内部函数即使在外层函数执行结束后,仍能访问外层函数的变量。" }

更完整的格式可能包含 system、history、context 等字段:

{ "system": "你是一个简洁的编程助手。", "instruction": "请用两句话解释什么是数据库索引。", "input": "", "output": "数据库索引是加速查询的数据结构,通常基于 B+ 树或哈希实现。它通过减少扫描行数来提升检索速度,但会占用额外存储并拖慢写入。" }

数据质量比数据量重要。几百条高质量指令往往比几万条噪音数据更有效。构造数据时要覆盖:简单问答、多轮对话、代码生成、文本改写、拒绝回答等场景。

3.3 SFT 的损失函数和训练方式

SFT 仍然使用交叉熵损失,但不同于预训练预测任意下一个词,SFT 只对回复部分的 token 计算损失,指令部分的 token 不参与梯度更新。这样可以避免模型反复学习“提问格式”,而专注于学习如何生成回复。

PyTorch 训练时的 mask 实现,通常通过 labels 中把指令部分设置为 -100:

from transformers import AutoModelForCausalLM, AutoTokenizer model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-7B") tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B") def tokenize_with_mask(example): prompt = example["prompt"] response = example["response"] full_text = prompt + response input_ids = tokenizer(full_text, truncation=True, max_length=1024)["input_ids"] prompt_ids = tokenizer(prompt, truncation=True, max_length=1024)["input_ids"] prompt_len = len(prompt_ids) labels = input_ids.copy() labels[:prompt_len] = [-100] * prompt_len # 指令部分不参与损失 return {"input_ids": input_ids, "labels": labels}

这里的关键点是 labels 中 -100 在 PyTorch / Hugging Face 训练时会自动被忽略。如果不做 mask,模型会把“提问格式”也学进去,导致重复、偏题等行为。

3.4 后训练阶段容易踩的坑

  • 数据格式不一致:有的样本只有单轮、有的有多轮,没有统一模板,导致训练时 loss 震荡。
  • 回复长度差异过大:长文本和短文本混合训练,容易让模型偏向输出固定长度。
  • 混入错误答案:没有做人工抽检,模型学会的是错误知识。
  • 学习率设置过高:SFT 阶段如果沿用预训练的大学习率,模型会迅速遗忘原有能力。

建议:SFT 阶段把学习率控制在基座模型预训练学习率的 1/10 到 1/50 量级,并优先使用带 warmup 的调度策略。

4. 对齐:让模型的回答符合人类偏好和价值观

4.1 对齐要解决的问题

SFT 之后模型能“回答问题”了,但不代表回答边界正确。模型可能:

  • 对敏感问题给出不合规内容。
  • 在不确定时编造事实。
  • 回答啰嗦、缺少逻辑、不尊重用户意图。
  • 被恶意 prompt 诱导绕过安全规则。

对齐(Alignment)的目标是让模型行为朝人类偏好方向优化。它更关注“做得是否符合预期”,而不只是“是否答对”。

4.2 RLHF 的三阶段流水线

RLHF(人类反馈强化学习)是经典对齐方案,分为三步:

  1. 训练奖励模型(Reward Model):收集人类对多个回答的排序,训练一个模型预测回答质量打分。
  2. 用奖励模型打分:让策略模型生成多个回答,奖励模型给出分数。
  3. 用强化学习优化策略:以奖励分数作为 reward,用 PPO 等算法更新模型参数。

PPO 目标里的 KL 惩罚是核心:

reward = reward_model_score - beta * KL(pi_theta || pi_ref)

KL 惩罚的作用是防止模型为了拿高分而彻底偏离原始模型,保证回答仍然自然、稳定。beta 值过大,模型变化太小;beta 值过小,模型容易生成高奖励但语义混乱的文本。

4.3 DPO:绕过奖励模型的简化方案

DPO(Direct Preference Optimization)把偏好优化从“训练奖励模型 + PPO 强化学习”简化成“直接用偏好对做监督式优化”。它的核心观点是:奖励模型的参数变化可以隐含在策略模型的概率变化中,不需要显式训练一个奖励模型。

DPO 损失函数的关键结构:

L = -log sigmoid(beta * (log P(y_w | x) - log P_ref(y_w | x) - (log P(y_l | x) - log P_ref(y_l | x))))

其中 y_w 是被人类偏好的回答,y_l 是较差回答。训练目标让偏好回答的概率相对上升、较差回答概率下降,同时控制与参考模型的偏差。

DPO 的优势是训练稳定、资源占用低、实现简单;劣势是对偏好数据质量更敏感,且没有在线探索能力。

4.4 对齐的代价:对齐税

对齐不是免费的。一个常见现象是对齐后的模型在某些创意任务、代码生成、严格推理任务上表现下降,英文社区称这种损失为 alignment tax。

原因是偏好优化强化了“稳妥、安全、符合人类直觉”的输出模式,可能抑制了模型原有的大胆推理和长尾能力。

工程上的应对方式:

  • 区分通用模型和专用模型,不要在一个模型里做所有事。
  • 保留多个 checkpoint,按场景选择模型。
  • 对高风险场景做额外的输入输出过滤,而不是只依赖模型自对齐。
  • 建立持续的评估集,跟踪对齐前后能力变化。

5. 微调实战:全量微调、Freeze 微调与 LoRA 如何选

5.1 三种方式更新参数的范围不同

  • 全量微调:所有参数都参与梯度更新。效果上限最高,但显存需求大,容易过拟合,也最容易产生灾难性遗忘。
  • Freeze 微调:冻结模型大部分层,只训练最后几层或特定模块。显存占用低,适合资源有限场景,但表达能力受限。
  • LoRA:冻结原模型参数,在每层注入低秩矩阵。训练时只更新低秩矩阵,推理时可以合并回原模型,不增加推理延迟。

三者不是“谁一定更好”,而是取决于数据量、硬件、目标任务。

5.2 对比速查表

对比维度全量微调Freeze 微调LoRA
可训练参数量全部少量层约 0.1% - 1%
显存需求中低
对数据量要求中低
灾难性遗忘风险较高中等较低
推理延迟无额外开销无额外开销合并后无额外开销
适合场景数据充足、任务变化大轻量适配快速实验、多任务适配

5.3 LoRA 最小训练示例

使用 Hugging Face PEFT 库实现 LoRA 微调,以 Qwen 系列为例:

from transformers import AutoModelForCausalLM, AutoTokenizer from peft import LoraConfig, get_peft_model base_model_name = "Qwen/Qwen2.5-1.5B-Instruct" model = AutoModelForCausalLM.from_pretrained( base_model_name, torch_dtype="auto" ) tokenizer = AutoTokenizer.from_pretrained(base_model_name) lora_config = LoraConfig( r=8, lora_alpha=16, target_modules=["q_proj", "k_proj", "v_proj", "o_proj"], lora_dropout=0.05, bias="none", task_type="CAUSAL_LM", ) model = get_peft_model(model, lora_config) model.print_trainable_parameters()

输出中的可训练参数量通常在总参数量的 1% 以内,说明 LoRA 只需要更新很少参数。

5.4 r、alpha、dropout 怎么设置

参数含义常见值调整影响
r低秩矩阵秩8 / 16 / 32越大表达力越强,越容易过拟合
lora_alpha缩放因子8 / 16 / 32与 r 配合缩放更新量,过大会导致训练震荡
lora_dropout低秩层随机失活0.05 / 0.1越大越防过拟合,过大会欠拟合
target_modules注入低秩矩阵的模块依模型而定覆盖注意力层是常见做法

如果训练数据很少,先从 r=8 开始;如果任务复杂且数据充足,再尝试 r=16 或 32。不要一上来就堆参数。

5.5 什么时候不应该微调

微调不是唯一手段。

  • 如果只是想让模型参考内部文档回答问题,优先做 RAG(检索增强生成),不需要改模型参数。
  • 如果只有几十条示例,先试 few-shot 提示工程,观察效果是否已经满足需求。
  • 如果任务是规范化输出、字段抽取,且可以用 prompt 控制,优先尝试提示词模板。
  • 如果任务需要高频稳定地改变模型行为,才考虑微调。

微调的正确使用路径是:先用现有模型验证基线,再判断是数据不足还是模型能力不足,最后才决定是否微调以及用哪种方式。

注意:不要只验证程序能启动,还要验证输入、输出、异常分支和日志是否符合预期。模型训练同理,loss 收敛不等于效果达标。

6. 验证与排查:训练完成后如何判断模型真的“学会”了

6.1 训练阶段看哪几个指标

训练日志中重点观察三个指标:

  • loss:训练 loss 下降说明模型在拟合训练数据,但下降过快可能过拟合。
  • eval_loss:验证集 loss 更关键,持续上升说明泛化能力变差。
  • 梯度范数:如果出现 NaN 或极大值,多半是学习率过高或数据异常。

LoRA 微调时,loss 常见区间在 0.5 到 2.0 之间,具体取决于任务难度和数据集规模。不要只看 loss 绝对值,要对比微调前基座模型在同样验证集上的表现。

6.2 验证方式要三种同时做

  • 自动指标:BLEU、ROUGE、准确率、F1,适合结构化任务,但对生成类任务参考价值有限。
  • 样例抽检:人工查看 50 到 100 个输入输出,检查格式正确性、逻辑一致性、错别字、危险内容。
  • 对抗测试:用偏离训练分布的 prompt 测试,比如换一种问法、加入无关背景,验证模型是否稳定。

建议维护一个固定评估集,包含简单用例、边界用例、拒答用例、多轮用例,每次训练后进行对比。

6.3 常见问题排查表

问题现象常见原因检查方式处理建议
训练 loss 不下降数据格式错误、mask 错误、学习率过低打印 batch 样本和 labels检查 prompt 和 response 拼接方式,确认 -100 mask 生效
loss 快速降到接近 0数据泄漏或过拟合对比训练集和验证集分布检查重复样本,减少轮数,增加数据多样性
微调后通用能力下降灾难性遗忘用通用 benchmark 测试混入通用数据、降低学习率、改用 LoRA
输出全是重复句子训练数据重复、解码参数不合适查看 token 重复率增加 repetition_penalty,检查数据多样性
指令理解能力变差SFT 阶段没做 mask 或模板不一致打印每个样本的 input_ids 和 labels统一模板,指令部分设为 -100
对齐后拒绝回答过多偏好数据过度保守统计拒绝回答比例平衡偏好数据,调整安全策略

6.4 推理阶段还要检查什么

微调完成后直接部署很容易踩坑:

  • 检查 tokenizer 的 pad_token 和 eos_token 设置,否则生成会卡死或输出到无限长度。
  • 检查 temperature、top_p、max_new_tokens 是否符合任务。
  • 检查是否加载了正确的 adapter:使用 PeftModel.from_pretrained 显式加载 LoRA 权重。
  • 生产环境要记录输入输出、推理耗时、资源占用,方便后续回滚和观测。

7. 最佳实践与学习路径:从跑通实验到上生产

7.1 学习环境与生产环境的差异

学习环境的目标是“跑通流程”,用 1B 级别模型、几百条数据、单卡即可。

生产环境的目标是“稳定且可维护”,至少要多考虑:

  • 使用已验证的模型版本和依赖版本,明确记录 checkpoint 与训练数据的对应关系。
  • 配置外置化:训练参数、数据路径、模型路径不写死在脚本里。
  • 数据版本管理:每次实验记录数据集的 hash、清洗规则、人工抽检结果。
  • 训练日志和监控:保存 loss、显存、吞吐量,出现异常可以回溯。
  • 回滚方案:保留多个模型版本和对应服务版本,支持一键切换。
  • 安全控制:输入输出过滤、敏感词拦截、人工审核入口。

7.2 微调前检查清单

开始微调之前,按这份清单逐项确认:

  • 数据集是否经过去重、清洗、格式统一?
  • prompt 和 response 是否分离清晰,mask 逻辑是否正确?
  • 数据集中是否包含测试集相关文本?
  • 是否已用基座模型跑过验证,建立基线指标?
  • 是否确定微调方式(全量 / Freeze / LoRA)和对应显存约束?
  • 学习率、batch size、训练轮数是否设置了初始合理值?
  • 是否预留部分数据做验证集?
  • 训练完成后是否准备了通用 benchmark 测试灾难性遗忘?
  • 是否有模型版本、数据版本、训练参数的记录?
  • 是否规划了生产部署的回滚方案?

7.3 推荐的学习顺序

如果从零开始学习这条流水线,推荐按以下顺序推进:

  1. 先用 Hugging Face transformers 加载一个 1B 级别模型,跑通文本生成,理解 base 模型和 chat 模型的差异。
  2. 构造 500 条指令数据,做一次 LoRA SFT,观察 loss 和输出格式变化。
  3. 学习 RLHF 和 DPO 的损失函数原理,用开源偏好数据集跑一次 DPO 实验。
  4. 在目标任务上做评估,对比微调前后指标。
  5. 再扩展学习全量微调、多卡分布式训练、数据并行和模型并行的概念。

整个过程中最重要的不是掌握某个库的 API,而是能解释每一步改动对模型行为的影响。真正理解这条流水线后,无论是做 Agent 场景、私有化模型还是垂直行业应用,都能快速定位问题所在,也不会再把“微调”和“对齐”当成同一件事。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询