想象你经营着一家叫“品味”的餐厅,新来的厨师小模刚从厨师学院毕业。他背熟了十万道菜谱,世界各地的名菜都能复刻,可顾客每次尝完都皱眉:“味道是正的,但不是我想要的。”小模很委屈——菜谱教的是“这道菜标准做法是什么”,可没人教他“客人真正喜欢什么”。大模型面临的困境一模一样:预训练让模型学会了“预测下一个词”,它懂语法、懂知识、懂逻辑,却不懂人类偏好。把“会生成”变成“会生成好的”,就是大模型对齐要解决的问题,也是偏好优化这个领域的起点。 最早的主流方案是 RLHF(基于人类反馈的强化学习),它像一位老派师傅,请来美食评论家打分,再让厨师反复调整。这套方法效果好,但工程复杂,像搭了一整套后厨评审体系。后来出现的 DPO(直接偏好优化)则像餐厅老板一拍桌子:“不用请评论家了,直接把顾客说‘这道比那道好吃’的反馈拿来练厨师!”不用训练奖励模型,数据直接驱动策略更新,简单、稳定、低成本。如今 KTO、SimPO、IPO 等变体又把这条路推向更远。读完这篇,你会理清偏好优化的完整技术脉络,知道该用哪种方法调校你的模型,以及各自的工程复杂度。
对 AI 从业者而言,掌握偏好优化是从“能跑模型”到“能对齐模型”的必修课:它决定了你的产品是让人惊艳,还是让人失望。
目录
可视化演示
展示RLHF三阶段对齐流程、DPO直接偏好优化原理以及两者在复杂度、稳定性、数据效率和计算量四个维度的工程权衡对比。
本节配有交互动效(进入视口后自动加载,约 3KB)。
RLHF三阶段对齐 SFT监督微调→RM奖励模型训练→PPO强化学习优化,逐步对齐人类偏好 π←SFT→RM→PPO→π* 三阶段流程复杂但效果稳定,需要额外训练奖励模型并维护在线策略
对齐问题:为什么要调教大模型的“口味”
厨师学院的课程只教一件事:“根据菜谱,预测下一道工序是什么。”小模在学院里成绩优异,他能根据前半道菜的做法,准确说出后半道菜怎么做——这就是大模型预训练的本质:预测下一个词。可顾客真正关心的不是“你有没有按常理出牌”,而是“这道菜好不好吃、合不合我口味”。模型懂知识,但不懂偏好,这就是对齐问题的由来。
从比喻过渡到技术:要让小模从“会做菜”变成“做出客人爱吃的菜”,我们需要在预训练之外增加一个“偏好对齐”阶段。这张训练图谱上,核心是让模型学会一个隐藏的“人类口味函数”——我们看不见它,但可以通过人类的对比反馈去逼近它。
技术展开:把这个问题形式化,假设策略模型是 $\pi_\theta$,它接收用户请求 $x$,生成回答 $y$。我们期望找到一个模型,让输出 $y$ 在“人类真实偏好”函数 $r^*(x, y)$ 上的期望分数最高:
1. 策略模型:$\pi_\theta(y|x)$ 表示当前模型在看到输入 $x$ 时,生成回答 $y$ 的概率分布。它就是“厨师小模”的决策机制。
2. 真实偏好:$r^*(x, y)$ 是顾客对“输入 $x$ 时给出回答 $y$”的真实满意度。在数学上把它当作一个理想化的打分函数,实际中不可直接观测。
3. 期望与最大化:$\mathbb{E}[\cdot]$ 是对所有输入和输出取平均;$\arg\max$ 表示我们要找一套参数 $\theta$,让这个平均满意度最高。
回到比喻:菜谱学院只教会小模“世界上的菜长什么样”,没教会它“顾客的舌头喜欢什么”。而接下来的所有方法——RLHF、DPO,都是在回答同一个问题:如何用有限的顾客反馈,把厨师的厨艺拧到正确的方向上。
RLHF流程:老派的三步教法
老板决定用最稳妥的方法训练小模。第一步,请一位经验丰富的老师傅手把手带他做几道经典招牌菜——这是“监督微调”(SFT),先把基础动作练对。第二步,请一批美食评论家来盲测,记录“哪道菜更好吃、为什么”,训练出一位能打分的首席评论家——这是“奖励模型”。第三步,让小模自己反复试做新菜,首席评论家打分,他根据分数调整厨艺——这是 PPO 策略优化。
这三步层层递进:SFT 让模型先学会“说人话”,奖励模型把“人类偏好”压缩成一个可计算的分数,PPO 再用这个分数驱动模型迭代。从宏观视角看,RLHF 的目标就是让策略模型产出的回答在奖励模型上拿到高分:
其中 $r_\phi$ 是训练好的评分函数(奖励模型),$\phi$ 是它的参数。这个公式看起来很简洁,但它背后藏着大量的工程细节:奖励模型怎么训、PPO 怎么采样、怎么保证梯度稳定。
1. 期望采样:$\mathbb{E}_{(x, y) \sim \pi_{\theta}}$ 表示从当前策略生成的一批“用户提问 + 模型回答”组合中取平均。这就是让小模不断试菜、记录成绩。
2. 奖励函数:$r_\phi(x, y)$ 是评论家对“在问题 $x$ 下给出回答 $y$”给出的分数,$\phi$ 是评论家自己的参数。
3. 最大化:$\max_{\theta}$ 是我们要调整厨师小模的策略参数 $\theta$,让这组分数在平均意义下尽量高。
RLHF 就像老字号培养传人:每一步都有师傅把关、有评论家背书,效果稳健。但整套体系搭起来很重——要训练评论家、要反复采样、要精细调 PPO 的超参数。一旦评论家本身品味有偏差,所有努力都会被带偏。这也是后来 DPO 要革新的地方。
奖励模型:训练一位“美食评论家”
小模做菜好不好吃,不能自己说了算,得请评论家打分。可这位评论家不是天生的,ta 在学徒期间品尝了成千上万道菜,听了无数句“这道比那道好吃”的评语,才慢慢建立起品味。奖励模型的训练正是如此:它需要海量“偏好对”数据来养成。
技术细节上,奖励模型接收一个回答,输出一个标量分数。训练数据是一个个对比对:给定同一个用户提问 $x$,模型先生成两个候选回答 $y_w$(更好的那个)和 $y_l$(较差的那个),人类标注者判断哪个更好。奖励模型要最大化“赢家得分高于输家”的概率。这里最常用的数学框架是 Bradley-Terry 模型:
1. 偏好符号:$y_w \succ y_l$ 表示“回答 $y_w$ 比 $y_l$ 更受人类偏好”,这是训练数据的核心标注。
2. 指数化:$\exp(r_\phi(x, y))$ 把奖励分数映射成正数,分数越高权重越大。就像把“美味程度”从线性刻度换到指数刻度。
3. 归一化占比:用赢家的权重除以所有候选权重之和,得到“赢家胜出”的预测概率。训练时让这个概率尽量接近真实标注(即接近 1)。
评论家的偏好不是凭空出现的,而是被偏好数据“喂”出来的。它把顾客口味压缩成了一根可计算的标尺。但隐忧也随之而来:如果标尺本身有偏差(标注一致性差、覆盖场景不够),后面整个 PPO 训练都会被带偏。这正是 DPO 想绕开的坑。
PPO核心:策略更新与那根“橡皮筋”
有了评论家,小模就开始按分数改菜。可他越改越歪:他发现评论家喜欢摆盘华丽的菜,于是他疯狂堆砌雕花、用花瓣点缀,菜却难以下咽——这就是“奖励窜改”(Reward Hacking)。为了让小模不疯魔,老师傅给他拴了一根“橡皮筋”:你可以在新方向上探索,但别离传统做法太远。这根橡皮筋在数学上叫 KL 散度惩罚。
PPO 的优化目标因而包含两项:一是奖励分数要尽量高,二是新策略不能偏离参考策略太远:
1. 参考模型:$\pi_{\text{ref}}(y|x)$ 是“传统做法”的化身,通常取 SFT 之后的模型,用来记录重训之前的行为基准。
2. 对数概率比:$\log \frac{\pi_\theta(y|x)}{\pi_{\text{ref}}(y|x)}$ 衡量新策略相比参考策略,对当前回答的“偏爱变化”。偏离越大,惩罚越大。
3. KL 惩罚系数:$\beta$ 控制橡皮筋的松紧。$\beta$ 大,新策略不敢乱动;$\beta$ 小,探索更激进但更容易窜改奖励。
除了这个目标,PPO 还会用“优势估计”来判断某个回答比平均水平好多少,从而决定往哪个方向更新。整根流程就像一次步步为营的探索:既要高分,又别跑偏。橡皮筋的思想后来也被 DPO 继承了下来,只是 DPO 把整套强化学习舞台设备都撤掉了。
DPO原理:跳过评论家,直接学
老板终于受不了了:“请评论家、建评分体系、再调 PPO——太折腾了。为什么不直接用顾客的对比反馈练厨师?”DPO 的核心洞察是:在 RLHF 的最优解条件下,奖励函数其实可以被策略模型的概率比直接表示出来。也就是说,奖励模型是“多余”的——它的打分功能可以隐式地藏在策略里。
这个“隐式奖励”长这样:
把它代回 Bradley-Terry 框架,就可以直接写出 DPO 的损失函数:
1. 隐式奖励:$r_{\text{DPO}}(x, y)$ 用策略自身的概率比来充当奖励函数,不需要单独训练评论家。
2. 奖励差:$\beta \log \frac{\pi_\theta(y_w|x)}{\pi_{\text{ref}}(y_w|x)} - \beta \log \frac{\pi_\theta(y_l|x)}{\pi_{\text{ref}}(y_l|x)}$ 计算好回答与差回答的隐式奖励差,相当于“好菜比坏菜好多少”。
3. Sigmoid 与负对数:$\log \sigma(\cdot)$ 把奖励差转换成“好回答胜出的概率”,再取负对数变成损失——概率越高损失越低。
DPO 的最大优势是训练稳定:不需要强化学习循环,没有评论家偏差,计算成本大幅下降。餐厅老板砍掉了整套评审体系,用顾客最原始的偏好直接改写厨师的肌肉记忆。没有复杂舞台道具,训练自己就跑起来了。
方法对比:旧派与革新怎么选
小模的餐厅里,老派师傅坚持 RLHF,新派老板推 DPO。到底选谁?这取决于你的后厨资源。RLHF 像老字号培养传人,稳扎稳打但要养一个评论家团队;DPO 像快餐连锁培训,简单直接,上菜快。两条路其实都在同一条“橡皮筋”下做文章——KL 散度。
KL 散度是衡量新旧策略差异的标尺:
RLHF 把它作为惩罚项显式扣除;DPO 则把它内化到隐式奖励中,实现“用结果说话”。两者殊途同归,都不想让模型跑得太偏。
1. 分布差异:$\mathrm{KL}(\pi_\theta \| \pi_{\text{ref}})$ 计算新策略与参考策略分布之间的距离。值为 0 时两者完全一致,越大说明改得越猛。
2. 期望:$\mathbb{E}_{y \sim \pi_\theta}$ 表示在新策略生成的回答分布上取平均,统计平均的偏离程度。
3. 两种用法:RLHF 把它写成目标函数里的减法项;DPO 把它装进隐式奖励,再由对比对间接约束。
具体怎么选,可以看几个关键维度:
| 维度 | RLHF | DPO |
|---|---|---|
| 额外模型 | 需训练奖励模型 | 不需要 |
| 训练稳定性 | 依赖 PPO 调参 | 相对稳定 |
| 计算成本 | 高 | 低 |
| 长度偏差控制 | 较容易 | 需额外克制 |
| 适用场景 | 复杂推理、安全严控 | 快速迭代、通用对话 |
选哪条路取决于你的资源:有成熟的强化学习团队、不差算力、任务又刁钻,RLHF 仍是一把好手;想快、想省、想稳定迭代,DPO 是更轻的解法。没有银弹,只有匹配场景的选择。
前沿变体:DPO 的进化家族
DPO 的成功带火了一个家族。就像餐厅后厨里,有人发明了“不用顾客对比也能知道好不好”的新教法,有人发现“连老菜谱都不需要了”,还有人用“平方误差”取代原来的概率损失。它们各显神通,把偏好优化推向了更轻、更稳的边界。
- KTO:不需要成对偏好,只需要知道某个回答“整体上被接受还是被拒绝”。类似顾客只对一道菜竖拇指或摇头,就能训练。数据收集难度大大降低。
- SimPO:连参考模型都省了,直接用回答的平均对数概率代替参考得分,减少一次模型前向,更省显存。
- IPO:把 DPO 的 sigmoid 损失改成类似平方间隔的损失,避免模型对“赢家赢多少”过度自信,训练更稳。
以 SimPO 为例,它的目标函数长这样:
1. 长度归一化:$\frac{1}{|y_w|}$ 和 $\frac{1}{|y_l|}$ 把得分除以回答长度,防止长回答因为“字数多”而天然占便宜,这是 SimPO 的特色去偏手段。
2. 目标间隔:$\gamma$ 是“领先阈值”。奖励差至少要超过 $\gamma$,模型才认为这对偏好被学到位了。
3. 省略参考模型:整个公式没有再出现 $\pi_{\text{ref}}$,这意味着训练时不需要加载并前向参考模型,显存和耗时都下降。
DPO 家族的这些变体,本质上都是在“简化操作、增强稳定、适配低成本部署”三个维度上做取舍。没有万能的偏好优化器,只有最贴合你数据形态和算力预算的那一种。
AI 应用场景
对话产品的“品牌调性”对齐
阶段:模型微调与对齐
解决的问题:企业部署大模型客服时,直接使用通用预训练模型,回答虽然通顺,但语气僵硬、不够礼貌、偶尔还会踩安全红线。用 RLHF 做对齐需要组建强化学习团队、训练奖励模型,成本高周期长。DPO 只需要构造几十到几百条“好回答 vs 差回答”的对比对,一次低资源微调就能让模型学会品牌要求的语气和边界。
具体案例:某金融机构要做一个理财助手,团队收集了 800 对回答:同一用户问题下,“合规且贴心”的回答作为赢家,“生硬或带误导性”的回答作为输家。用 DPO 在 LoRA 上微调开源底座模型,两天内完成对齐,回答的合规通过率从 71% 提升到 93%,且没有使用任何强化学习框架。
开源模型社区的“低成本对齐”
阶段:开源模型二次开发
解决的问题:开源模型(如 Llama、Qwen)能力很强,但缺少针对特定社群语言的“口味”。社区开发者没有 RLHF 所需的算力和人力,需要一种轻巧的方法把模型调成“自己人”。
具体案例:一个开源社区想要一个更“简洁直接”的代码助手。他们从 GitHub issue 中收集了 5000 组对比:用简短回答 vs 冗长回答、正确解法 vs 踩坑解法。用 DPO 训练后,模型在代码解释任务上平均回答长度下降 40%,用户投票满意度提升 28%。整个训练在一块消费级显卡上即可完成。
Python 演示
import torchimport torch.nn.functional as F def compute_logps(model, input_ids, attention_mask): logits = model(input_ids, attention_mask=attention_mask).logits[:, :-1, :] targets = input_ids[:, 1:] log_probs = F.log_softmax(logits, dim=-1) per_token_logp = torch.gather(log_probs, 2, targets.unsqueeze(-1)).squeeze(-1) mask = attention_mask[:, 1:].float() return (per_token_logp * mask).sum(dim=-1) def dpo_loss(w_logps, l_logps, w_ref_logps, l_ref_logps, beta=0.1): ratio = beta * ((w_logps - w_ref_logps) - (l_logps - l_ref_logps)) loss = -F.logsigmoid(ratio).mean() return loss def dpo_step(policy, ref_policy, batch, optimizer, beta=0.1): w_ids = batch["w_ids"] w_mask = batch["w_mask"] l_ids = batch["l_ids"] l_mask = batch["l_mask"] w_logps = compute_logps(policy, w_ids, w_mask) l_logps = compute_logps(policy, l_ids, l_mask) with torch.no_grad(): w_ref = compute_logps(ref_policy, w_ids, w_mask) l_ref = compute_logps(ref_policy, l_ids, l_mask) loss = dpo_loss(w_logps, l_logps, w_ref, l_ref, beta) optimizer.zero_grad() loss.backward() optimizer.step() return loss.item() if __name__ == "__main__": torch.manual_seed(42) w_logps = torch.tensor([-2.0, -1.6, -2.8, -2.3]) l_logps = torch.tensor([-3.2, -2.5, -3.6, -2.8]) w_ref = torch.tensor([-2.1, -1.9, -2.7, -2.5]) l_ref = torch.tensor([-2.6, -2.1, -2.9, -2.6]) loss_val = dpo_loss(w_logps, l_logps, w_ref, l_ref, beta=0.1) print("DPO loss:", loss_val.item())
logits = model(input_ids, attention_mask=attention_mask).logits[:, :-1, :]取模型每个位置输出的预测 logits,去掉最后一个位置(因为最后一个词没有“下一个词”)。targets = input_ids[:, 1:]把输入序列右移一位作为预测目标,形成“根据前文预测当前词”的配对。per_token_logp = torch.gather(...)从 log 概率矩阵中取出每个位置真实 token 对应的 log 概率。mask = attention_mask[:, 1:].float()把 padding 位置遮掉,确保损失只计算真实 token。ratio = beta * ((w_logps - w_ref_logps) - (l_logps - l_ref_logps))这是 DPO 的核心:好回答的隐式奖励差减去差回答的隐式奖励差。loss = -F.logsigmoid(ratio).mean()把奖励差转换成“偏好正确”的损失,差距越小损失越大。
常见误区
误区DPO 既然不用训练奖励模型,那是不是完全不需要人工标注了?让模型自己给自己打分就行。
正解DPO 依然需要偏好数据——同一提示下的两个回答,以及人类标注的“哪个更好”。它只是省掉了“用这些数据训练一个独立打分模型”这一步,并没有省掉数据本身。就像餐厅老板免去了评论家,但顾客依然得亲口说“A 比 B 好吃”,厨师才知道往哪个方向调。
为何常见:DPO 的宣传重点是“去掉奖励模型”,很多人误以为也去掉了人类反馈,实际上偏好数据才是成本主体。
误区RLHF 是 OpenAI 等大厂的成熟做法,DPO 只是简化版,最终效果一定差一截。
正解在大量对话、摘要、指令遵循任务上,DPO 的效果与 RLHF 相当甚至更好,尤其在分布外提示上更稳。RLHF 的优势主要体现在复杂多步生成、安全约束严格的场景。方法选择要看任务特性和工程资源,而不是看谁名气大。
为何常见:RLHF 历史更长、论文更多、大厂背书更强,容易让人默认它是“完全体”,而 DPO 只是“轻量替代”。
误区DPO 直接改策略,所以从头到尾没有奖励模型这个概念。
正解DPO 确实不显式训练奖励模型,但在数学推导中等价地隐含了一个奖励函数:$\beta \log (\pi_\theta / \pi_{\text{ref}})$。它仍然在“追求奖励”,只是把评分内嵌到了策略的概率比中。比喻:评论家被辞退了,但顾客的口味依然在暗中决定每道菜的命运。
为何常见:论文和博客都强调“去掉 RM”的工程简化,推导中的隐式奖励部分容易被忽略。
误区从网上随便扒一些“好回答/坏回答”丢进 DPO 就能提升模型。
正解偏好数据的质量、多样性和标注一致性非常关键。如果数据噪声大(标注员不认真、回答差异太小、任务过难),DPO 会把噪声当成信号放大,反而伤害模型的原有能力。好的偏好对讲究“同一提示下的可对比性”——差距要明显、错误要可解释。
为何常见:小样本实验里 DPO 看起来很快收敛,容易让人误以为“数据不重要,跑起来就有用”。
误区DPO 就一个损失函数,没有什么可调的。
正解$\beta$ 是关键超参数,控制模型偏离参考模型的程度,不同任务的最优 $\beta$ 从 0.05 到 0.7 不等;SimPO 还有 $\gamma$,KTO 还有 $\lambda$。DPO 比 PPO 简单,但不代表参数可以不管。比喻:橡皮筋的松紧如果不调,厨师要么放不开手脚,要么跑得太野。
为何常见:相比 PPO 的多个超参数,DPO 需要调的东西很少,容易给人“免调参”的错觉。
面试题
Q1. RLHF 三阶段的通常执行顺序是?
- A.SFT 预热 → 奖励模型训练 → PPO 优化← 正确答案
- B.PPO 优化 → SFT 预热 → 奖励模型训练
- C.奖励模型训练 → SFT 预热 → PPO 优化
- D.SFT 预热 → PPO 优化 → 奖励模型训练
答案:A。RLHF 的经典顺序是先用人工标注做监督微调(SFT),让模型输出“像样”的回答;再用偏好对训练奖励模型;最后用 PPO 利用奖励分数优化策略。B、C、D 都打乱了这条因果链。
Q2. DPO 方法最核心的改变是?
- A.使用更大规模的奖励模型
- B.绕开显式奖励模型直接调策略← 正确答案
- C.增加强化学习的迭代轮数
- D.用更大语料扩充预训练数据
答案:B。DPO 的突破在于用策略模型自身的概率比构造隐式奖励,跳过了“单独训练奖励模型”这一大步骤。它不是简单地调大模型或加数据,而是改变了整个对齐管线。
Q3. 奖励模型的典型训练数据形态是?
- A.单个回答的数值分数
- B.成对回答的偏好标记← 正确答案
- C.无标注的原始文本
- D.图像与文本的配对
答案:B。奖励模型通常用“偏好对”训练:同一个提示下两个候选回答,标注哪个更好。单个回答的分数标注也可以,但不是主流且成本更高;原始文本和图文配对是预训练或多模态任务的数据形态。
Q4. Bradley-Terry 模型主要负责?
- A.评估生成文本的语法是否正确
- B.推算偏好对中优质回答胜出的概率← 正确答案
- C.计算模型参数占用的显存
- D.把回答压缩成固定长度的向量
答案:B。Bradley-Terry 把赢家的指数奖励归一化,得到“赢家胜过输家”的概率。它负责的是“排序比较”,而不是语法检查、显存计算或向量压缩。
Q5. PPO 目标中加入 KL 惩罚项,主要目的是?
- A.让奖励模型更容易收敛
- B.防止策略偏离参考模型过远← 正确答案
- C.加快训练数据采样速度
- D.降低模型的推理延迟
答案:B。KL 惩罚是新策略与参考策略之间的“橡皮筋”,防止模型为了拿高分而输出极端、不自然的回答(奖励窜改)。它和奖励模型收敛、采样速度、推理延迟没有直接关系。
Q6. 与 RLHF 相比,DPO 的典型优点包括?
- A.免去单独训练奖励模型← 正确答案
- B.训练计算成本明显下降← 正确答案
- C.完全消除所有超参数
- D.训练过程通常更稳定← 正确答案
答案:ABD。DPO 不需要训练奖励模型,节省了正向计算和存储成本;不需要 PPO 的采样循环,稳定性更好。但它仍有 β 等关键超参数,不是“零调参”。
Q7. 下列哪些属于偏好优化的新变体?
- A.KTO← 正确答案
- B.SimPO← 正确答案
- C.LoRA
- D.IPO← 正确答案
答案:ABD。KTO、SimPO、IPO 都是 DPO 家族的代表变体。LoRA 是参数高效微调方法,与偏好优化属于不同维度,但它常被用来配合 DPO 做低资源微调。
Q8. DPO 使用的“隐式奖励”数学形式是?
- A.β·log(πθ(y|x)/πref(y|x))← 正确答案
- B.β·log(πref(y|x)/πθ(y|x))
- C.log(πθ(y|x)×πref(y|x))
- D.exp(β·(πθ(y|x)−πref(y|x)))
答案:A。DPO 推导出的隐式奖励是 β 乘以新策略与参考策略的对数概率比。其他形式把分子分母颠倒、把乘法写作指数或对数和,都不符合 DPO 的推导结果。
Q9. SimPO 相比 DPO 的主要简化是?
- A.不再需要成对的偏好数据
- B.去掉参考模型的前向计算← 正确答案
- C.用卷积网络替换注意力网络
- D.用规则打分替代模型判断
答案:B。SimPO 用回答的平均对数概率直接作为隐式奖励,不再需要加载并前向参考模型,显著降低了显存和计算开销。它仍然需要偏好对,也没有改动模型结构。
Q10. 关于 DPO 的说法,正确的有?
- A.DPO 完全不需要参考模型
- B.DPO 隐式包含一个奖励函数← 正确答案
- C.DPO 显著降低对齐工程复杂度← 正确答案
- D.DPO 完全不使用 KL 约束
答案:BC。DPO 在推导中隐式定义了奖励函数 β·log(πθ/πref),因此 B 正确;它省去了 RM 训练和 PPO 循环,工程复杂度大幅下降,C 正确。但 DPO 仍然需要参考模型来计算概率比,且 KL 约束体现在 β 的选择中,A、D 都错误。