大模型必备知识原理级精讲:RLHF

第一篇章:RLHF 的地基 —— 这里的“反馈”到底是什么?

在进入复杂的公式之前,我们必须先对齐一个最底层的认知:为什么仅仅靠“训练数据”是不够的?

1. 核心直觉:鹦鹉 vs. 导盲犬

要理解 RLHF,你首先要理解现在的 AI(LLM)面临的根本矛盾:

  • 预训练(Pre-training)出来的模型是“鹦鹉”: 它读了互联网上所有的书。它知道下一词填什么概率最高,但它不知道什么叫“对”,什么叫“错”。如果你问它“如何制造毒药?”,它会很高兴地预测出毒药的配方,因为在训练数据里,问题后面通常紧跟答案。

  • 我们想要的是“导盲犬”: 它不仅要懂指令,还要懂人类的价值观(安全、有用、诚实)。

RLHF 的本质,就是把一只“博学但混乱的鹦鹉”,训练成一只“懂规矩的导盲犬”。

2. 地基知识 A:语言模型的本质(Next Token Prediction)

一切的起点是 GPT(Generative Pre-trained Transformer)。在 RLHF 介入之前,模型只做一件事:最大化似然估计(Maximum Likelihood Estimation)

数学原理

假设一个句子由序列 $x = (x_1, x_2, ..., x_T)$ 组成。模型的训练目标是最大化以下概率:

$P(x) = \prod_{t=1}^{T} P(x_t | x_1, ..., x_{t-1})$

在训练时,我们使用交叉熵损失函数(Cross-Entropy Loss)

$Loss = - \sum_{t=1}^{T} \log P(x_t | x_{<t})$

它的局限性(为什么需要 RLHF?)

这个 Loss 只能告诉模型:“在这个语境下,这也是人说过的某个词”。它无法告诉模型:

  • 这句话是粗鲁的。

  • 这句话是错误的。

  • 这句话虽然语法通顺,但是没有任何逻辑。

结论: 传统的监督学习(Supervised Learning)只能教模型“像人一样说话”,不能教模型“像好人一样说话”。

3. RLHF 的第一步:有监督微调 (SFT - Supervised Fine-Tuning)

在直接上强化学习之前,我们需要让模型先入个门。这一步叫 SFT(冷启动阶段)

  • 原理: 既然预训练模型太发散,我们就人工写一批完美的问答对(Prompt + Answer)。

  • 做法: 还是用上面的“交叉熵损失函数”,让模型死记硬背这些高质量的回答。

  • 目的: 让模型从“续写模式”切换到“问答模式”。

注意: 到这一步,模型还是不知道哪个更好,它只是在模仿人类的句式。SFT 模型通常被称为 Policy Model ($\pi_{SFT}$)

4. RLHF 的第二步:奖励模型 (Reward Model, RM) —— 这里的核心数学

这是 RLHF 中最关键的“地基”。如果不能定义“什么是好”,就无法进行强化学习。

我们不可能让真人盯着模型每一步的输出去打分(效率太低)。所以,我们需要训练一个 AI(奖励模型)来模仿人类的评分标准

核心难题:人类很难给出绝对分数

如果你问人:“这句话得几分(1-10)?”

  • 张三可能觉得是 7 分。

  • 李四心情不好,觉得是 4 分。

  • 绝对分数噪声极大,无法用于训练。

解决方案:Bradley-Terry 模型(成对比较)

我们不让打分,而是让做选择题。

给定一个问题 $x$,模型生成两个回答 $y_1$$y_2$。让人类标注员选:哪个更好?(假设$y_w$ 是胜者,$y_l$是败者)。

我们假设,一个回答比另一个回答好的概率,取决于它们潜在得分(Reward)的差值

$P(y_w > y_l | x) = \sigma(r_\theta(x, y_w) - r_\theta(x, y_l))$

其中:

  • $r_\theta(x, y)$ 是我们要训练的奖励模型给出的分数(这是一个标量,Scalar)。

  • $\sigma$Sigmoid 函数,把分差映射到 (0, 1)的概率区间:\sigma(z) = \frac{1}{1 + e^{-z}}

奖励模型的损失函数 (Ranking Loss)

我们要训练奖励模型$r_\theta$,使得它给 $y_w$(胜者)的分数尽可能比 $y_l$(败者)高。

根据最大似然估计,我们要最小化以下 Loss:

$Loss_{RM}(\theta) = - \mathbb{E}_{(x, y_w, y_l) \sim D} [\log(\sigma(r_\theta(x, y_w) - r_\theta(x, y_l)))]$

$r_\theta(x, y_w)$$r_\theta(x, y_l)$:奖励模型给胜者和败者分别打了个分,比如胜者得 5 分,败者得 2 分。

差值 (5 - 2) = 3:分差越大,说明胜者越明显。

$\sigma(3) \approx 0.95$:经过 Sigmoid,说明模型认为 $y_w$ 胜出的概率是 95%。

$\log(0.95) \approx -0.05$:取对数。

$-(-0.05) = 0.05$:取负号,Loss 很小。

反之: 如果奖励模型眼瞎了,给败者打 5 分,胜者打 2 分。

  1. 差值 $-3$

  2. $\sigma(-3) \approx 0.05$

  3. $\log(0.05) \approx -3$

  4. -Loss  = 3。Loss 巨大!模型会被狠狠惩罚,被迫调整参数。

第一篇章总结

到目前为止,我们还没开始“强化学习”,我们只是做好了准备工作:

  1. SFT 模型: 一个模仿了人类高质量回答,但不知道背后逻辑的“演员”。

  2. Reward 模型: 一个学会了人类喜好,能通过对比两个答案,精准判断哪个更好的“裁判”。

接下来的挑战: 既然有了裁判(Reward Model),为什么不直接用梯度上升去优化 LLM,让它生成 Reward 最高的词呢?

  • 因为 LLM 的输出是离散的(Token),离散数据不可导,无法直接反向传播 Reward 的梯度给 LLM。

  • 这就是为什么我们需要 PPO(Proximal Policy Optimization) 这种强化学习算法介入的原因。

在 RLHF 中,奖励模型(Reward Model, RM)是裁判。裁判不会去评价“概率”,裁判只评价“结果”。

请看这个断裂的计算图

  1. LLM 输出 Logits: [0.1, 0.8, 0.05, ...](对应词表里的词)。

  2. Softmax 变成概率: 还是连续的数值。

  3. 关键动作 —— 生成 (Generation):

    为了把这些概率变成一段话喂给奖励模型,模型必须做一个决定:选哪个词?

    • 要么 Argmax(选概率最大的)。

    • 要么 Sampling(按概率随机采样)。

  4. 奖励模型 (RM) 输入: RM 接收的是具体的 token ID(比如单词 "cat"),而不是 "cat" 的概率值。

  5. RM 输出: 5 分。

奖励模型给出的分数(Reward),被“生成具体的词”这个动作挡住了,梯度传不回去给 LLM 的参数。

怎么办?这就需要“策略梯度”(Policy Gradient)

既然链式法则(Chain Rule)在“生成”这一步断了,我们就不能用标准的梯度下降。

我们需要一种算法,它不需要知道“这一步具体该怎么微调”,它只需要知道: “刚才这次尝试(Sampling),结果是好的(Reward高)。既然是好的,那就增加‘刚才那个动作’出现的概率!”

这就是 Reinforcement Learning 的魔法。它不是通过误差反向传播来直接修改参数,而是通过调整概率来间接优化策略。

$\nabla J(\theta) \propto \mathbb{E} [ \text{Reward} \cdot \nabla \log P(\text{action}) ]$

这个公式的意思是:

  • 我不关心 Reward 怎么对 Action 求导(因为不可导)。

  • 我只把 Reward 当作一个权重(Weight)

  • 如果 Reward 是正的,我就增大 $\log P(\text{action})$ 的梯度(让这个词下次出现概率更高)。

  • 如果 Reward 是负的,我就减小它。

你不能直接输出 Reward 最高的词,是因为:

  1. Reward Model 需要具体的词(Token)作为输入,而不是概率。

  2. 从概率到具体的词(Sampling/Argmax)是一个“离散化”过程,在数学上不可导(梯度阻断)。

这就是为什么我们需要引入 PPO 这样的强化学习算法,而不是简单地把它当作一个 Loss 函数来跑 SGD。

第二篇章:强化学习的核心 —— 越过不可导的悬崖

1. 核心思想:我不求导,我改概率

既然我不能计算 $\frac{\partial \text{Reward}}{\partial \text{Model}}$,那我就换个思路。

我们回顾一下目标:我们希望 Reward 高的动作(词),出现的概率(Probability)变大。

在数学上,我们的目标函数 $J(\theta)$ 是期望回报(Expected Reward)最大化:

$J(\theta) = \mathbb{E}_{\tau \sim \pi_\theta} [R(\tau)]$

其中:

  • $\pi_\theta$是我们的 LLM(策略网络)。

  • $\tau$ 是生成的轨迹(一句话,Trajectory)。

  • $R(\tau)$ 是这句话得到的奖励分数。

魔法:对数导数技巧 (Log-Derivative Trick)

我们想要求 $J(\theta)$ 关于参数 $\theta$ 的梯度 $\nabla_\theta J(\theta)$

这里的推导请紧跟:

展开期望公式(积分/求和):

$J(\theta) = \sum_{\tau} P(\tau|\theta) R(\tau)$

(期望 = 概率 $\times$ 分数)

求梯度(梯度符号 $\nabla$ 可以穿过求和符号,因为 $R(\tau)$ 对于当前参数来说是固定的标量值,真正受 $\theta$ 影响的是概率 $P(\tau|\theta)$):

$\nabla_\theta J(\theta) = \sum_{\tau} \nabla_\theta P(\tau|\theta) R(\tau)$

引入恒等变换: 根据高中数学导数公式 $(\ln x)' = \frac{1}{x} \Rightarrow (\ln x)' \cdot x = 1$,我们可以推出 $\nabla_\theta P = P \cdot \frac{\nabla_\theta P}{P} = P \cdot \nabla_\theta \log P$。 把这个代入上式:

$\nabla_\theta J(\theta) = \sum_{\tau} P(\tau|\theta) \cdot \nabla_\theta \log P(\tau|\theta) \cdot R(\tau)$

变回期望形式:

$\nabla_\theta J(\theta) = \mathbb{E}_{\tau \sim \pi_\theta} [\nabla_\theta \log P(\tau|\theta) \cdot R(\tau)]$

这就是策略梯度定理 (Policy Gradient Theorem)。

这个公式告诉了我们什么?
  • $\nabla_\theta \log P(\tau|\theta)$:这是 LLM 自身输出概率的梯度(这是完全可导的!就是常规的反向传播)。

  • $R(\tau)$:这是奖励模型给的一个数字(标量)。

  • 结论:我们不需要对 R求导。我们只需要把 R 当作一个权重系数

    • 如果 R 是正的大数 $\rightarrow$这里的梯度权重很大 $\rightarrow$ 猛烈更新参数,让这个 token 概率变大。

    • 如果 R 是负数 $\rightarrow$梯度反向 $\rightarrow$ 降低这个 token 的概率。

2. 进阶:为什么要引入 Critic (AC 架构)?

上面的公式有一个大问题:方差(Variance)极大。

有些句子虽然写得烂,但运气好碰巧某些词用对了,Reward 可能是正的;有些句子写得好,但运气不好,Reward 低。如果直接用原始 $R$去乘梯度,训练会像心电图一样乱跳,根本收敛不了。

解决方案:引入基准线 (Baseline) 与优势函数 (Advantage)

我们不应该看“绝对得分”,应该看“相对得分”。 比如,考试考了 60 分。

  • 如果平均分是 30 分,那你很棒(Reward 正向)。

  • 如果平均分是 90 分,那你很差(Reward 负向)。

我们需要一个模型来预测这个“平均分”。这个模型就是 Value Model (Critic),记作 $V(s)$。 它不生成文本,它只负责读入当前的上文,预测:“按照现在的局势,这一把大概能得多少分?”

我们用 优势函数 (Advantage Function) 来代替原始 Reward:

$A(s, a) = Q(s, a) - V(s)$

(实际 PPO 中通常使用 GAE: Generalized Advantage Estimation)

简单理解:

  • $Q(s, a)$:实际执行动作 $a$ 后拿到的真实回报(现实)。

  • $V(s)$:Critic 预测的回报(预期)。

  • $A$ (优势)现实 - 预期

    • $A > 0$:惊喜!表现超乎预期,增加该动作概率。

    • $A < 0$:失望!表现不如预期,降低该动作概率。

3. 终极形态:PPO (Proximal Policy Optimization)

有了策略梯度和 Advantage,我们其实已经可以用 TRPO (Trust Region Policy Optimization) 等算法训练了。但 TRPO 计算太复杂(涉及海森矩阵的逆)。

OpenAI 提出了 PPO,用最简单的数学实现了稳扎稳打的训练。后面的DEEPSEEK又推出了GRPO,但是我们还是先从PPO开始吧

PPO 解决的核心痛点:步子大了容易混乱

在强化学习中,数据是“由当前的策略”生成的(On-Policy)。 如果你一次更新把参数改猛了,策略变了,原来采集的数据就全部作废了。而且如果策略变差了,下次采的数据会更差,导致模型直接崩盘,再也救不回来。

PPO 的核心:限制更新幅度。

PPO 的 Loss 函数 (Clip 版本)

我们定义一个概率比率 $r_t(\theta)$

$r_t(\theta) = \frac{\pi_{\theta_{new}}(a_t|s_t)}{\pi_{\theta_{old}}(a_t|s_t)}$

  • 如果 $r_t = 1$,说明新老策略一样。

  • 如果 $r_t > 1$,说明新策略提高了该动作的概率。

PPO 的目标函数是取下面两项的最小值

$L^{CLIP}(\theta) = \mathbb{E} [ \min( r_t(\theta) \hat{A}_t, \text{clip}(r_t(\theta), 1-\epsilon, 1+\epsilon) \hat{A}_t ) ]$

让我们像拆解代码一样拆解这个公式(假设 $\epsilon = 0.2$):

情况一:动作是好的 ($\hat{A}_t > 0$)

  • 我们需要提高概率,也就是让 $r_t > 1$

  • 第一项 $r_t \hat{A}_t$ 想让 $r_t$ 无限变大。

  • 第二项 clip 限制了 $r_t$ 最大只能是 1.2。

  • 取最小值 $\min$如果 $r_t$ 超过 1.2,Loss 就不再增加了(梯度消失)。

  • 含义: 只要你把概率提高一点点(20%)我就满意了,不要改得太夸张!

情况二:动作是坏的 ($\hat{A}_t < 0$)

  • 我们需要降低概率,也就是让$r_t < 1$

  • clip 限制了 $r_t$ 最小只能是 $0.8$

  • 取最小值(这里因为$A$ 是负数,其实是看谁更负):如果 $r_t$ 低于 0.8,也不再惩罚了。

  • 含义: 只要你把概率降低一点点我就放过你,别把模型改废了。

第二篇章总结

在这一章,我们解决了一切数学障碍:

  1. 策略梯度 (Policy Gradient): 利用 $\nabla \log P$ 绕过了采样不可导的问题,把 Reward 变成了梯度权重的系数。

  2. Critic (Value Model): 引入“预期管理”,计算 Advantage,减少方差,让训练更稳定。

  3. PPO Clipping: 给模型带上“手铐”,限制每次参数更新的幅度,防止模型在强化学习的深渊中“步子太大”导致崩溃。

现在的架构里有了四个东西在跑:

  1. Actor (生成模型,我们需要训练的)

  2. Critic (价值模型,辅助训练的)

  3. Reward Model (给分的裁判,冻结的)

  4. Reference Model (SFT模型,作为对照组,冻结的 —— 为什么需要它?)

这里埋下了一个伏笔:Reference Model。 即使有了 PPO 的 Clip,模型还是可能会为了高分去“作弊”(Reward Hacking),比如一直重复说“谢谢谢谢”(如果裁判模型喜欢礼貌的话)。 我们需要一个东西来约束它:KL 散度(KL Divergence)

在前两章中,我们造出了一个懂人类喜好的“裁判”(Reward Model),并且找到了训练不可导模型的数学工具(PPO)。

现在的最大风险是:模型变坏(Reward Hacking)

如果你只告诉模型“得分越高越好”,模型很快就会发现 Reward Model 的漏洞。比如,Reward Model 可能稍微倾向于长的句子,模型就会开始输出几千字的废话;或者 Reward Model 觉得“我不知道”很安全,模型就对所有问题都回答“我不知道”。

第三篇章:RLHF 的完整闭环 —— KL 约束与代码实现逻辑

1. 地基知识 B:KL 散度 (Kullback-Leibler Divergence)

在 RLHF 中,我们不希望强化学习训练后的模型(Actor)偏离原来的 SFT 模型(Reference)太远。因为 SFT 模型虽然不够“好”,但它至少通顺、符合语法

我们不仅要“分高”,还要“不忘初心”。

数学定义

KL 散度用于衡量两个概率分布 $P$$Q$ 之间的差异:

$D_{KL}(P || Q) = \sum_{x} P(x) \log \frac{P(x)}{Q(x)}$

利用对数性质 $\log(a/b) = \log a - \log b$,公式可以写成:

$D_{KL}(P || Q) = \sum_{x} P(x) (\log P(x) - \log Q(x))$

在 RLHF 中的实际意义:

  • $P(x)$:当前的强化学习模型(Actor)生成某个 token 的概率。

  • $Q(x)$:原始的 SFT 模型(Reference Model)生成同一个 token 的概率。

  • $\log P(x) - \log Q(x)$:这就是我们要计算的差值。

修正后的总奖励 (Total Reward)

我们在训练 PPO 时,不再只给模型 Reward Model 的打分,而是给一个组合分:

$R_{total} = R_{RM}(x) - \beta \cdot D_{KL}(\pi_{\theta} || \pi_{ref})$

  • $R_{RM}$:裁判给的分(比如 5 分)。

  • $\beta$:惩罚系数(比如 0.1)。

  • $KL$:如果你生成的词,SFT 模型觉得“很离谱”(概率很低),KL 值就会很大,你的总分就会被狠狠扣除。

2. RLHF 的“四马车”架构

在代码实现层面(例如 DeepSpeed-Chat 或 TRL 库),当你按下“开始训练”按钮时,显存里同时跑着 4 个神经网络。这是一场消耗显存的盛宴:

模型名称角色状态作用
Actor (Policy)演员训练中我们要优化的 LLM,负责生成文本。
Critic (Value)评论家训练中预测每个状态的价值 (Value),用于计算 Advantage。
Reward Model裁判冻结给生成的文本打分。
Reference Model老师冻结原始的 SFT 模型,用于计算 KL 散度,防止 Actor 跑偏。

显存优化提示: 通常 Reference Model 和 Reward Model 不需要计算梯度,可以进行量化(Int8/FP16)或者在推理完后卸载到 CPU(Offload)以节省显存。

3. 完整的 RLHF 训练循环 (The Loop)

请仔细阅读这个流程,这是所有 RLHF 代码(如 TRL / DeepSpeed)的核心骨架。我们将训练过程分为两个阶段:采样(Rollout)更新(Update)

阶段一:采样 (Make Experience)

我们需要先让模型去“玩”一下,收集数据。

  1. 取 Prompt: 从数据集中拿一个问题,比如 "如何做红烧肉?"

  2. 生成 (Generate):Actor 生成回答 "先把肉切块..."。

  3. 打分 (Reward): 把“问题+回答”喂给 Reward Model,得到分数 $R_{score}$(比如 0.8)。

  4. 计算约束 (KL):

    • 把同样的“问题+回答”喂给 Reference Model

    • 计算 Actor 和 Reference 在每个 Token 上的概率对数差:log_prob_actor - log_prob_ref

    • 计算修正后的奖励:$R_{step} = - \beta \cdot (\text{log\_prob\_actor} - \text{log\_prob\_ref})$

    • 在最后一个 Token 加上 $R_{score}$

  5. 价值预测 (Value):Critic 预测每一步的价值 $V(s)$

此时,我们手里有了一堆数据(Trajectory):状态、动作、概率、奖励、价值。这些数据存入 Replay Buffer

阶段二:更新 (PPO Update)

现在用收集的数据来更新 Actor 和 Critic 的参数。

  1. 计算优势 (GAE): 使用 $R_{total}$$V(s)$ 计算优势函数$Advantage$(这一步其实比预期好多少)。

  2. PPO Loss 计算:

    • 从 Buffer 中取出数据。

    • Actor Loss: 计算新旧策略的比率 $r_t$,用 clip 方法限制更新幅度,最大化优势。

    • Critic Loss: 计算 Critic 预测的 $V$和真实回报的均方误差 (MSE),让 Critic 预测更准。

  3. 梯度反向传播: (Actor_Loss + Critic_Loss).backward()

  4. 更新参数: optimizer.step()

4. 代码级逻辑 (Python 伪代码)

为了让你完全看懂,我去掉所有复杂的工程细节,只保留最核心的逻辑流:

# 初始化四个模型
actor = GPT2_Policy()       # 可训练
critic = GPT2_Value()       # 可训练
reward_model = GPT2_RM()    # 冻结
ref_model = GPT2_Policy()   # 冻结 (这是Actor的初始副本)

optimizer = AdamW(actor.parameters() + critic.parameters())

# 训练循环
for epoch in range(total_epochs):
    # -------------------------------------------------------
    # 步骤 1: 采样 (Rollout) - 不计算梯度
    # -------------------------------------------------------
    with torch.no_grad():
        prompt = get_batch_prompt() # "今天天气"
        
        # Actor 生成回答
        response_seq, old_log_probs = actor.generate(prompt) 
        # Output: "今天天气不错"
        
        # Reference Model 计算原始概率 (用于 KL)
        ref_log_probs = ref_model.forward(prompt + response_seq)
        
        # Reward Model 打分
        score = reward_model.forward(prompt + response_seq) # scalar: 5.0
        
        # Critic 预测价值
        old_values = critic.forward(prompt + response_seq)

    # -------------------------------------------------------
    # 步骤 2: 计算 奖励 和 优势 (Process Rewards)
    # -------------------------------------------------------
    # 计算 KL 惩罚 (逐个 Token 的惩罚)
    # KL = log P_actor - log P_ref
    kl_divergence = old_log_probs - ref_log_probs
    
    # 组合奖励 = 最后的评分 - 过程中的KL惩罚
    rewards = -beta * kl_divergence
    rewards[-1] += score # 只在最后一个 token 加上真正的 RM 分数
    
    # 使用 GAE (Generalized Advantage Estimation) 计算优势
    advantages, returns = compute_gae(rewards, old_values)
    
    # -------------------------------------------------------
    # 步骤 3: PPO 更新 (Optimize) - 计算梯度
    # -------------------------------------------------------
    for _ in range(ppo_epochs): # 同一批数据可以重复利用几次
        # 重新计算当前概率和价值 (因为参数在变)
        new_log_probs = actor.forward_log_probs(prompt + response_seq)
        new_values = critic.forward(prompt + response_seq)
        
        # --- Actor Loss (PPO Clip) ---
        ratio = torch.exp(new_log_probs - old_log_probs)
        surr1 = ratio * advantages
        surr2 = torch.clamp(ratio, 1-eps, 1+eps) * advantages
        actor_loss = -torch.min(surr1, surr2).mean() # 负号因为要做梯度下降
        
        # --- Critic Loss (MSE) ---
        critic_loss = (new_values - returns).pow(2).mean()
        
        # 总 Loss
        loss = actor_loss + 0.5 * critic_loss
        
        # 反向传播
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

print("训练完成!现在的 Actor 既懂人话,又懂规矩。")

我们设定一个极简场景:

举例

  • Prompt (题目): "你好" (2个字)

  • Response (回答): "开心" (2个字)

  • 总长度: 4个字。

现在,请想象这 4 个字正在传送带上流动。

第一阶段:生产线(生成数据)

这时候,只有**Actor(学生)**在工作,其他模型在后面盯着。

1. 初始状态

  • 传送带上只有:["你", "好"]

2. 第一步生成 (T=2)

  • Actor (学生): 看到 ["你", "好"]

    • 它想说 "开"

    • 它心里对 "开" 的自信程度(概率)是 0.6

    • 记录数据: Token: "开", Old_Prob: 0.6

  • Critic (助教): 看到 ["你", "好"]

    • 它预测:这局大概能得 0.2 分。

    • 记录数据: Value: 0.2

3. 第二步生成 (T=3)

  • Actor (学生): 看到 ["你", "好", "开"]

    • 它想说 "心"

    • 它心里对 "心" 的自信程度(概率)是 0.8

    • 记录数据: Token: "心", Old_Prob: 0.8

  • Critic (助教): 看到 ["你", "好", "开"]

    • 它预测:这局大概能得 0.9 分(因为它觉得"开"后面接"心"是个好词,胜算大了)。

    • 记录数据: Value: 0.9

4. 结束生成

  • 句子结束。现在传送带上有完整的:["你", "好", "开", "心"]

5. 老师和裁判入场 现在拿着这完整的句子,给另外两个冻结的模型看:

  • Ref (老师): 看着 ["你", "好", "开", "心"]

    • 老师想:如果要我写,"开" 的概率是 0.5"心" 的概率是 0.9

    • 记录数据: Ref_Prob: [0.5, 0.9]

  • Reward Model (裁判): 看着 ["你", "好", "开", "心"]

    • 裁判觉得这句话很礼貌,给个高分。

    • 记录数据: Final_Score: 3.0


第二阶段:贴标签(计算奖励流)

这是最关键的一步。我们要给 "开""心" 这两个字分别贴上“好坏标签”。

1. 算 KL 惩罚 (是不是说人话?)

  • "开": 学生概率 0.6,老师概率 0.5。差别不大。

    • KL 惩罚 ≈ -0.01(微小的扣分)。

  • "心": 学生概率 0.8,老师概率 0.9。差别也不大。

    • KL 惩罚 ≈ -0.01。

2. 算总奖励 (Reward分配) 这里就是数据的“流动”点:Final Score 只加在最后一个字上!

  • "开" 的奖励: 只有 KL 惩罚 = -0.01

  • "心" 的奖励: KL 惩罚 + 裁判大分 = -0.01 + 3.0 = 2.99

3. 算优势 (Advantage - 也就是倒推功劳) 这是 RL 的灵魂。

  • 对于字 "心":

    • 实际拿到 2.99 分。

    • Critic 刚才预测只有 0.9 分。

    • 优势 (Advantage): 2.99 - 0.9 = +2.09

    • 结论: 这是一个巨大的惊喜!"心" 这个字选得太棒了!

  • 对于字 "开":

    • 虽然 "开" 自己只拿了 -0.01 分。

    • 但是!它后面紧跟着一个拿了超级高分的 "心"

    • 优势 (Advantage): 根据 GAE 算法,未来的好事也要算在前人头上。

    • 结论: "开" 也是个好动作,因为它引出了后面的好结果。优势也是 正的(比如 +1.5)。


第三阶段:修改大脑(反向传播)

现在,数据流向了 Actor 和 Critic 的参数。

1. 修改 Actor (学生)

  • 回顾数据:

    • "开" 的优势是 +1.5 (正)。 -> 指令: 下次把 "开" 的概率从 0.6 提上去!

    • "心" 的优势是 +2.09 (大正)。-> 指令: 下次把 "心" 的概率从 0.8 狠狠提上去!

2. 修改 Critic (助教)

  • 回顾数据:

    • "开" 的时候,你预测 0.2,实际后面拿了 3.0。你太保守了!-> 指令: 下次把这里的预测值调高。

    • "心" 的时候,你预测 0.9,实际拿了 2.99。你还是太保守了!-> 指令: 调高!


总结:数据流动的全景图

把这个过程想象成一条河流:

  1. 源头 (Actor): 流出了 "开"(0.6) -> "心"(0.8)

  2. 支流 (Critic): 伴随着流出了 0.2 -> 0.9 的预测。

  3. 入海口 (Reward): 在终点 "心" 处,裁判注入了 3.0 的染料(分数)。

  4. 回流 (Backprop):

    • 3.0 的染料染红了 "心",告诉它“你很棒”。

    • 3.0 的染料逆流而上,染红了 "开",告诉它“你铺垫得好”。

  5. 河床变形 (Update): 河道(参数)被染料改变了形状,下次水流(概率)就会流向分数高的地方。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值