8 分钟阅读

简介

李宏毅老师曾以猫狗识别为例,比喻机器学习就是让机器找一个函数f,f(picture)=猫/狗。对监督学习 label = func(input),对 RL 来说,action = func(observation)。监督学习中:$f_\theta(x)=\hat y$,训练数据直接给出 $y$,因此可以计算:$L(\hat y,y)$,例如图片的 Label 是“猫”,它和模型的输出都处于同一个语义空间。RL 中,Policy 更准确地写成:$\pi_\theta(a\mid s)$,它输出的是各个动作的概率。环境返回的 Reward $r$ 却只是一个标量评价:

state s
  ↓
Policy 输出动作概率
  ↓
采样 action a
  ↓
环境返回 reward r 和下一个状态 s'

Reward 只说明“执行这个动作以后得了多少分”,没有告诉智能体:

  • 当时应该选择哪个动作;
  • Reward 是由当前动作还是之前的动作造成的;
  • 没选的其他动作是否更好;
  • 眼前扣分是否会换来未来更大的收益。

因此它不是 Action 的 Label,而是构造学习目标的原始材料。Sutton 和 Barto 对此有一组很准确的术语:

  • SL 获得的是 instructive feedback:直接告诉你正确输出。
  • RL 获得的是 evaluative feedback:只评价实际做出的行为,却不告诉你最佳动作是什么。

从神经网络训练机制看,确实非常接近:

SL:数据 → 网络 → 可微Loss → backward → 更新参数
RL:轨迹 → 回报/优势 → Surrogate Loss → backward → 更新参数

它们都使用同一套 backprop 和 optimizer。最大的差别首先来自learning signal

  1. SL:正确答案产生误差信号;
  2. RL:Reward 经 Return、Value、TD Error 或 Advantage 转换成梯度信号。此外
    1. Delayed credit assignment ,奖励可能来自很久以前的动作。
    2. Exploration 没有 Label 告诉你正确动作,必须亲自尝试才能发现。
    3. Agent-dependent data distribution,SL 通常在给定数据集上学习;RL 看到什么数据,取决于当前 Policy 做出了什么动作。Policy 一变,后续数据分布也会变。

SL 学习“输入对应什么正确输出”;RL 学习“在当前状态采取什么动作,会使未来结果更好”。Value Learning 负责把延迟评价传播成局部评分,Policy Learning 再把这种评分转换成行为。神经网络只是承载这些函数的工具。

从 Expected Return 到 Surrogate Loss

Backprop 只负责 Differentiation

不管是 backprop 还是 RL,它们的最终目的都是修改 DNN 的 parameters $\theta$。先厘清一件事:backprop 本身不是一种 learning algorithm,它的作用其实是求导(differentiation)。给定一个可微的 loss $L(\theta)$,backprop 通过 chain rule 算出 $\nabla_\theta L$,然后我们把这个 gradient 交给 optimizer(SGD、Adam)去更新 $\theta$。

在监督学习(比如 CNN)里,这个流程非常直观,因为 data 和 $\theta$ 无关——不管训练时 params 怎么变,图片本身不会变,所以我们可以直接对着固定的 dataset 做 backprop。

Expected Return 为什么不能直接 Backprop

而 RL 的目标函数是 $J(\theta) = \mathbb{E}{\tau \sim \pi\theta}[R(\tau)]$,我们想最大化策略 $\pi_\theta$ 所能 sample 到的 trajectory 的 average returns。看起来也是”算个目标、对 $\theta$ 求导、交给 optimizer”,但真要动手求导,会撞上两道监督学习里根本不存在的坎。

  1. 数据分布本身随 $\theta$ 一起动(监督学习里数据是钉死的)。把两边的目标摊开对比就清楚了。监督学习的 loss 长这样:

    \[L(\theta) = \frac{1}{N}\sum_{i=1}^{N} \ell\big(f_\theta(x_i),\, y_i\big)\]

    这里的数据 $(x_i, y_i)$ 来自一个固定的、和 $\theta$ 无关的 dataset。所以求梯度时,求和号外面那一圈样本纹丝不动,梯度只落在里面的 $f_\theta$ 上:$\nabla_\theta L = \frac{1}{N}\sum_i \nabla_\theta\, \ell\big(f_\theta(x_i), y_i\big)$。一句话——对着一批不变的题,只调整你的答题函数。

    而 RL 的目标,把期望按定义展开,其实是对所有可能的轨迹求和:

    \[J(\theta) = \sum_{\tau} P(\tau;\theta)\, R(\tau)\]

    李宏毅老师的课件把同一个目标记作 $\overline{R}_\theta$:左边是对所有可能 trajectory 的精确求和,右边是让当前 policy 实际运行 $N$ 次,用 sampled returns 的平均值近似这个期望。这张图把“目标定义在整个分布上,但训练只能依靠有限采样”表达得很直观。

    关键在于轨迹出现的概率 $P(\tau;\theta)$ 里带着 $\theta$。逻辑链路是:$\theta$ 变 → 策略 $\pi_\theta$ 变 → 每一步采的 action 变 → 环境随之给出的下一个 state 也变 → 整条轨迹 $\tau$ 的分布 $P(\tau;\theta)$ 跟着变。也就是说,你”训练数据”(采样到的轨迹)的分布,随着你优化 $\theta$ 一起在漂。这就是后面会反复出现的 on-policy 困境:上一轮采的数据,参数一更新就”过期”了。落到求导上,这一项绕不过去——你必须对 $P(\tau;\theta)$ 本身求导,而不能像监督学习那样把数据分布当常数提到求和号外面。

  2. 采样这一步不可导,链式法则在这里断了。

    就算我们下决心去对 $P(\tau;\theta)$ 求导,还有第二道坎。策略网络的实际工作方式是:forward 先算出一个动作的概率分布(比如 logits 过 softmax),然后从这个分布里”掷骰子”抽一个具体的 action $a \sim \pi_\theta(\cdot\mid s)$。(顺带一提,softmax 有平移不变性——logit 的绝对高度无意义,只有 logit 之间的差值有意义:所有 logit 同时加一个常数,$\text{softmax}$ 出来的分布完全不变。这也是常说”模型权重的绝对大小意义不大、相对值才重要”的一个来源。)

    监督学习的前向过程,从头到尾都是矩阵乘、激活函数这类可微算子的堆叠,所以 chain rule 能一路从 loss 流回每个参数。但”从分布里采样”这一步不是可微算子:它的输入是一组概率,输出是一个被随机抽中的离散动作。你把 $\theta$ 挪动一丁点,这个被抽中的动作要么不变、要么突然跳到另一个值,中间没有平滑的 $\frac{\partial a}{\partial \theta}$ 可言。形象点说,采样就像在计算图正中间插了个 np.random.choice,梯度流到这儿就断了,没法像监督学习一样直接 backprop 穿过去。

RL 真正想优化的是期望 Reward,但奖励信号通常不能直接对策略参数 $\theta$ 求导。例如 Reward 可能来自人类打分、代码测试是否通过、最终答案是否正确,这些都是计算图之外的黑盒反馈。即使 Reward 来自一个神经网络形式的 Reward Model,Reward Model 本身虽然可微,但“策略参数 $\theta$ → 离散采样 token → Reward Model 得分”这条链路仍被离散采样操作截断;而且 Reward Model 通常作为冻结的外部评估器使用,并不会把梯度直接传回 Policy。

Policy Loss 是 Surrogate Loss,而不是 Prediction Error

更专业地说,监督学习提供的是 target-based supervision(目标值监督)/ direct supervision(直接监督)。例如预测身高时,label $y=179$ 和 prediction $\hat y_\theta=180$ 位于同一个 prediction space(预测空间),单位也相同,因此可以直接定义 discrepancy。严格来说,$y-\hat y_\theta$ 是 residual(残差),再经过平方或绝对值才成为 loss,例如 $L(\theta)=(y-\hat y_\theta)^2$。label 本身不需要可微;关键是 loss 对模型输出 $\hat y_\theta$ 可微,而且这个 error signal 同时给出了“错多少”和“往哪个方向改”,梯度可以沿着 $L\rightarrow\hat y_\theta\rightarrow\theta$ 传回去。

RL 提供的则通常是 evaluative feedback(评价性反馈):action / trajectory 位于 behavior space(行为空间),Reward 位于另一个 utility space(效用空间)。Reward 不是与 action 对齐的 ground-truth target,二者不能像 $y-\hat y$ 那样直接相减;它只评价已经采样出来的行为“有多好”,并不直接说明正确 action 是什么、哪个 action 导致了结果,以及每一步应该改多少。因此 Reward 也常被称为 scalar feedback、outcome-level feedback 或 bandit feedback。把这种整体评价转换成每个 action / token 的优化信号,需要额外解决 credit assignment,并通过 policy gradient 间接完成。

关键是:Reward 对策略参数不可直接求导,但模型生成某条轨迹的概率是可微的。策略梯度不计算 $\frac{\partial R}{\partial\theta}$,而是用 Reward / Advantage 加权已采样 action 的 log-prob,从而估计期望 Reward 对模型参数的梯度。对于一条已经采样出来的固定轨迹,$R(\tau)$ 可以看作外部给定的标量;参数 $\theta$ 改变的是这条轨迹再次出现的概率 $P(\tau;\theta)$。

这一区别也解释了为什么 Policy Loss 通常不是 prediction error。RL 真正想最大化的是

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

它是策略的 true objective:数值直接表示当前策略的 expected return。但由于轨迹需要经过离散 sampling 和外部 environment 才能产生,$J(\theta)$ 不能像监督学习里的 $L_{\text{MSE}}=(y-\hat y_\theta)^2$ 那样,直接构造一条从 ground-truth target 到 model output 的可微计算图。Policy network 输出的是 action distribution,而 Reward / Advantage 是对已采样行为的 evaluative feedback;两者既不在同一个 semantic space,也不存在可以直接相减的“正确答案”。

因此,policy gradient 的首要任务不是先发明一个 loss,而是估计 $\nabla_\theta J(\theta)$。给定当前 policy 采集的一个 minibatch $\mathcal B$,所需的 gradient direction 可以估计为:

\[\hat g = \frac{1}{|\mathcal B|} \sum_{t\in\mathcal B} \nabla_\theta\log\pi_\theta(a_t\mid s_t)\hat A_t \approx \nabla_\theta J(\theta)\]

其中 $\hat A_t$ 是不参与求导的 weighting signal;在最原始的 REINFORCE 中可以直接使用 return $G_t$,加入 baseline 或 Critic 后则使用 Advantage estimate。为了让 autograd 计算出这个方向,工程上把它编码成一个可微的 scalar surrogate loss

\[\mathcal L_{\mathrm{PG}}(\theta) = -\frac{1}{|\mathcal B|} \sum_{t\in\mathcal B} \operatorname{stop\_gradient}(\hat A_t) \log\pi_\theta(a_t\mid s_t)\]

这个 loss 与目标 gradient 的关系是:

\[\nabla_\theta\mathcal L_{\mathrm{PG}}(\theta)=-\hat g, \qquad \theta \leftarrow \theta-\alpha\nabla_\theta\mathcal L_{\mathrm{PG}}(\theta) = \theta+\alpha\hat g\]

在 PyTorch 中,stop_gradient 对应 .detach()。一段最小实现是:

log_probs = policy_dist.log_prob(actions)
policy_loss = -(log_probs * advantages.detach()).mean()

optimizer.zero_grad()
policy_loss.backward()
optimizer.step()

这里的 actions 已经由 policy sampling 得到,计算图不需要穿过 sampling;log_probs 保留了 policy parameters 到已采样 action 概率的可微路径。advantages.detach() 让 Advantage 只作为 weighting signal,不让 Policy Loss 沿这条路径修改 Critic。backward() 负责计算 gradient,真正修改 parameters 的是 optimizer.step()

因此,RL 的转换顺序是:先从 expected return 推导出 policy 应该沿哪个 gradient direction 更新,再把这个方向编码成方便 autograd 计算的 surrogate loss。这里真正承接 gradient 的是 model output 的 log-prob;$\hat A_t>0$ 时,gradient descent 会提高已采样 action 再次出现的概率,$\hat A_t<0$ 时则会降低它的概率。

Policy Loss 的数值通常不表示“policy 错了多少”,单独看也未必有直观意义;它主要是让 loss.backward() 产生所需 gradient 的计算载体。这并不意味着 RL 里的 loss 可以随意构造:surrogate objective 必须有数学依据,它的 gradient 要能够估计或近似 true objective 的 gradient。

PPO-Clip 又向前走了一步。相对原始的 on-policy Policy Gradient,它有意修改 surrogate objective:超出 clipping range 的有利更新不再继续提供 gradient。这样得到的 gradient estimator 对原始 objective 一般带有 bias,但可以限制过大的 policy update,用少量 bias 换取更稳定的 optimization。

与之相对,Critic 的 Value Loss 更接近普通 regression loss:return target 和 $V_\phi(s)$ 都位于 utility space,可以用 MSE 衡量 prediction error。也就是说,同一个 Actor-Critic 系统里,Policy Loss 主要负责提供有用的 update direction,Value Loss 则确实在拟合一个 target value。

Log-Derivative Trick:构造 Score-Function Estimator

下面的 log-derivative trick(似然比技巧),就是从 true objective 推导 gradient estimator,并说明这个 surrogate loss 为什么成立。它基于一个对任意可微概率 $P$ 都成立的恒等式(来自 $\nabla_\theta \log P = \frac{\nabla_\theta P}{P}$ 这条求导链式法则的反用):

\[\nabla_\theta P(\tau;\theta) = P(\tau;\theta)\,\nabla_\theta \log P(\tau;\theta)\]

其中 $\nabla_\theta\log P(\tau;\theta)$ 称为 score function,因此这类方法也叫 score-function estimatorlikelihood-ratio estimator。$\log$ 的作用不是装饰公式:它的导数产生 $1/P(\tau;\theta)$,恰好抵消 expectation 中隐含的 $P(\tau;\theta)$,从而把“对 probability distribution 求导”改写成“在该 distribution 下求期望”。

把它代进 $\nabla_\theta J(\theta) = \sum_\tau \nabla_\theta P(\tau;\theta)\, R(\tau)$:

\[\nabla_\theta J(\theta) = \sum_\tau P(\tau;\theta)\,\nabla_\theta \log P(\tau;\theta)\, R(\tau) = \mathbb{E}_{\tau \sim \pi_\theta}\big[R(\tau)\,\nabla_\theta \log P(\tau;\theta)\big]\]

一条 trajectory 的 probability 可以进一步分解为:

\[P(\tau;\theta) = \rho_0(s_0) \prod_{t=0}^{T-1} \pi_\theta(a_t\mid s_t) P(s_{t+1}\mid s_t,a_t)\]

其中 $\rho_0$ 是 initial-state distribution,$P(s_{t+1}\mid s_t,a_t)$ 是 environment transition probability。只有 $\pi_\theta(a_t\mid s_t)$ 含有 policy parameters $\theta$,所以:

\[\nabla_\theta\log P(\tau;\theta) = \sum_{t=0}^{T-1} \nabla_\theta\log\pi_\theta(a_t\mid s_t)\]

乘积经过 $\log$ 变成求和,再对 $\theta$ 求导后,initial-state distribution 和 environment transition 都会消失,只留下由 Actor 控制的 action probability:

这也是 Policy Gradient 可以在未知 environment model 下训练的关键原因:训练仍然需要与 environment interaction 来采样 trajectory,但不需要事先知道 transition probability,也不需要让 gradient 穿过 environment。

这一步同时拆掉了上面两道坎:

  • 拆第一道坎:右边重新变回了一个”对 $\pi_\theta$ 的期望”,于是可以用采样去估计——拿当前策略实际跑出来的几条轨迹求平均,就是对这个期望的无偏估计,不必再纠结”分布在漂”。
  • 拆第二道坎:gradient 不再穿过 sampling 去计算 $\frac{\partial a_t}{\partial\theta}$,而是对已采样 action 的 log-prob 求导。这一项完全可微,可以直接交给 backprop。

把 trajectory probability 展开到每一步,并用从时刻 $t$ 开始的 return $G_t$ 做 credit assignment,就得到:

\[\nabla_\theta J(\theta) = \mathbb E_{\tau\sim\pi_\theta} \left[ \sum_t \nabla_\theta\log\pi_\theta(a_t\mid s_t)G_t \right]\]

再减去不依赖 action 的 baseline,期望 gradient 不变;把 $G_t-b(s_t)$ 写成 Advantage estimate $\hat A_t$:

\[\nabla_\theta J(\theta) = \mathbb E_{\tau\sim\pi_\theta} \left[ \sum_t \nabla_\theta\log\pi_\theta(a_t\mid s_t)\hat A_t \right]\]

这就是前面 minibatch gradient estimator 的理论来源。

REINFORCE:从 Gradient Estimator 到 Parameter Update

使用 sampled trajectories 和 $G_t$ 来近似上面的期望,就是 REINFORCE。直觉上它在干一件很朴素的事:对真正采到的 action,按照它后续带来的 return 调高或调低其 log-prob——高回报 action 以后更容易被采到,低回报 action 的概率则被压低。加入 baseline、Critic 和 GAE 后,weight 从 $G_t$ 逐步变成更低方差的 Advantage estimate $\hat A_t$,但 gradient estimator 的基本结构不变。

李宏毅老师的课件把这个过程画成“采样 trajectory → 用 return 加权其中每一步的 log-prob gradient → 更新 Actor”。图中展示的是最粗粒度的 trajectory-level 写法:同一条 trajectory 中,各 action 共享同一个 sequence-level return,因此只能提供比较粗的 credit assignment。用一句话概括:RL 先判断哪个输出更好,再提高它被采样的概率;后续算法的“花活”主要在于每一步究竟应该提高或降低多少。

监督学习可以从固定 data 上的 prediction error 直接得到 gradient;RL 则要先从 sampled interaction 中估计 gradient。REINFORCE 产生的估计值最终仍然交给和监督学习相同的 optimizer(Adam)更新 $\theta$。credit assignment、exploration 和 variance reduction 等问题,都会影响这个 gradient estimator 的质量。

karpathy

karpathyDeep Reinforcement Learning: Pong from Pixels

  1. PG(Policy Gradients) is preferred because it is end-to-end: there’s an explicit policy and a principled approach that directly optimizes the expected reward.
  2. Policy network. First, we’re going to define a policy network that implements our player (or “agent”). This network will take the state of the game and decide what we should do (move UP or DOWN). Now, the initial random W will of course cause the player to spasm on spot. So the only problem now is to find W that lead to expert play of Pong!
  3. We get 100,800 numbers (2101603) and forward our policy network,Suppose that we decide to go UP. The game might respond that we get 0 reward this time step and gives us another 100,800 numbers for the next frame. We could repeat this process for hundred timesteps before we get any non-zero reward! E.g. suppose we finally get a +1. That’s great, but how can we tell what made that happen? Was it something we did just now? Or maybe 76 frames ago? Or maybe it had something to do with frame 10 and then frame 90? And how do we figure out which of the million knobs to change and how, in order to do better in the future? We call this the credit assignment problem.
  4. we do not have the correct label in the Reinforcement Learning. Our policy network calculated probability of going UP as 30% (logprob -1.2) and DOWN as 70% (logprob -0.36). We will now sample an action from this distribution; E.g. suppose we sample DOWN, and we will execute it in the game. we can simply wait a bit and see!we do not yet know if going DOWN is good. But the critical point is that that’s okay, because we can simply wait a bit and see! For example in Pong we could wait until the end of the game, then take the reward we get (either +1 if we won or -1 if we lost), and enter that scalar as the gradient for the action we have taken (DOWN in this case).So if we fill in -1 for log probability of DOWN and do backprop we will find a gradient that discourages the network to take the DOWN action for that input in the future (and rightly so, since taking that action led to us losing the game).
  5. that’s it: we have a stochastic policy that samples actions and then actions that happen to eventually lead to good outcomes get encouraged in the future, and actions taken that lead to bad outcomes get discouraged. Also, the reward does not even need to be +1 or -1 if we win the game eventually. It can be an arbitrary measure of some kind of eventual quality.
  6. If you think through this process you’ll start to find a few funny properties. For example what if we made a good action in frame 50 (bouncing the ball back correctly), but then missed the ball in frame 150? If every single action is now labeled as bad (because we lost), wouldn’t that discourage the correct bounce on frame 50? You’re right - it would. However, when you consider the process over thousands/millions of games, then doing the first bounce correctly makes you slightly more likely to win down the road, so on average you’ll see more positive than negative updates for the correct bounce and your policy will end up doing the right thing.
  7. The approach is a fancy form of guess-and-check, where the “guess” refers to sampling rollouts from our current policy, and the “check” refers to encouraging actions that lead to good outcomes.

RL 为什么难训——样本效率与信用分配

rl最大的缺点:效率极低。模型往往要把整个任务完整跑一遍,等到最后才知道自己做得对不对。只有在这一次尝试彻底结束后,它才能收到一个简单的结果信号。想象一下,一个系统花了几十步、上百步去写代码、下棋或解题,最后得到的只是一个模糊的提示:成功还是失败。它不知道哪一步做得好,也不清楚哪一步出错,只能靠反复试验去猜。往往要重复上千次,才能从偶然的成功里提炼出一点有价值的经验。低效的根源在于,它几乎只看结果。模型在完成一项复杂任务时,无论中间经历了多少误判和偶然,只要最后成功,就会被判定为正确。它学到的不是理解,而是取巧。强化学习让模型更会迎合奖励,却未必更聪明。现实世界的目标是模糊的、多维度的,根本无法被单一的奖励函数概括。Karpathy 更看重的,是让模型在每一步中学会理解。不是完成任务后才得到结果,而是在过程中就能意识到自己哪里做得好、哪里需要调整。这需要更细致的过程监督与反思机制,让模型能像人一样边做边学。人类的智慧并非来自被奖励,而是来自对错误的体察与对过程的理解。

长程任务中的 RL

长程任务为什么难?

稀疏奖励;信用分配;探索空间爆炸

在大多数长程任务中,智能体只有在完成整个任务后才能获得奖励(比如围棋的胜负、机器人完成组装)。中间步骤的奖励$r_t=0$,策略梯度无法从零奖励中学到任何方向信号。这就是稀疏奖励问题(Sparse Reward Problem)。对比 CartPole:每保持一步杆子不倒就获得$r_t=1$,信号非常稠密。而在“组装机器人”任务中,智能体可能随机探索一百万步都碰不到一个非零奖励。形式化地说,如果一个 episode 有 $T$ 步,每步有 $A$ 个可选动作,那么随机策略碰到非零奖励的概率是$A^{-T}$。当 $T=100,\ A=4$ 时,这个概率约为$10^{-60}$ 几乎为零。稀疏奖励不等于“没有奖励”。有时奖励虽然非零但频率极低——比如在 Montezuma’s Revenge 中,通过一扇门才得 100 分,但整个游戏有 24 间房,平均需要上千步才能通过一扇门。

即使最终获得了奖励,智能体也很难判断哪一步的哪个动作对这个奖励贡献最大。一个 1000 步的 episode,最终奖励是 $+1$,那么第 37 步的动作和第 892 步的动作,谁贡献更大?这就是信用分配问题(Credit Assignment Problem),随着 horizon 增长而急剧恶化。信用分配的困难有数学上的根源:策略梯度估计的方差与有效 horizon 成正比。回顾 REINFORCE 的梯度估计:

\[\nabla_\theta J(\theta) \approx \frac{1}{N} \sum_{i=1}^{N} \sum_{t=0}^{T} \nabla_\theta \log \pi_\theta \left(a_t^{(i)} \mid s_t^{(i)}\right) \cdot \left( \sum_{t'=t}^{T} \gamma^{t'-t}r_{t'}^{(i)} \right)\]

当 $T$ 很大时,累计回报

\[G_t=\sum_{t'=t}^{T}\gamma^{t'-t}r_{t'}\]

的方差极大。前面介绍的 Actor-Critic 和 GAE(Generalized Advantage Estimation)本质上都是为了缓解信用分配问题——用价值函数来“估计”每一步的贡献,而不是直接使用高方差的累计回报。

长程任务的状态空间随着步数指数级增长。假设每步有 4 个动作可选,100 步的任务就有 $4^{100}$ 种可能的轨迹。随机探索几乎不可能碰到有意义的解。这个问题被称为探索瓶颈(Exploration Bottleneck)。探索空间爆炸与稀疏奖励形成了一个恶性循环:因为探索空间太大,随机策略几乎不可能碰到奖励;因为没有奖励信号,策略无法学到“哪些方向值得探索”。$\epsilon$-greedy 或添加高斯噪声这样的简单探索策略在短程任务中够用,但在长程任务中完全不够——它们只能探索局部邻域,无法做出“大步跳跃”式的探索。

其它

如果基座在多次采样中偶尔能生成正确轨迹(哪怕概率只有 5%),RL 就有东西可以放大;如果基座 100 次采样全错,GRPO 也无从比较

留下评论