LECTURE 07

基于值函数的强化学习:从策略迭代到 Q-Learning

如果值函数已经告诉了我们每个动作有多好,还需要单独维护一个策略网络吗?本讲把 actor 彻底删掉,只留下 critic——代价是失去了几乎所有收敛保证。

讲师:Sergey Levine UC Berkeley 原始材料:lec-7.pdf(20 页)

0. 本讲导读

上一讲的 actor-critic 算法有两个网络:一个策略网络 $\pi_\theta(a|s)$(actor),一个值函数网络 $\hat Q^\pi_\phi(s,a)$ 或 $\hat V^\pi_\phi(s)$(critic)。critic 的作用是给 actor 提供一个低方差的优势估计 $A^\pi(s,a)$,actor 再沿着策略梯度爬坡。整个流程仍然逃不开策略梯度那一套:高方差、需要小心调学习率、对分布偏移敏感。

本讲提出一个近乎挑衅的问题:既然 critic 已经知道每个动作的好坏,我们为什么还要花力气用梯度去「慢慢推」策略?直接取 $\argmax_a Q(s,a)$ 不就完了吗?这个想法一旦成立,actor 就被彻底删除,我们只需要训练一个网络,也不再需要高方差的策略梯度估计量。这就是本讲的主题:基于值函数的强化学习(value-based RL),它的代表算法叫 Q-learning。

Levine 在本讲的推进方式仍然是一条严密的动机链条,一环扣一环:

  • 删掉 actor 合法吗?——要证明「对 $A^\pi$ 取贪心(greedy)」得到的新策略 $\pi'$ 至少不比 $\pi$ 差。这就是策略改进定理(policy improvement theorem),本讲会把证明一步步写全。
  • 怎么算 $Q^\pi$?——在状态、动作都离散且不多的表格(tabular)情形下,可以用动态规划(dynamic programming, DP)直接迭代 Bellman 方程。由此得到策略迭代(policy iteration)和更简洁的值迭代(value iteration)。
  • 为什么 DP 一定收敛?——因为 Bellman 最优算子 $\mathcal{B}$ 是 $\infty$-范数下模为 $\gamma$ 的压缩映射(contraction mapping)。本讲给出完整证明,并推出误差衰减率 $\|V_k-V^\star\|_\infty\le\gamma^k\|V_0-V^\star\|_\infty$。
  • 状态空间太大怎么办?——用神经网络代替表格,得到拟合值迭代(fitted value iteration)。但它需要对每个动作「试一遍」才能算 $\max_a$,这要求我们能任意重置环境、或者知道转移模型 $p(s'|s,a)$。
  • 不知道模型怎么办?——把学习对象从 $V$ 换成 $Q$。因为 $Q(s,a)$ 的 $\max_{a'}$ 是在已经算好的函数上取最大,不需要真的去执行动作。这就是 fitted Q-iteration,进而是 Q-learning。
  • 为什么它是 off-policy 的?——因为整个更新只依赖四元组 $(s,a,r,s')$,而给定 $s$ 和 $a$ 之后转移与策略无关。于是一个装满历史数据的 replay buffer 可以被反复利用。
  • 代价是什么?——一旦离开表格情形,收敛性证明全部失效。Bellman 算子在 $\infty$-范数下压缩,而监督学习的回归投影在 $\ell_2$-范数下压缩,两个不同范数下的压缩复合起来不是压缩。本讲最后给出这个关键负面结果和一个经典发散例子。

与前后讲的关系:上一讲(actor-critic)给出了 critic 的训练方法(bootstrapped policy evaluation),本讲把它推到极致;下一讲(Q-Learning 的工程实践)会告诉你,本讲末尾那个「看起来很干净」的算法如果照着直接写代码,几乎必然不 work——需要 replay buffer、target network、double Q-learning 等一整套工程手段才能救活。用 Levine 自己的话说:「If you try to code this up, it almost certainly won't work.」

核心结论
  • 策略改进定理:令 $\pi'(a|s)=\mathbb{1}[a=\argmax_{a}A^\pi(s,a)]$,则对一切 $s$ 有 $V^{\pi'}(s)\ge V^\pi(s)$。所以「取贪心」永远安全,无需策略梯度。
  • 值迭代把策略迭代里的「策略评估 + 策略改进」压缩成一步:$V(s)\leftarrow\max_a\big(r(s,a)+\gamma\E_{s'}[V(s')]\big)$。$\max$ 本身就隐含了贪心改进,策略不必显式存在。
  • Bellman 最优算子是 $\gamma$-压缩($\infty$-范数),故有唯一不动点 $V^\star$,且 $\|V_k-V^\star\|_\infty\le\gamma^k\|V_0-V^\star\|_\infty$,线性收敛。
  • 为什么必须学 $Q$ 而不是 $V$:$\max_a\big(r(s,a)+\gamma\E[V(s')]\big)$ 需要模型或可重置的模拟器;$\max_{a'}Q(s',a')$ 只是查表/前向传播,不需要真的执行动作。
  • Q-learning 是 off-policy 的:更新只用 $(s,a,r,s')$,给定 $(s,a)$ 后 $s'$ 的分布与行为策略无关,且目标里的 $\max_{a'}$ 已经代表了新策略 $\pi'$。数据可以来自任何策略、任何时候。
  • 探索必须显式加入:贪心策略是确定性的,在线采集时会卡死在局部。实践中用 $\epsilon$-greedy 或 Boltzmann 探索。
  • 负面结果:拟合值迭代 = Bellman 备份($\infty$-范数压缩) + 回归投影($\ell_2$-范数压缩),复合算子在任何范数下都不是压缩,可以构造出发散的例子。actor-critic 的 bootstrapped policy evaluation 有同样的问题。

1. 先看结论:把 actor-critic 里的 actor 删掉

本讲的第一部分标题就叫 "Actor-critic without the actor"。Levine 的教学策略是先把答案摆出来,再回头解释为什么它是对的。我们也照做。

1.1 复习:带 replay buffer 的 off-policy actor-critic

上一讲末尾给出的 off-policy actor-critic 长这样($\theta$ 是策略参数,$\phi$ 是 critic 参数):

  1. 用当前策略 $a\sim\pi_\theta(a|s)$ 与环境交互一步,得到 $(s_i,a_i,r_i,s_i')$,存入 replay buffer;
  2. 从 buffer 里取一个 batch $\{(s_i,a_i,s_i')\}_{i=1}^B$,计算回归目标 $$ y_i=r(s_i,a_i)+\gamma\,\E_{a'\sim\pi_\theta(a'|s_i')}\big[\hat Q^\pi_\phi(s_i',a')\big]; $$
  3. 用 $\nabla_\phi\sum_{i=1}^B\|\hat Q^\pi_\phi(s_i,a_i)-y_i\|^2$ 更新 critic 参数 $\phi$;
  4. 用策略梯度 $\nabla_\theta J(\theta)\approx\sum_i\E_{a\sim\pi_\theta(a|s_i)}\big[\nabla_\theta\log\pi_\theta(a|s_i)\hat Q^\pi_\phi(s_i,a)\big]$ 更新 actor;
  5. $\theta\leftarrow\theta+\alpha\nabla_\theta J(\theta)$,回到第 1 步。

注意第 2 步里的期望 $\E_{a'\sim\pi_\theta}$:因为 buffer 里的 $s_i'$ 的后续动作是旧策略选的,不能直接用 buffer 里记录的下一动作,必须重新从当前 $\pi_\theta$ 采样 $a'$ 再查 critic。这一步是 off-policy 修正的关键。

带 replay buffer 的 off-policy actor-critic,以及把期望换成 max 的「有趣想法」
上半部分是上一讲的 off-policy actor-critic 五步,右侧箭头表示每一步交互产生的 $(s_i,a_i,s_i')$ 被写进 replay buffer,训练时再从中取 batch。红线划掉的是第 4、5 步——也就是 actor 的策略梯度更新,本讲要把它们整个删除。下半部分给出替换方案:把目标里的 $\gamma\E_{a'\sim\pi_\theta}[\hat Q(s_i',a')]$ 换成 $\gamma\max_{a'}\hat Q(s_i',a')$。右下角的「a funny idea」写出了理由:如果我们把策略定义成对 $\hat Q$ 取 $\argmax$ 的确定性策略(是则概率 1,否则 0),那么在这个策略下求期望本来就等于取最大值——期望和 $\max$ 是同一回事,于是 actor 完全不必显式存在。

1.2 那个「有趣的想法」

假设我们不再让策略是一个独立的神经网络,而是由 critic 直接定义:

$$ \pi_\theta(a|s)=\begin{cases}1 & \text{if } a=\argmax_{a}\hat Q^\pi_\phi(s,a)\\ 0 & \text{otherwise}\end{cases} $$

这是一个确定性(deterministic)策略。把它代入第 2 步的期望里:

$$ \E_{a'\sim\pi_\theta(a'|s_i')}\big[\hat Q^\pi_\phi(s_i',a')\big]=\hat Q^\pi_\phi\big(s_i',\argmax_{a'}\hat Q^\pi_\phi(s_i',a')\big)=\max_{a'}\hat Q^\pi_\phi(s_i',a') $$

期望塌缩成了一个 $\max$。于是第 2 步变成

$$ y_i=r(s_i,a_i)+\gamma\max_{a'}Q_\theta(s_i',a') $$

(这里起把 critic 的参数重新记作 $\theta$,因为它现在是唯一的网络了。)第 4、5 步——策略梯度和 actor 更新——整个消失,因为策略不再有自己的参数。

删掉 actor 之后得到的三步算法:带 replay buffer 的 Q-learning
删掉 actor 之后剩下的算法只有三步:(1) 用当前(由 $Q_\theta$ 导出的)策略走一步,得到 $(s_i,a_i,s_i')$ 存入 replay buffer;(2) 从 buffer 取 batch,算目标 $y_i=r(s_i,a_i)+\gamma\max_{a'}Q_\theta(s_i',a')$;(3) 用 $\nabla_\theta\sum_i\|Q_\theta(s_i,a_i)-y_i\|^2$ 做一步回归。左下角是策略的定义:对 $Q_\theta$ 取 $\argmax$ 的确定性策略。右下角画的是这个唯一的网络——输入 $(s,a)$、输出标量 $Q_\theta(s,a)$、参数 $\theta$。两条黄色标注是 Levine 的原话:「我们其实可以就停在这里」(算法已经完整了),「但多理解一些会很有帮助」——接下来四节就是补上这个「为什么」。
核心结论

整个 Q-learning 就是上面三行。剩下的四节要回答的是三个「凭什么」:凭什么可以直接取 $\argmax$ 而不用梯度上升(第 2 节,策略改进定理);凭什么这个迭代会收敛(第 3–4 节,压缩映射);凭什么可以用任意来源的数据(第 6 节,off-policy 性质)。以及一个「凭什么不」:凭什么这一切在神经网络下全部失效(第 8 节)。

2. 策略迭代与贪心策略改进定理

要证明「删掉 actor 是合法的」,先要把这个想法放回一个更古老、更干净的框架里:策略迭代(policy iteration)。它是动态规划时代(Bellman、Howard,1950–60 年代)就有的算法,只有两步:

策略迭代算法
  1. 策略评估(policy evaluation):算出当前策略的 $Q^\pi(s,a)$;
  2. 策略改进(policy improvement):令 $\pi\leftarrow\pi'$,其中 $$ \pi'(a_t|s_t)=\begin{cases}1 & \text{if } a_t=\argmax_{a_t}Q^\pi(s_t,a_t)\\ 0 & \text{otherwise}\end{cases} $$

重复直到策略不再变化。

策略迭代的两步,以及它在「采样—拟合—改进」三步循环图上的位置
左侧是策略迭代的两步:第 1 步「evaluate $Q^\pi(s,a)$」被打了个问号——「how to do this?」,这是接下来两节要解决的;第 2 步的 $\pi'$ 就是对 $Q^\pi$ 取 $\argmax$ 的确定性策略。下方两行提示了评估 $Q^\pi$ 的路径:由定义 $Q^\pi(s,a)=r(s,a)+\gamma\E[V^\pi(s')]$,只要能评估 $V^\pi$ 就能得到 $Q^\pi$,所以问题归约为「评估 $V^\pi(s)$」。右侧是本课程贯穿始终的三步循环图:橙色「generate samples」(跑策略采数据)、绿色「fit a model to estimate return」(这里就是拟合 $Q^\pi$ 或 $V^\pi$)、蓝色「improve the policy」(这里就是 $\pi\leftarrow\pi'$)。策略迭代把绿色盒子做成「精确的策略评估」,把蓝色盒子做成「取 $\argmax$」——蓝色盒子里没有任何梯度、没有任何学习率。

2.1 为什么第 2 步是安全的:策略改进定理

第 2 步看起来很暴力:直接跳到贪心策略,步子迈这么大不会翻车吗?策略梯度之所以要用小学习率,正是怕迈太大步。但对贪心改进,我们有一个无条件的保证。

先定义优势函数(advantage function):

$$ A^\pi(s,a)=Q^\pi(s,a)-V^\pi(s)=r(s,a)+\gamma\E_{s'\sim p(s'|s,a)}[V^\pi(s')]-V^\pi(s) $$

它衡量「在状态 $s$ 先强制执行动作 $a$、之后一直按 $\pi$ 走」相比「一开始就按 $\pi$ 走」多赚了多少。注意 $\argmax_a A^\pi(s,a)=\argmax_a Q^\pi(s,a)$,因为 $V^\pi(s)$ 与 $a$ 无关,减掉一个常数不改变 $\argmax$。所以「对 $A^\pi$ 贪心」和「对 $Q^\pi$ 贪心」是同一件事。

推导:策略改进定理(Policy Improvement Theorem)

命题. 设 $\pi'$ 是对 $A^\pi$(等价地对 $Q^\pi$)取贪心得到的确定性策略,即 $\pi'(s)=\argmax_a A^\pi(s,a)$。则对一切状态 $s$ 有 $$ V^{\pi'}(s)\ \ge\ V^\pi(s). $$

第一步:贪心保证单步不变差。由 $\pi'$ 的定义,对任意 $s$: $$ A^\pi(s,\pi'(s))=\max_a A^\pi(s,a)\ \ge\ \E_{a\sim\pi(a|s)}[A^\pi(s,a)]=0 $$ 最后一个等号是因为 $\E_{a\sim\pi}[A^\pi(s,a)]=\E_{a\sim\pi}[Q^\pi(s,a)]-V^\pi(s)=V^\pi(s)-V^\pi(s)=0$:优势函数在自己的策略下期望为零。所以贪心动作的优势必然 $\ge 0$。写开就是 $$ Q^\pi(s,\pi'(s))\ \ge\ V^\pi(s).\qquad(\ast) $$

第二步:把 $(\ast)$ 沿时间反复展开。从任意 $s_0=s$ 出发: $$ V^\pi(s_0)\ \le\ Q^\pi(s_0,\pi'(s_0))=r(s_0,\pi'(s_0))+\gamma\,\E_{s_1\sim p(\cdot|s_0,\pi'(s_0))}\big[V^\pi(s_1)\big] $$ 再对括号里的 $V^\pi(s_1)$ 用一次 $(\ast)$:$V^\pi(s_1)\le Q^\pi(s_1,\pi'(s_1))=r(s_1,\pi'(s_1))+\gamma\E[V^\pi(s_2)]$。代回去: $$ V^\pi(s_0)\ \le\ \E_{\pi'}\Big[r(s_0,a_0)+\gamma r(s_1,a_1)+\gamma^2 V^\pi(s_2)\Big] $$ 其中 $\E_{\pi'}$ 表示动作由 $\pi'$ 产生、状态由环境转移产生。归纳地重复 $T$ 次: $$ V^\pi(s_0)\ \le\ \E_{\pi'}\Big[\sum_{t=0}^{T-1}\gamma^t r(s_t,a_t)\Big]+\gamma^{T}\E_{\pi'}\big[V^\pi(s_T)\big] $$

第三步:取极限。若奖励有界 $|r|\le R_{\max}$,则 $|V^\pi|\le R_{\max}/(1-\gamma)$,于是当 $\gamma\lt 1$ 时 $\gamma^{T}\E[V^\pi(s_T)]\to 0$。而前一项收敛到 $V^{\pi'}(s_0)$。因此 $$ V^\pi(s_0)\ \le\ V^{\pi'}(s_0)\quad\text{对一切 } s_0. \qquad\blacksquare $$

2.2 这个证明说明了什么

这个定理的力量在于它的无条件性:只要 $Q^\pi$ 算得准,贪心一步永远不会变差,不管步子有多「大」。对比策略梯度——那里我们必须小心翼翼地选步长,因为大步长会让新策略跑到旧数据覆盖不到的地方、让线性近似失效。这里没有这个问题,因为我们不是在做局部线性近似,而是用整个 $Q^\pi$ 函数(它已经包含了未来所有影响)来决策。

直觉

为什么「$\E_{a\sim\pi}[A^\pi(s,a)]=0$」这么关键?它说明:在旧策略自己看来,它的所有动作平均是「不好不坏」的。所以只要挑出其中优势最大的那个(一定 $\ge$ 平均值 $=0$),第一步就至少不亏。而第二步的展开告诉我们,「每一步都不亏」通过折扣求和累积起来,最终整条轨迹的期望回报也不亏。
换句话说:局部贪心 + 值函数正确 = 全局不变差。值函数把「未来」打包进了一个标量,所以短视的选择反而是全局最优的——这正是动态规划的核心思想。

常见误区

「贪心一定不变差」的前提是 $Q^\pi$ 是精确的。如果 $Q^\pi$ 有估计误差 $\varepsilon=\max_{s,a}|\hat Q^\pi(s,a)-Q^\pi(s,a)|$,那么贪心策略的性能损失可以被界为 $$ V^{\pi'}(s)\ \ge\ V^{\pi}(s)-\frac{2\gamma\varepsilon}{1-\gamma} $$ 分母上的 $1-\gamma$ 意味着误差会被 $1/(1-\gamma)$ 放大:$\gamma=0.99$ 时放大约 100 倍。这就是为什么后面用神经网络近似 $Q$ 时,一点点系统性的高估就足以让策略彻底跑偏——第 8 节和下一讲的 double Q-learning 都在处理这件事。

3. 动态规划:如何精确地评估 $V^\pi$

策略迭代的第 1 步「evaluate $Q^\pi$」还欠着。本节在最理想的假设下把它做掉:我们知道转移概率 $p(s'|s,a)$,且状态 $s$ 与动作 $a$ 都是离散且数量很少的。这个设定叫 tabular(表格)情形。

表格情形下的动态规划:bootstrapped 更新与确定性策略的化简
顶部写明假设:已知 $p(s'|s,a)$,$s$ 和 $a$ 都离散且规模小。左上角的 4×4 网格是一个 16 状态、每状态 4 个动作的玩具环境(例如格子世界),格子里的数字 0.2/0.3/0.4/… 就是当前对 $V^\pi(s)$ 的估计——整个值函数就是一张 16 个数的表。转移张量 $\mathcal{T}$ 的形状是 $16\times16\times4$(当前状态 × 下一状态 × 动作),完全可以显式存下来。中间是 bootstrapped 更新式 $V^\pi(s)\leftarrow\E_{a\sim\pi}[r(s,a)+\gamma\E_{s'}[V^\pi(s')]]$,向上的箭头指着等号右边的 $V^\pi(s')$,标注写着「just use the current estimate here」——这就是自举(bootstrapping):用当前这张表里的旧估计,去更新这张表,而不是等一整条轨迹跑完。底部两行:因为策略迭代产生的 $\pi'$ 是确定性的($\pi(s)=a$),外层对 $a$ 的期望可以直接去掉,更新式简化成 $V^\pi(s)\leftarrow r(s,\pi(s))+\gamma\E_{s'\sim p(s'|s,\pi(s))}[V^\pi(s')]$。

3.1 表格值函数与 bootstrapped 更新

在表格情形下,$V^\pi$ 就是一个长度为 $|\mathcal{S}|$ 的数组。策略评估的更新规则直接来自 Bellman 期望方程:

$$ V^\pi(s)\ \leftarrow\ \E_{a\sim\pi(a|s)}\Big[r(s,a)+\gamma\,\E_{s'\sim p(s'|s,a)}\big[V^\pi(s')\big]\Big] $$

右边用的是当前这张表的值,算完之后写回左边。反复扫描所有状态,这张表就会收敛到真正的 $V^\pi$(第 4 节证明)。

如果策略是确定性的——策略迭代产生的贪心策略正是如此,记 $\pi(s)=a$——外层期望消失:

$$ V^\pi(s)\ \leftarrow\ r(s,\pi(s))+\gamma\,\E_{s'\sim p(s'|s,\pi(s))}\big[V^\pi(s')\big] $$

这就是策略评估的最终形式:一次全表扫描的代价是 $O(|\mathcal{S}|^2)$(每个状态要对所有可能的 $s'$ 求和)。

直觉:一个 $\gamma=0.9$ 的两状态例子

设两个状态 $s_A,s_B$,策略确定。$r(s_A)=0$,从 $s_A$ 必然转移到 $s_B$;$r(s_B)=1$,从 $s_B$ 必然自环。初始化 $V_0(s_A)=V_0(s_B)=0$。
第 1 轮:$V_1(s_B)=1+0.9\cdot 0=1$,$V_1(s_A)=0+0.9\cdot 0=0$。
第 2 轮:$V_2(s_B)=1+0.9\cdot 1=1.9$,$V_2(s_A)=0+0.9\cdot 1=0.9$。
第 3 轮:$V_3(s_B)=1+0.9\cdot1.9=2.71$,$V_3(s_A)=0.9\cdot1.9=1.71$。
真值是 $V^\pi(s_B)=1/(1-0.9)=10$,$V^\pi(s_A)=0.9\times10=9$。可以看到误差每轮乘以 $0.9$:第 1 轮误差 9,第 2 轮 8.1,第 3 轮 7.29……这就是下一节要证的 $\gamma^k$ 衰减。$\gamma$ 越接近 1,收敛越慢——这是折扣因子的根本代价。

3.2 拼装成策略迭代

用动态规划实现的完整策略迭代:内层评估循环 + 外层改进循环
这一页把两块拼在一起,形成完整的表格策略迭代。左上是外层循环(策略迭代):1. 评估 $V^\pi(s)$;2. $\pi\leftarrow\pi'$,其中 $\pi'$ 是对 $Q^\pi$ 取 $\argmax$ 的确定性策略。左下是内层循环(策略评估):反复执行 $V^\pi(s)\leftarrow r(s,\pi(s))+\gamma\E_{s'}[V^\pi(s')]$ 直到收敛,绿色回环箭头表示这一步本身要迭代多次。那条从「policy evaluation」拉回到「1. evaluate $V^\pi(s)$」的长弧线,说明内层循环的输出正是外层第 1 步所需的东西。右侧的三步循环图上标着「estimate $V^\pi$」——绿盒子被具体化为「跑内层 DP 循环」;蓝盒子被具体化为 $\pi\leftarrow\pi'$。左下角重复了 16 状态玩具环境,提醒这一切只在表格规模下可行。

注意这里的双层循环结构:外层每改进一次策略,内层就要把值函数评估到收敛。这很浪费——策略只要变一点,值函数就得重算。有没有办法把两层合成一层?有,而且合并之后算法反而更简单。

3.3 值迭代:把 argmax 吸收进 max

值迭代:跳过策略,直接计算值函数
左上仍是贪心策略 $\pi'$ 的定义,但下方写着关键的转折:「skip the policy and compute values directly!」(跳过策略,直接算值)。右上是 $Q^\pi$ 的表格表示——一个 $|\mathcal{S}|\times|\mathcal{A}|$ 的矩阵,行是状态、列是动作,每格存一个 $Q(s,a)$;黄色高亮的格子表示每一行里被 $\argmax$ 选中的那个动作。右上角的更新式 $Q^\pi(s,a)\leftarrow r(s,a)+\gamma\E_{s'}[V^\pi(s')]$ 说明如何从 $V$ 得到 $Q$。中间被红圈圈出的是 $\max_a Q(s,a)$(在 $\argmax_a Q(s,a)$ 里),向下的箭头标注「approximates the new value!」——取最大值这个操作本身,就等于「先做贪心改进,再评估新策略一步」。右侧循环图的蓝盒子下方因此写成 $V^\pi(s)\leftarrow\max_a Q^\pi(s,a)$:策略改进这一步不再产生一个策略对象,而是直接产生新的值。左下角是最终的值迭代算法:1. $Q(s,a)\leftarrow r(s,a)+\gamma\E[V(s')]$;2. $V(s)\leftarrow\max_a Q(s,a)$。

推理是这样的:策略改进后的新策略 $\pi'$ 在状态 $s$ 处的值是多少?如果我们只往前看一步、后面仍用旧的 $V^\pi$ 近似,那就是

$$ V^{\pi'}(s)\ \approx\ Q^\pi(s,\pi'(s))=\max_a Q^\pi(s,a) $$

也就是说,$\max_a Q^\pi(s,a)$ 已经是「改进后策略的值」的一个估计。既然如此,我们根本不需要显式地把 $\pi'$ 写出来再拿去评估——直接把 $\max$ 写进值函数的更新里就行了。于是得到

值迭代算法(Value Iteration)
  1. $Q(s,a)\ \leftarrow\ r(s,a)+\gamma\,\E_{s'\sim p(s'|s,a)}[V(s')]$
  2. $V(s)\ \leftarrow\ \max_a Q(s,a)$

把两步合并写成一步,就是 Bellman 最优方程的迭代形式: $$ V_{k+1}(s)\ \leftarrow\ \max_a\Big(r(s,a)+\gamma\,\E_{s'\sim p(s'|s,a)}\big[V_k(s')\big]\Big) $$

整个算法里没有出现过策略。策略只在最后需要行动时才被导出:$\pi(s)=\argmax_a Q(s,a)$。这正是本讲标题「value-based RL」的含义——策略是值函数的副产品,而不是一个需要单独训练的对象。

策略迭代值迭代
循环结构双层:外层改进,内层评估到收敛单层:评估与改进合并成一次 $\max$ 备份
每轮代价内层多次全表扫描 + 一次 $\argmax$一次全表扫描(含 $\max$)
显式策略有,每轮维护一个 $\pi$没有,最后才导出
收敛所需轮数通常很少(策略空间有限,最多 $|\mathcal{A}|^{|\mathcal{S}|}$ 轮,实际远小于此)较多,但每轮更便宜;误差按 $\gamma^k$ 衰减
是否严格单调是(策略改进定理保证)值单调收敛到 $V^\star$(若从 $V_0\le V^\star$ 出发则单调上升)

4. 为什么值迭代一定收敛:Bellman 算子是 $\gamma$-压缩映射

上一节给出了值迭代的更新式,但没说它为什么会收敛、收敛到哪里、收敛多快。这一节把这三个问题一次性解决。这是全课少数几个「有干净理论保证」的地方,也正因为如此,第 8 节的负面结果才显得刺眼。

4.1 把更新写成算子

把值函数 $V$ 看成 $\R^{|\mathcal{S}|}$ 里的一个向量(表格情形下它确实就是一个向量)。定义 Bellman 最优算子(Bellman optimality operator) $\mathcal{B}:\R^{|\mathcal{S}|}\to\R^{|\mathcal{S}|}$:

$$ (\mathcal{B}V)(s)\ =\ \max_a\Big(r(s,a)+\gamma\sum_{s'}p(s'|s,a)V(s')\Big) $$

用矩阵记号写更紧凑:设 $\mathcal{T}_a$ 是动作 $a$ 对应的转移矩阵(第 $(s,s')$ 元为 $p(s'|s,a)$),$r_a$ 是奖励向量,则

$$ \mathcal{B}V=\max_a\big(r_a+\gamma\,\mathcal{T}_a V\big) $$

这里的 $\max$ 是逐状态(elementwise)取的:每个状态可以选不同的 $a$。值迭代就是简单地反复施加这个算子:$V_{k+1}=\mathcal{B}V_k$。

关键事实一:最优值函数 $V^\star$ 是 $\mathcal{B}$ 的不动点,即 $\mathcal{B}V^\star=V^\star$。这直接来自 Bellman 最优方程 $V^\star(s)=\max_a\big(r(s,a)+\gamma\E_{s'}[V^\star(s')]\big)$,而后者是「最优策略必然在每一步选最优动作」的直接表述。

4.2 压缩映射的定义

回忆度量空间上的压缩映射:若存在 $\gamma\in[0,1)$ 使得对任意 $V,\bar V$ 都有 $\|\mathcal{B}V-\mathcal{B}\bar V\|\le\gamma\|V-\bar V\|$,则 $\mathcal{B}$ 称为模为 $\gamma$ 的压缩映射。Banach 不动点定理告诉我们:完备度量空间上的压缩映射有唯一不动点,且从任意起点反复迭代都收敛到它,收敛速率是几何级数。

这里用的范数是 $\infty$-范数(无穷范数 / 最大范数):

$$ \|V-\bar V\|_\infty=\max_{s}\big|V(s)-\bar V(s)\big| $$

也就是「所有状态上误差的最大值」。范数的选择在这里至关重要,第 8 节的负面结果就出在这一点上。

推导:$\mathcal{B}$ 是 $\infty$-范数下的 $\gamma$-压缩

命题. 对任意两个值函数 $V,\bar V$, $$ \|\mathcal{B}V-\mathcal{B}\bar V\|_\infty\ \le\ \gamma\,\|V-\bar V\|_\infty . $$

引理(max 的差不超过差的 max). 对任意两个实值函数 $f,g$ 定义在同一有限集上, $$ \Big|\max_a f(a)-\max_a g(a)\Big|\ \le\ \max_a\big|f(a)-g(a)\big| $$ 证明:设 $a_f=\argmax_a f(a)$。则 $$ \max_a f(a)-\max_a g(a)=f(a_f)-\max_a g(a)\le f(a_f)-g(a_f)\le\max_a|f(a)-g(a)| $$ (第一个不等号用了 $\max_a g(a)\ge g(a_f)$。)交换 $f,g$ 的角色得到另一方向的不等式,合起来即得引理。$\square$

主证明. 固定任意状态 $s$。令 $f(a)=r(s,a)+\gamma\sum_{s'}p(s'|s,a)V(s')$,$g(a)=r(s,a)+\gamma\sum_{s'}p(s'|s,a)\bar V(s')$。由引理, $$ \big|(\mathcal{B}V)(s)-(\mathcal{B}\bar V)(s)\big|=\Big|\max_a f(a)-\max_a g(a)\Big|\le\max_a\big|f(a)-g(a)\big| $$ 而奖励项相消: $$ |f(a)-g(a)|=\gamma\Big|\sum_{s'}p(s'|s,a)\big(V(s')-\bar V(s')\big)\Big|\le\gamma\sum_{s'}p(s'|s,a)\big|V(s')-\bar V(s')\big| $$ 这里用了三角不等式和 $p\ge 0$。再把每一项的绝对值放大到最大值: $$ \le\gamma\sum_{s'}p(s'|s,a)\cdot\|V-\bar V\|_\infty=\gamma\,\|V-\bar V\|_\infty $$ 最后一个等号用了 $\sum_{s'}p(s'|s,a)=1$——概率归一化是整个证明的技术核心:转移矩阵是随机矩阵,它在 $\infty$-范数下的诱导范数恰好等于 $1$,所以只把误差「搬运」而不放大,剩下的 $\gamma$ 就是纯粹的收缩因子。
由于上式对每个 $a$ 一致成立,也对每个 $s$ 一致成立,取 $s$ 上的最大值即得 $$ \|\mathcal{B}V-\mathcal{B}\bar V\|_\infty\le\gamma\|V-\bar V\|_\infty.\qquad\blacksquare $$

4.3 直接推论:收敛速率

把 $\bar V$ 取成 $V^\star$,利用 $\mathcal{B}V^\star=V^\star$:

$$ \|V_{k+1}-V^\star\|_\infty=\|\mathcal{B}V_k-\mathcal{B}V^\star\|_\infty\le\gamma\|V_k-V^\star\|_\infty $$

归纳下去:

$$ \boxed{\ \|V_k-V^\star\|_\infty\ \le\ \gamma^k\,\|V_0-V^\star\|_\infty\ } $$

这就是值迭代的线性(几何)收敛。同时,压缩性保证不动点唯一,所以 $V^\star$ 是值迭代唯一可能的极限——不存在「收敛到别的东西」的风险。

直觉:$\gamma$ 到底控制了什么

把 $\gamma^k\le\epsilon$ 解出来:$k\ge\dfrac{\log(1/\epsilon)}{\log(1/\gamma)}\approx\dfrac{\log(1/\epsilon)}{1-\gamma}$。所以达到给定精度所需的迭代次数正比于 有效视界(effective horizon)$1/(1-\gamma)$。
具体数字:$\gamma=0.9$ 时有效视界 10,把误差压到 $1\%$ 需要约 44 轮;$\gamma=0.99$ 时有效视界 100,需要约 458 轮;$\gamma=0.999$ 时需要约 4600 轮。折扣因子越接近 1,问题越「长视」,DP 越慢。这也解释了为什么实践中很少用 $\gamma\gt 0.999$:不仅慢,误差放大因子 $1/(1-\gamma)$ 也会让任何近似误差被放大上千倍。

注意

同样的证明几乎一字不改地适用于策略评估算子 $\mathcal{B}^\pi V=r_\pi+\gamma\mathcal{T}_\pi V$(把 $\max_a$ 换成对 $\pi$ 求期望,引理换成「期望的差不超过差的最大值」即可)。所以策略评估内层循环也是 $\gamma$-压缩,收敛到 $V^\pi$。$\mathcal{B}$ 和 $\mathcal{B}^\pi$ 的唯一区别是前者带 $\max$(非线性)、后者是仿射(线性)——这个差别在下面会变得重要:$\mathcal{B}^\pi$ 的不动点可以直接解线性方程组 $V^\pi=(I-\gamma\mathcal{T}_\pi)^{-1}r_\pi$,而 $\mathcal{B}$ 因为有 $\max$ 只能迭代。

下面这段代码把表格值迭代完整跑一遍,并打印出误差的 $\gamma^k$ 衰减:

import numpy as np

def value_iteration(P, R, gamma=0.9, tol=1e-10, max_iter=10000):
    """P: [S, A, S] 转移概率; R: [S, A] 即时奖励。返回 V*, Q*, 贪心策略。"""
    S, A, _ = P.shape
    V = np.zeros(S)
    for k in range(max_iter):
        # Bellman 备份: Q[s,a] = R[s,a] + gamma * sum_s' P[s,a,s'] V[s']
        Q = R + gamma * P.dot(V)          # [S, A]
        V_new = Q.max(axis=1)             # 逐状态取 max ——这一步同时完成了策略改进
        delta = np.abs(V_new - V).max()   # 无穷范数下的变化量
        V = V_new
        if delta < tol:
            break
    Q = R + gamma * P.dot(V)
    return V, Q, Q.argmax(axis=1)

# 一个 3 状态、2 动作的小例子:动作 0 原地不动,动作 1 向右走
S, A = 3, 2
P = np.zeros((S, A, S))
for s in range(S):
    P[s, 0, s] = 1.0                      # 动作 0:停留
    P[s, 1, min(s + 1, S - 1)] = 1.0      # 动作 1:右移,末状态吸收
R = np.zeros((S, A))
R[S - 1, :] = 1.0                         # 只有到达最后一个状态才有奖励

V, Q, pi = value_iteration(P, R, gamma=0.9)
print(V)    # [8.1  9.   10. ]  —— 末状态 1/(1-0.9)=10,每退一格乘 0.9
print(pi)   # [1 1 0 或 1]      —— 前两个状态都应该向右走

输出验证了理论:末状态自环拿常奖励 1,值为 $1/(1-0.9)=10$;往前每退一步乘 $\gamma=0.9$,得到 $9$ 和 $8.1$。贪心策略在前两个状态都选「向右」。

5. 拟合值迭代:把表格换成神经网络

前面所有结论都建立在「表格」这个假设上。现实中这个假设几乎总是不成立。

5.1 维度灾难

值函数用表格存储,需要为每个离散状态开一个格子。状态数随维度指数增长:如果状态是 $n$ 维、每维离散成 $K$ 档,表格大小是 $K^n$。Levine 举的例子是从像素学开车:一张 $200\times200$ 的 RGB 图像,每个像素每通道 256 个取值,状态空间大小是

$$ |\mathcal{S}|=(255^3)^{200\times200} $$

这个数字远远超过可观测宇宙中的原子总数(约 $10^{80}$)。别说存表,连枚举一遍都不可能。

拟合值迭代:用神经网络表示 V,回归到 Bellman 备份目标
左上问「how do we represent $V(s)$?」,给出两条路:一是大表格(每个离散 $s$ 一个格子,中上方列出的 $s=0:V=0.2$、$s=1:V=0.3$、$s=2:V=0.5$ 就是表格形式);二是神经网络函数 $V:\mathcal{S}\to\R$,画的网络输入状态 $s$、输出标量 $V(s)$、参数 $\theta$。中间的赛车游戏截图配上 $|\mathcal{S}|=(255^3)^{200\times200}$("more than atoms in the universe")和红字「curse of dimensionality」,说明表格路线在图像观测下彻底不可行。左下的损失函数 $\mathcal{L}(\theta)=\frac12\|V_\theta(s)-\max_a Q^\pi(s,a)\|^2$ 是关键:我们把「值迭代的更新」变成了「一个回归问题」——目标值 $\max_a Q^\pi(s,a)$ 用当前网络算出来,然后让网络去拟合它。最下方是完整的拟合值迭代算法:1. $y_i\leftarrow\max_{a_i}\big(r(s_i,a_i)+\gamma\E[V_\theta(s_i')]\big)$;2. $\theta\leftarrow\argmin_\theta\frac12\sum_i\|V_\theta(s_i)-y_i\|^2$。右侧循环图的蓝盒子仍写着 $V^\pi(s)\leftarrow\max_a Q^\pi(s,a)$。

5.2 用回归代替赋值

解决办法很自然:用一个参数化函数 $V_\theta:\mathcal{S}\to\R$(比如神经网络)代替表格。但表格更新是「把新值写进格子」,神经网络没有格子可写——只能用梯度下降去逼近。于是「赋值」变成「回归」:

$$ \mathcal{L}(\theta)=\frac12\Big\|V_\theta(s)-\max_a Q^\pi(s,a)\Big\|^2 $$
拟合值迭代算法(Fitted Value Iteration)
  1. 对采样到的每个状态 $s_i$,计算回归目标 $$ y_i\ \leftarrow\ \max_{a_i}\Big(r(s_i,a_i)+\gamma\,\E\big[V_\theta(s_i')\big]\Big) $$
  2. 做一次(或若干次)监督回归 $$ \theta\ \leftarrow\ \argmin_\theta\ \frac12\sum_i\big\|V_\theta(s_i)-y_i\big\|^2 $$

重复。注意第 1 步里的 $V_\theta$ 用的是更新前的参数——又一次自举。

这个算法的形式很讨喜:第 1 步是纯粹的数值计算,第 2 步是一个标准的监督学习问题,可以直接扔给 PyTorch。函数逼近还带来了泛化:网络在见过的 $s_i$ 上学到的值会推广到没见过的相似状态,这是表格永远做不到的。

注意:这里悄悄付出了代价

表格值迭代每一轮做的是「精确的 Bellman 备份」;拟合值迭代做的是「Bellman 备份 再加一次回归投影」。回归不可能完美——网络容量有限、样本有限、优化不到全局最优。多出来的这一步投影,正是第 8 节所有麻烦的根源。另外,第 2 步只在采样到的状态 $\{s_i\}$ 上做拟合,所以值函数的准确性受限于数据分布:没被访问过的状态区域,$V_\theta$ 的取值完全由网络的外推行为决定,可能是任意的。

5.3 一个致命的实现障碍

不知道转移动态时,fitted value iteration 的第 1 步无法执行;回到 policy iteration 用 Q 改写
上半部分把拟合值迭代的第 1 步用红线标出:$\max_{a_i}\big(r(s_i,a_i)+\gamma E[V_\theta(s_i')]\big)$,右边箭头指出问题——「need to know outcomes for different actions!」。要对所有动作取最大值,就必须知道每一个动作会导致什么后果,也就是必须知道 $p(s'|s,a)$,或者至少能把模拟器重置回 $s_i$ 反复试每个动作。真实世界里两者都做不到:你只能试一个动作,试完就回不去了。下半部分是解决思路的伏笔——回到策略迭代,把策略评估从 $V$ 的形式改写成 $Q$ 的形式:红线划掉 $V^\pi(s)\leftarrow r(s,\pi(s))+\gamma\E_{s'\sim p(s'|s,\pi(s))}[V^\pi(s')]$,换成 $Q^\pi(s,a)\leftarrow r(s,a)+\gamma\E_{s'\sim p(s'|s,a)}\big[Q^\pi(s',\pi(s'))\big]$,底部标注「can fit this using samples」——这个式子可以只用采样到的 $(s,a,r,s')$ 来拟合,因为它的右边不需要「换个动作再试一次」。

问题出在 $\max_{a_i}$ 上。要算 $\max_a\big(r(s_i,a)+\gamma\E[V_\theta(s')]\big)$,我必须知道:在状态 $s_i$ 执行动作 $a=1$ 会到哪、执行 $a=2$ 会到哪、$a=3$ 会到哪……对每一个动作都要知道它的后果。这有两条路:

  • 知道转移模型 $p(s'|s,a)$——但 model-free RL 的前提就是不知道;
  • 能把模拟器重置到 $s_i$,然后逐个动作试一遍——在 MuJoCo 这类可存档的模拟器里勉强可行,在真实机器人或真实用户交互中完全不可能,因为「时间不能倒流」。

而我们从环境里能拿到的,只有一条一条的转移 $(s,a,r,s')$:在 $s$ 采了某一个 $a$,看到了那一个后果。用这样的数据没法算 $V$ 的 Bellman 最优备份。

6. 学 $Q$ 而不是 $V$:拟合 Q 迭代

上一节的死结是:$\max_a$ 需要「对每个动作试一遍」。解开这个结的办法出奇地简单——把 $\max$ 挪到一个我们已经算好的函数上去取。

6.1 把策略评估改写成 $Q$ 的形式

先看策略迭代这一支。原本的策略评估是对 $V$ 的备份:

$$ V^\pi(s)\ \leftarrow\ r(s,\pi(s))+\gamma\,\E_{s'\sim p(s'|s,\pi(s))}\big[V^\pi(s')\big] $$

这个式子的问题是:它规定了在 $s$ 处必须执行 $\pi(s)$,所以只能用「恰好由 $\pi$ 产生的转移」来估计。改写成 $Q$ 的形式:

$$ Q^\pi(s,a)\ \leftarrow\ r(s,a)+\gamma\,\E_{s'\sim p(s'|s,a)}\big[Q^\pi(s',\pi(s'))\big] $$

差别看似微小,意义却完全不同:左边的 $(s,a)$ 现在是自由变量。给定任意一条转移 $(s,a,r,s')$,我都可以拿它做一次更新——不管 $a$ 是不是 $\pi$ 选的。而右边需要的 $Q^\pi(s',\pi(s'))$ 只是在已有的 $Q$ 函数上查一个值,不需要真的在 $s'$ 执行 $\pi(s')$。这就是「不需要模拟动作」的含义。

6.2 再用一次 max 技巧

把 max 技巧从 V 迁移到 Q,得到 fitted Q-iteration,以及它的优缺点
上半部分回顾了从策略迭代(左:评估 $V^\pi$ → 改进 $\pi$)到拟合值迭代(右:直接算 $y_i=\max_{a_i}(r+\gamma E[V_\theta(s_i')])$ 再回归)的那次「max 技巧」,标注「no policy, compute value directly」。中间一行提出本节的问题:「can we do this with Q-values also, without knowing the transitions?」——能不能对 Q 值也来一次,而且不需要知道转移?下半部分给出答案,即 fitted Q iteration:1. $y_i\leftarrow r(s_i,a_i)+\gamma E[V_\theta(s_i')]$;2. $\theta\leftarrow\argmin_\theta\frac12\sum_i\|Q_\theta(s_i,a_i)-y_i\|^2$。左指箭头写明关键近似:$E[V(s_i')]\approx\max_{a'}Q_\theta(s_i',a')$,右侧标注「doesn't require simulation of actions!」(不需要模拟动作)。底部三条是 Levine 对这个算法的总评:+ 即使是 off-policy 的样本也能用;+ 只有一个网络,没有高方差的策略梯度;− 非线性函数逼近下没有收敛保证(后面细说)。

现在把 $\pi$ 也去掉。既然 $\pi$ 就是对 $Q$ 的贪心策略,那么

$$ Q^\pi\big(s',\pi(s')\big)=\max_{a'}Q^\pi(s',a') $$

等价地说,我们用 $\max_{a'}Q_\theta(s',a')$ 来近似 $\E[V(s')]$。这个 $\max$ 是在网络的输出上取的——对离散动作空间,把 $s'$ 前向传播一次得到 $|\mathcal{A}|$ 个 Q 值,取最大即可,完全不需要与环境交互。至此死结解开。

核心结论:为什么必须是 $Q$ 而不是 $V$

$V$ 的 Bellman 最优备份是 $\max_a\big(r(s,a)+\gamma\E_{s'}[V(s')]\big)$:$\max$ 在期望外面,每个 $a$ 都对应一个不同的 $s'$ 分布,所以必须知道模型。
$Q$ 的 Bellman 最优备份是 $r(s,a)+\gamma\E_{s'}\big[\max_{a'}Q(s',a')\big]$:$\max$ 在期望里面,且只作用在 $Q$ 这个已知函数上;期望 $\E_{s'}$ 可以用单个采样 $s'$ 无偏地替代。把 $\max$ 从「需要环境」的位置搬到了「只需要网络」的位置——这就是 Q 函数存在的全部理由。

6.3 完整算法

完整的 fitted Q-iteration 算法及其三个超参数
左侧是完整的 fitted Q-iteration,注意有两重循环:外层(大绿箭头)是数据收集,内层(小绿箭头,标着 $K\times$)是 Q 迭代。1. 用某个策略收集数据集 $\{(s_i,a_i,s_i')\}$;2. 计算目标 $y_i\leftarrow r(s_i,a_i)+\gamma\max_{a_i'}Q_\theta(s_i',a_i')$;3. 回归 $\theta\leftarrow\argmin_\theta\frac12\sum_i\|Q_\theta(s_i,a_i)-y_i\|^2$;步骤 2、3 重复 $K$ 次后回到步骤 1 再收集数据。右侧列出三个超参数与它们对应的位置:数据集大小 $N$ 与收集策略(对应步骤 1)、迭代次数 $K$(内层循环)、梯度步数 $S$(步骤 3 里回归实际做多少步 SGD,因为 $\argmin$ 通常不会真的解到底)。左下角是网络结构:输入 $(s,a)$、输出 $Q_\theta(s,a)$、参数 $\theta$。实践中对离散动作更常见的是「输入 $s$、输出 $|\mathcal{A}|$ 维向量」,这样一次前向就能取 $\max$。
Fitted Q-Iteration 完整算法
  1. 用某个策略收集数据集 $\mathcal{D}=\{(s_i,a_i,r_i,s_i')\}_{i=1}^N$;
  2. 重复 $K$ 次:
    1. $y_i\ \leftarrow\ r(s_i,a_i)+\gamma\max_{a'}Q_\theta(s_i',a')$,对所有 $i$;
    2. $\theta\ \leftarrow\ \argmin_\theta\frac12\sum_i\|Q_\theta(s_i,a_i)-y_i\|^2$(实际做 $S$ 步梯度下降);
  3. 回到第 1 步继续收集数据。
超参数含义取大 / 取小的影响
$N$(数据集大小)每轮收集多少条转移大:分布覆盖好、目标稳定;小:更接近在线、样本效率更高但更不稳
$K$(迭代次数)在同一批数据上做多少次 Bellman 备份大:把这批数据的信息榨干,但会过拟合到数据分布、放大外推误差;小:浪费数据
$S$(梯度步数)每次回归做多少步 SGD大:更接近真正的 $\argmin$,但目标 $y_i$ 是旧的、容易过度拟合旧目标;$S=1$ 就退化成在线 Q-learning
import torch, torch.nn as nn

class QNet(nn.Module):                      # 输入 s,输出所有动作的 Q 值
    def __init__(self, obs_dim, n_act):
        super().__init__()
        self.f = nn.Sequential(nn.Linear(obs_dim, 128), nn.ReLU(),
                               nn.Linear(128, 128), nn.ReLU(),
                               nn.Linear(128, n_act))
    def forward(self, s):
        return self.f(s)                    # [B, n_act]

def fitted_q_iteration(qnet, data, gamma=0.99, K=10, S=100, lr=1e-3):
    """data: (s, a, r, s_next, done),均为张量;s:[N,obs] a:[N] r:[N] done:[N]"""
    s, a, r, s_next, done = data
    opt = torch.optim.Adam(qnet.parameters(), lr=lr)
    for k in range(K):
        with torch.no_grad():               # 目标不回传梯度:这是「回归」而非「联合优化」
            q_next = qnet(s_next).max(dim=1).values          # max_a' Q(s', a')
            y = r + gamma * (1.0 - done) * q_next            # 终止状态不 bootstrap
        for _ in range(S):
            q_sa = qnet(s).gather(1, a.unsqueeze(1)).squeeze(1)   # Q(s_i, a_i)
            loss = 0.5 * ((q_sa - y) ** 2).mean()
            opt.zero_grad(); loss.backward(); opt.step()
    return qnet
常见误区

代码里的 torch.no_grad() 不是性能优化,而是算法正确性的一部分。目标 $y_i$ 里含有 $Q_\theta(s_i',a')$,如果让梯度穿过它,你优化的就不再是「拟合值迭代」,而是所谓的残差梯度(residual gradient)——那是一个不同的算法,收敛到不同的解,实践中通常更慢更差。拟合 Q 迭代的正确解读是:$y_i$ 是一个被冻结的常数标签,第 2 步是一个纯粹的监督回归问题。下一讲的 target network 正是把这个「冻结」做得更彻底。

7. 为什么 Q-learning 是 off-policy 的,它在优化什么

7.1 off-policy 性质的来源

fitted Q-iteration 的 off-policy 性质:转移与策略无关,max 已代表新策略
算法上有两处被红圈圈出。第一处是 $r(s_i,a_i)$ 里的 $(s_i,a_i)$,下方箭头标注「given $s$ and $a$, transition is independent of $\pi$」——一旦状态和动作都给定,环境如何转移完全由 $p(s'|s,a)$ 决定,与是谁选的这个动作无关。第二处是 $\gamma\max_{a_i'}Q_\theta(s_i',a_i')$,右侧标注「this approximates the value of $\pi'$ at $s_i'$」,并给出 $\pi'$ 的定义(对 $Q^\pi$ 取 $\argmax$ 的确定性策略):目标里的 $\max$ 已经代表了「当前的新策略」,而不是采集数据时用的旧策略。下方的绿色圆柱是「dataset of transitions」,里面画着一根根互不相连的小箭头——每根箭头是一条独立的转移 $(s,a,r,s')$,它们不需要拼成完整轨迹,也不需要来自同一个策略。右侧的橙色回环箭头表示 fitted Q-iteration 只是反复在这堆散装转移上做备份和回归。

回顾 fitted Q-iteration 的第 2、3 步,问一句:数据必须来自哪个策略?逐项检查:

  • $r(s_i,a_i)$:奖励函数是环境给的,与策略无关;
  • $s_i'$:由 $p(s'|s_i,a_i)$ 采样得到。给定 $s_i$ 和 $a_i$ 之后,$s_i'$ 的分布与策略无关——策略只影响「你会选哪个 $a_i$」,不影响「选了 $a_i$ 之后会发生什么」;
  • $\max_{a'}Q_\theta(s_i',a')$:这是对当前 $Q_\theta$ 的运算,与数据来源无关。而且它恰好等于「新的贪心策略 $\pi'$ 在 $s_i'$ 处的值」;
  • $Q_\theta(s_i,a_i)$:网络对给定输入的输出。

结论:整个更新只依赖四元组 $(s,a,r,s')$ 本身,不依赖它是被哪个策略、在什么时候采集的。所以数据可以来自:几百万步之前的旧策略、一个随机策略、人类演示、别人训练好的另一个 agent、甚至一个纯粹的离线数据集。这就是 off-policy 的含义,也是 Q-learning 相对策略梯度最大的实用优势。

直觉:转移是「散装」的

策略梯度需要完整轨迹,而且必须是当前策略的轨迹,因为 $\nabla_\theta J=\E_{\tau\sim p_\theta}[\cdots]$ 里的期望下标就是当前的 $\theta$,更新一次参数所有数据全部作废。
Q-learning 需要的只是一堆互不相连的转移片段。你可以把一条 1000 步的轨迹拆成 1000 个独立样本,随机打乱、反复使用。这不仅让 replay buffer 成为可能(提高样本效率),还顺带打破了轨迹内相邻样本的强相关性——这对 SGD 的稳定性很重要,下一讲会详细讨论。

注意:off-policy 不等于「任意数据都行」

理论上更新式对任何数据都成立,但目标里的 $\max_{a'}Q_\theta(s',a')$ 会去查询数据里可能根本没出现过的动作 $a'$。如果 $Q_\theta$ 在这些没见过的 $(s',a')$ 上高估(神经网络的外推常常如此),这个高估就会通过 Bellman 备份传播到所有前驱状态,而且没有任何数据能纠正它——因为你从没试过那个动作。这就是离线强化学习(offline RL)里的分布偏移(distributional shift)问题,也是本讲末尾负面结果的一个具体表现。数据分布 $\beta$ 覆盖得越差,问题越严重。

7.2 fitted Q-iteration 在优化什么

fitted Q-iteration 的误差目标:Bellman 误差为零时得到最优 Q 函数
步骤 2 的右侧标注「this max improves the policy (tabular case)」——括号里的「表格情形」是重点,出了表格这句话就不再严格成立。步骤 3 下方的向上箭头指向一个被命名为 $\mathcal{E}$ 的量: $\mathcal{E}=\frac12 E_{(s,a)\sim\beta}\Big[\big(Q_\theta(s,a)-[r(s,a)+\gamma\max_{a'}Q_\theta(s',a')]\big)^2\Big]$, 这就是 Bellman 误差(Bellman error),$\beta$ 是数据的采样分布。下面两行说明它的意义:若 $\mathcal{E}=0$,则 $Q_\theta(s,a)=r(s,a)+\gamma\max_{a'}Q_\theta(s',a')$ 对所有 $(s,a)$ 成立,这正是 Bellman 最优方程,因此 $Q_\theta$ 就是最优 Q 函数,对应的贪心策略 $\pi'$ 就是最优策略(常记作 $Q^\star$ 和 $\pi^\star$),它最大化奖励。最下方的红字是本讲最重要的免责声明:「most guarantees are lost when we leave the tabular case (e.g., use neural networks)」——一旦离开表格情形(比如用神经网络),绝大多数保证都失效了。

fitted Q-iteration 表面上是在最小化一个回归损失,但那个损失的目标 $y_i$ 每轮都在变,所以它不是在最小化任何固定的函数。真正有意义的「进度指标」是 Bellman 误差:

$$ \mathcal{E}=\frac12\,\E_{(s,a)\sim\beta}\left[\Big(Q_\theta(s,a)-\big[r(s,a)+\gamma\max_{a'}Q_\theta(s',a')\big]\Big)^2\right] $$

其中 $\beta$ 是数据的分布。这个量的意义非常清晰:

  • 若 $\mathcal{E}=0$(且 $\beta$ 覆盖所有 $(s,a)$),则 $Q_\theta$ 精确满足 Bellman 最优方程 $Q=\mathcal{B}Q$,于是 $Q_\theta=Q^\star$,导出的贪心策略就是最优策略 $\pi^\star$;
  • 若 $\mathcal{E}$ 很小但不为零,我们希望策略接近最优。表格情形下确实有界;但用神经网络时,小的 Bellman 误差并不能保证策略好——因为 $\beta$ 覆盖不到的区域可以任意糟,而 $\mathcal{E}$ 对它们视而不见。
常见误区:把训练 loss 当成学习进度

很多人训练 DQN 时盯着回归 loss 看,发现 loss 下降就以为在学好,loss 上升就以为出问题了。这是错的。回归 loss 衡量的是「网络拟合当前这批目标拟合得多好」,而目标本身在变。loss 很小可能只是因为 $Q$ 已经塌缩成了一个常数(比如全部高估到同一个大数),这种情况下 Bellman 误差小、策略却毫无意义。判断 Q-learning 是否在进步,唯一靠谱的指标是周期性地跑贪心策略、测真实回报;辅助指标是看 $Q$ 值的量级是否与实际回报的量级相符(严重高估是发散的前兆)。

8. 在线 Q-learning 与探索

8.1 把批量算法推到极限

在线 Q 迭代算法:N=1, K=1, S=1 的 fitted Q-iteration
上方是完整的 fitted Q-iteration(收集 $N$ 条数据 → 迭代 $K$ 次备份+回归)。下方是把三个超参数全部取 1 得到的 online Q iteration:1. 执行某个动作 $a_i$,观察到 $(s_i,a_i,s_i')$;2. $y_i=r(s_i,a_i)+\gamma\max_{a'}Q_\theta(s_i',a_i')$;3. $\theta\leftarrow\theta-\alpha\frac{dQ_\theta}{d\theta}(s_i,a_i)\big(Q_\theta(s_i,a_i)-y_i\big)$——第 3 步就是平方损失 $\frac12(Q_\theta-y)^2$ 对 $\theta$ 的一步梯度下降,链式法则给出「网络梯度 × 残差」。指向步骤 1 的箭头写着「off policy, so many choices here!」:因为算法是 off-policy 的,第 1 步用什么策略采集动作是自由的,这个自由度正是下一节讲探索的入口。右侧循环图上,绿盒子对应 $Q_\theta(s,a)\leftarrow r(s,a)+\gamma\max_{a'}Q_\theta(s',a')$,蓝盒子对应 $a=\argmax_a Q_\theta(s,a)$——三个盒子各只走一步就绕一圈,这就是「在线」的含义。

把 fitted Q-iteration 的 $N=1$、$K=1$、$S=1$,就得到最经典的 online Q-learning(Watkins, 1989):

Online Q-iteration 算法
  1. 执行某个动作 $a_i$,观察到 $(s_i,a_i,r_i,s_i')$;
  2. $y_i=r(s_i,a_i)+\gamma\max_{a'}Q_\theta(s_i',a')$;
  3. $\displaystyle\theta\leftarrow\theta-\alpha\,\frac{dQ_\theta}{d\theta}(s_i,a_i)\big(Q_\theta(s_i,a_i)-y_i\big)$

第 3 步就是对损失 $\frac12\big(Q_\theta(s_i,a_i)-y_i\big)^2$ 求梯度:$\nabla_\theta\mathcal{L}=\big(Q_\theta(s_i,a_i)-y_i\big)\nabla_\theta Q_\theta(s_i,a_i)$。在表格情形下 $\nabla_\theta Q_\theta(s_i,a_i)$ 是一个 one-hot 向量,更新退化成大家熟悉的

$$ Q(s,a)\ \leftarrow\ Q(s,a)+\alpha\Big(r+\gamma\max_{a'}Q(s',a')-Q(s,a)\Big) $$

括号里的量叫 TD 误差(temporal difference error)。

8.2 探索:为什么不能用贪心策略采数据

Q-learning 的探索策略:epsilon-greedy 与 Boltzmann 探索
左侧重复了 online Q iteration 三步。右上给出「final policy」——训练结束后真正部署的策略是纯贪心的确定性策略 $\pi(a_t|s_t)=\mathbb{1}[a_t=\argmax_{a_t}Q_\theta(s_t,a_t)]$。紧接着的提问是本页的核心:「why is this a bad idea for step 1?」——为什么把这个贪心策略用在第 1 步(采集数据)是个坏主意?下方给出两个替代方案。$\epsilon$-greedy:$\pi(a_t|s_t)=1-\epsilon$ 若 $a_t$ 是贪心动作,否则 $\epsilon/(|\mathcal{A}|-1)$ 均分给其余动作。Boltzmann 探索:$\pi(a_t|s_t)\propto\exp\big(Q_\theta(s_t,a_t)\big)$,即对 Q 值取 softmax。底部注明探索会在后面的专门一讲里细讲。

训练结束后我们要部署的确实是贪心策略。但用它来采集训练数据是灾难性的,原因有两个:

  • 确定性 = 零覆盖。贪心策略在每个状态只会选一个动作,那么其他动作的 $(s,a)$ 就永远没有数据,$Q_\theta(s,a)$ 永远只是网络的外推猜测,永远得不到修正。
  • 初期的 $Q$ 是随机的。训练刚开始时 $Q_\theta$ 基本是噪声,此时的 $\argmax$ 是任意的。如果就此锁死,agent 会永远重复一个由随机初始化决定的动作序列,自我实现地把这个坏策略学成「唯一见过的策略」。举个具体例子:某个动作的真实回报是 10,但初始化时 $Q$ 恰好给它 $-1$,而另一个真实回报 1 的动作被初始化成 $+0.5$;贪心策略永远选后者,前者的 $-1$ 永远不会被修正。

因此第 1 步必须用一个有随机性的行为策略(behavior policy)。因为 Q-learning 是 off-policy 的,这么做不引入任何偏差——这是它相对 on-policy 方法的又一个便利。两个最常用的选择:

策略公式特点
$\epsilon$-greedy$\pi(a|s)=\begin{cases}1-\epsilon & a=\argmax_{a}Q_\theta(s,a)\\ \epsilon/(|\mathcal{A}|-1) & \text{otherwise}\end{cases}$实现最简单;但把所有非贪心动作一视同仁,哪怕某个动作明显很糟(比如让机器人摔倒)也会以同样概率被选中。实践中让 $\epsilon$ 随训练衰减(如从 1.0 线性降到 0.05)
Boltzmann(softmax)探索$\pi(a|s)\propto\exp\big(Q_\theta(s,a)/\tau\big)$按 Q 值大小分配概率:明显糟糕的动作概率指数级地小,而两个 Q 值相近的动作被近乎等概率地尝试——这正是我们想要的「在不确定的地方多试」。温度 $\tau$ 控制随机程度,$\tau\to 0$ 退化为贪心
直觉:为什么 Boltzmann 常常更合理

$\epsilon$-greedy 的问题是它不利用 Q 值携带的信息。设三个动作的 Q 值分别是 $10.0,\ 9.9,\ -1000$。$\epsilon$-greedy 会用同样的概率去试第二个和第三个动作——但第二个动作几乎和最优一样好(值得多试,因为估计误差可能让排序反了),第三个动作则明确是灾难(不该浪费样本)。Boltzmann 探索天然做出了这个区分:前两个概率几乎相等,第三个的概率是 $e^{-1010}$ 量级,实际上是零。
反过来说,$\epsilon$-greedy 的均匀性在「Q 值完全不可靠的训练早期」反而是优点,所以实践中常见的做法是早期大 $\epsilon$、后期小 $\epsilon$ 或切换到 Boltzmann。

8.3 合起来:带 replay buffer 的 Q-learning

本讲的最终算法:带 replay buffer 与 epsilon-greedy 探索的 Q-learning
这一页把本讲所有零件拼回第 1 节那个算法,但补齐了探索:1. 用 $a\sim\pi_\theta(a|s)$ 走一步得到 $(s_i,a_i,s_i')$,存入 replay buffer;2. 从 buffer 取一个 batch,算 $y_i=r(s_i,a_i)+\gamma\max_{a'}Q_\theta(s_i',a')$;3. 用 $\nabla_\theta\sum_{i=1}^B\|Q_\theta(s_i,a_i)-y_i\|^2$ 更新 $\theta$。左下角的 $\pi_\theta$ 现在写成了 $\epsilon$-greedy 形式而不是纯贪心。右侧两个黄色标注是本讲的收尾:「If you try to code this up, it almost certainly won't work」(照着写几乎肯定跑不通),「We'll find out how to make it work next time!」(下一讲讲怎么让它 work)。

注意这个最终算法相对 online Q-learning 多了 replay buffer:每步交互写入 buffer,训练时从 buffer 随机取 batch。它在 $(N,K,S)$ 的谱系上处于中间位置——既有在线交互的及时性,又有批量数据的稳定性。这正是 DQN 的骨架。

import random, torch
from collections import deque

buffer = deque(maxlen=1_000_000)
eps, gamma, B = 1.0, 0.99, 32

for step in range(total_steps):
    # --- 1. 交互一步(epsilon-greedy 探索)---
    if random.random() < eps:
        a = random.randrange(n_act)
    else:
        with torch.no_grad():
            a = int(qnet(torch.as_tensor(s).float()).argmax())
    s_next, r, done, _ = env.step(a)
    buffer.append((s, a, r, s_next, float(done)))
    s = env.reset() if done else s_next
    eps = max(0.05, 1.0 - step / 100_000)        # 线性衰减探索率

    # --- 2&3. 从 buffer 采样 batch,做一步回归 ---
    if len(buffer) >= B:
        batch = random.sample(buffer, B)
        bs, ba, br, bs2, bd = map(lambda x: torch.as_tensor(x).float(), zip(*batch))
        with torch.no_grad():
            y = br + gamma * (1 - bd) * qnet(bs2).max(dim=1).values
        q = qnet(bs).gather(1, ba.long().unsqueeze(1)).squeeze(1)
        loss = ((q - y) ** 2).mean()
        opt.zero_grad(); loss.backward(); opt.step()

这段代码逻辑上完全正确,但正如 Levine 警告的:它大概率不会 work。缺的是 target network、梯度裁剪、合适的学习率、以及对 $\max$ 造成的系统性高估的处理。下一讲会逐个补上。而它为什么不 work,理论上的根源就是下一节。

9. 关键负面结果:带函数逼近的值迭代不保证收敛

第 4 节我们证明了表格值迭代必然收敛,速率 $\gamma^k$。第 5 节我们把表格换成神经网络,形式上只多了一步「回归」。但这一步毁掉了全部保证。本节解释为什么,这是 Levine 反复强调的一个点,也是理解下一讲所有工程技巧的理论前提。

9.1 把拟合值迭代拆成两个算子

拟合值迭代的一轮可以精确地写成两个算子的复合:

  • Bellman 备份 $\mathcal{B}$:$\bar V=\mathcal{B}V$,即 $\bar V(s)=\max_a\big(r(s,a)+\gamma\E_{s'}[V(s')]\big)$。这一步的输出 $\bar V$ 是一个任意的函数,一般不在神经网络能表示的函数集合 $\Omega=\{V_\theta:\theta\in\Theta\}$ 里。
  • 投影 $\Pi$:$V'=\Pi\bar V=\argmin_{V'\in\Omega}\frac12\sum_i\|V'(s_i)-\bar V(s_i)\|^2$。这一步把 $\bar V$ 拉回到 $\Omega$ 里离它最近的点——在$\ell_2$ 范数(欧氏距离)意义下最近。

于是拟合值迭代就是 $V_{k+1}=\Pi\mathcal{B}V_k$。表格情形下 $\Omega$ 是全空间,$\Pi=I$(恒等算子),所以退化成纯 $\mathcal{B}$,一切正常。

9.2 两个算子各自都很乖,合起来却不乖

推导:为什么复合不是压缩

事实一:$\mathcal{B}$ 是 $\infty$-范数下的 $\gamma$-压缩。(第 4 节已证) $$ \|\mathcal{B}V-\mathcal{B}\bar V\|_\infty\le\gamma\|V-\bar V\|_\infty $$

事实二:$\Pi$ 是 $\ell_2$-范数下的非扩张映射(non-expansion)。因为 $\Pi$ 是到集合 $\Omega$ 上的正交投影($\Omega$ 为线性子空间时严格成立),而正交投影总满足 $$ \|\Pi V-\Pi\bar V\|_2\le\|V-\bar V\|_2 $$ 直观上:投影是「把点垂直压到一个平面上」,两点之间的欧氏距离只会缩短,不会拉长。

但是:$\Pi\mathcal{B}$ 在任何范数下都不保证是压缩。这不是证明技巧不够,而是事实如此——下面会给出发散的具体例子。
问题的根源在于两个压缩用的是不同的范数。若两者都在 $\infty$-范数下压缩,复合的模就是乘积 $\le\gamma\cdot 1=\gamma$,仍是压缩。但 $\Pi$ 在 $\infty$-范数下可以是扩张的:最小二乘拟合为了让平均平方误差最小,完全可能在某个单独的状态上把误差放大(牺牲一个点,换其他点的整体更准)。而 $\mathcal{B}$ 在 $\ell_2$ 范数下同样不保证压缩。于是复合算子 $\Pi\mathcal{B}$ 的「模」可以大于 1,迭代就可能发散。

直觉:投影为什么会把误差放大

想象一条直线 $\Omega$(可表示函数的集合),真值 $V^\star$ 是平面上的一个点,一般不在这条直线上。当前估计 $V_k$ 在直线上。
$\mathcal{B}$ 这一步把 $V_k$ 拉向 $V^\star$,距离缩短到原来的 $\gamma$——这一步永远是好的,它把 $\mathcal{B}V_k$ 移到了离 $V^\star$ 更近的位置。
$\Pi$ 这一步把 $\mathcal{B}V_k$ 垂直压回直线。它保证「离 $\mathcal{B}V_k$ 最近」,但完全不保证「离 $V^\star$ 更近」——因为 $V^\star$ 根本不在直线上。如果直线的方向和 $V^\star$ 的方向配合得不好,这一压完全可能把点推得比 $V_k$ 离 $V^\star$ 更远。$\gamma$ 越接近 1,$\mathcal{B}$ 拉回的力度越小,越容易被投影的这一推盖过去。

9.3 一个具体的发散例子

最经典的构造(Tsitsiklis & Van Roy, 1997)只需要两个状态、零奖励、一个参数:

  • 状态 $s_1,s_2$;转移是确定性的:$s_1\to s_2$,$s_2\to s_2$(自环);
  • 奖励恒为 $0$。因此真值函数是 $V^\star(s_1)=V^\star(s_2)=0$;
  • 函数类是线性的、只有一个参数:$V_\theta(s)=\theta\,\phi(s)$,特征 $\phi(s_1)=1$,$\phi(s_2)=2$。注意 $\theta=0$ 时可以精确表示真值,所以这不是表达能力不足的问题。

第一步,Bellman 备份。由于奖励为 0、转移确定:

$$ (\mathcal{B}V_\theta)(s_1)=\gamma V_\theta(s_2)=2\gamma\theta,\qquad(\mathcal{B}V_\theta)(s_2)=\gamma V_\theta(s_2)=2\gamma\theta $$

第二步,最小二乘投影。在两个状态上等权重拟合,求 $\theta'$ 使

$$ \mathcal{L}(\theta')=\tfrac12\big(1\cdot\theta'-2\gamma\theta\big)^2+\tfrac12\big(2\cdot\theta'-2\gamma\theta\big)^2 $$

最小。令导数为零:$(\theta'-2\gamma\theta)+2(2\theta'-2\gamma\theta)=0$,即 $5\theta'=6\gamma\theta$,故

$$ \theta'=\frac{6\gamma}{5}\,\theta $$

结论:每一轮参数被乘以 $\tfrac{6\gamma}{5}$。当 $\gamma\gt\tfrac56\approx0.833$ 时这个系数大于 1,$|\theta|$ 指数发散。取常用的 $\gamma=0.9$:系数是 $1.08$,从 $\theta_0=1$ 出发,100 轮后 $\theta\approx 2200$,1000 轮后约 $10^{32}$。而真值就是 $0$,且这个函数类完全能表示 $0$。

注意:这个例子有多「干净」

它没有神经网络的非凸优化,没有探索不足,没有采样噪声,没有奖励的尺度问题,甚至没有 $\max$ 算子(只有两个状态、一个动作,$\mathcal{B}$ 是线性的)。回归也是精确解到全局最优的。发散纯粹来自「Bellman 备份 + 投影」这个复合本身。把 $\gamma$ 调到 $0.8$(小于 $5/6$)它就收敛了——收敛与否取决于 $\gamma$ 与特征几何的相互关系,而不是任何可以靠调网络解决的东西。

9.4 online Q-learning 也不是梯度下降

还有一个独立的问题。看在线更新:

$$ \theta\leftarrow\theta-\alpha\big(Q_\theta(s,a)-\underbrace{[r+\gamma\max_{a'}Q_\theta(s',a')]}_{y,\ \text{也依赖 }\theta}\big)\nabla_\theta Q_\theta(s,a) $$

这不是任何函数的梯度。真正的 $\nabla_\theta\frac12(Q_\theta(s,a)-y(\theta))^2$ 还应包含 $-\nabla_\theta y$ 这一项,但我们故意把它丢掉了(代码里的 no_grad())。这种更新叫 semi-gradient(半梯度)。因此,SGD 的所有收敛理论(哪怕是「收敛到局部极小」这种弱结论)在这里一条都不适用。加上 $-\nabla_\theta y$ 得到的「残差梯度法」确实是真正的梯度下降,但它优化的目标是均方 Bellman 残差,在随机环境下有双采样偏差、且实践中收敛极慢,所以几乎没人用。

9.5 同样的病也在 actor-critic 里

上一讲的 critic 训练是自举式策略评估(bootstrapped policy evaluation):

$$ y_i=r(s_i,a_i)+\gamma\hat V^\pi_\phi(s_i'),\qquad \phi\leftarrow\argmin_\phi\sum_i\|\hat V^\pi_\phi(s_i)-y_i\|^2 $$

把它写成算子形式就是 $V_{k+1}=\Pi\mathcal{B}^\pi V_k$,其中 $\mathcal{B}^\pi$ 是策略评估算子。结构与拟合值迭代完全相同:$\mathcal{B}^\pi$ 是 $\infty$-范数压缩,$\Pi$ 是 $\ell_2$ 投影,复合不是压缩。上面那个两状态例子里根本没有用到 $\max$,所以它同时也是 policy evaluation 发散的例子。也就是说:actor-critic 的 critic 同样没有收敛保证,只是实践中 actor-critic 通常更温和一些(因为策略变化慢、且常配合 on-policy 数据)。

核心结论:致命三要素(the deadly triad)

Sutton & Barto 把导致发散的三个因素总结为「deadly triad」,三者同时出现才危险:

  1. 函数逼近(function approximation)——引入投影 $\Pi$;
  2. 自举(bootstrapping)——用自己的估计做目标,误差会被反复放大而不是被真实回报锚定;
  3. 离策略(off-policy)——训练分布与被评估策略的访问分布不一致,投影用错了权重。

去掉任何一个就安全:纯蒙特卡洛(去掉自举)总是收敛;表格(去掉逼近)总是收敛;on-policy 的线性 TD(去掉 off-policy)也被证明收敛(Tsitsiklis & Van Roy, 1997)。而 Q-learning + 神经网络 = 三者齐备,所以它是最危险的组合。这就是「照着写几乎肯定跑不通」的理论解释。

常见误区

「没有收敛保证」不等于「没用」。DQN 在 Atari 上、以及后续的 SAC、TD3 等在连续控制上都工作得很好。理论保证的缺失意味着:你不能指望它自动稳定,必须靠工程手段把它按住——target network(把 $\Pi$ 和 $\mathcal{B}$ 的耦合减弱)、replay buffer(改善数据分布、去相关)、小学习率与梯度裁剪(限制单步移动幅度)、double Q-learning(抑制 $\max$ 带来的系统性高估)。这些正是下一讲的全部内容。反过来,如果你调 Q-learning 时遇到 Q 值爆炸到 $10^6$,请记住这不是 bug,是算法本身的性质。

本讲小结

一条主线

「值函数已经知道哪个动作好 → 那就直接取 $\argmax$,不要 actor」→ 这一步合法(策略改进定理)→ 表格下用 DP 精确实现(策略迭代 / 值迭代),且必然收敛($\gamma$-压缩)→ 状态太多,换神经网络(拟合值迭代)→ 但 $\max_a$ 需要模型,换成学 $Q$(拟合 Q 迭代 / Q-learning)→ 天然 off-policy,可用 replay buffer → 需要显式探索 → 但函数逼近毁掉了收敛保证。

速查表

算法核心更新需要模型?on/off-policy收敛保证
策略迭代(表格)$V^\pi\leftarrow r_\pi+\gamma\mathcal{T}_\pi V^\pi$,再 $\pi\leftarrow\text{greedy}(Q^\pi)$是—有限步收敛到 $\pi^\star$
值迭代(表格)$V\leftarrow\max_a\big(r(s,a)+\gamma\E[V(s')]\big)$是—$\|V_k-V^\star\|_\infty\le\gamma^k\|V_0-V^\star\|_\infty$
拟合值迭代$y_i=\max_{a}\big(r(s_i,a)+\gamma\E[V_\theta(s_i')]\big)$,回归是(或可重置模拟器)off无($\Pi\mathcal{B}$ 非压缩)
拟合 Q 迭代$y_i=r_i+\gamma\max_{a'}Q_\theta(s_i',a')$,回归 $K$ 轮否off无(表格情形下有)
在线 Q-learning同上,$N=K=S=1$,semi-gradient 一步否off无(表格 + 适当步长下有)
Actor-critic(上一讲)$y_i=r_i+\gamma \hat V^\pi_\phi(s_i')$,回归 + 策略梯度否on(或需修正)critic 同样无保证

必须记住的要点

  • $\E_{a\sim\pi}[A^\pi(s,a)]=0$:优势函数在自己策略下期望为零,所以贪心动作的优势必然 $\ge 0$,这是策略改进定理的一行核心。
  • 贪心改进不需要学习率:只要 $Q^\pi$ 准确,跳多远都不会变差。但 $Q$ 有误差 $\varepsilon$ 时性能损失被 $\tfrac{2\gamma\varepsilon}{1-\gamma}$ 界住,$\gamma\to1$ 时放大剧烈。
  • 压缩性证明的技术核心是 $\sum_{s'}p(s'|s,a)=1$:随机矩阵在 $\infty$-范数下诱导范数为 1,所以只搬运误差不放大,剩下的 $\gamma$ 就是收缩因子。
  • $Q$ 存在的唯一理由:把 $\max$ 从期望外面(需要模型)搬到期望里面(只需要网络)。
  • off-policy 的一行论证:给定 $(s,a)$ 后 $s'$ 的分布与策略无关,且目标中的 $\max$ 已代表新策略。
  • 为什么必须探索:贪心策略确定性 → 零覆盖 → 初始化的随机偏好被自我实现地固化。用 $\epsilon$-greedy 或 Boltzmann,off-policy 保证这不引入偏差。
  • 发散的根源:$\mathcal{B}$ 在 $\infty$-范数压缩、$\Pi$ 在 $\ell_2$ 范数非扩张,不同范数下的压缩复合起来不是压缩。两状态例子里 $\theta'=\tfrac{6\gamma}{5}\theta$,$\gamma\gt5/6$ 即发散。
  • semi-gradient:在线 Q-learning 的更新不是任何函数的梯度,SGD 的理论一条也用不上。

与前后讲的接口

  • ← 上一讲(Actor-Critic):本讲的 $\mathcal{B}^\pi$ 分析直接解释了 critic 为什么也可能发散;本讲的 $\max$ 技巧是把 actor 删掉的关键。
  • → 下一讲(Q-Learning 的工程实践):replay buffer 的正确用法、target network、DQN、double DQN、multi-step return、以及连续动作空间下怎么算 $\max_a$(DDPG / SAC 的思路)。本讲写下的那段「逻辑正确但跑不通」的代码,会在下一讲被逐行修好。

延伸阅读

经典理论

  • R. Bellman, Dynamic Programming (1957) — 值迭代与 Bellman 方程的源头,「维度灾难」一词也出自这里。
  • R. Howard, Dynamic Programming and Markov Processes (1960) — 策略迭代的原始提出,含策略改进定理。
  • C. Watkins, Learning from Delayed Rewards (PhD thesis, 1989) 与 Watkins & Dayan, Q-learning (1992) — Q-learning 的提出与表格情形下的收敛性证明,是理解「为什么表格能收敛」的必读。
  • J. Tsitsiklis & B. Van Roy, An Analysis of Temporal-Difference Learning with Function Approximation (IEEE TAC, 1997) — 本讲第 9 节那个两状态发散例子的出处,同时证明了 on-policy 线性 TD 的收敛性。要真正理解「什么条件下安全」,读这一篇。
  • L. Baird, Residual Algorithms: Reinforcement Learning with Function Approximation (ICML, 1995) — 著名的 Baird counterexample(星形 MDP),另一个更极端的发散构造,并提出残差梯度法作为补救。
  • D. Bertsekas & J. Tsitsiklis, Neuro-Dynamic Programming (1996) — 把 DP、压缩映射、函数逼近误差界系统串起来的教科书,本讲第 2.2 节那个 $\tfrac{2\gamma\varepsilon}{1-\gamma}$ 界的严格来源。
  • R. Sutton & A. Barto, Reinforcement Learning: An Introduction (2nd ed., 2018), 第 4、6、11 章 — 第 4 章讲 DP,第 6 章讲 TD 与 Q-learning,第 11 章专讲 deadly triad 与 off-policy 发散。

拟合 Q 迭代与批量 RL

  • D. Ernst, P. Geurts, L. Wehenkel, Tree-Based Batch Mode Reinforcement Learning (JMLR, 2005) — fitted Q-iteration 的正式提出(用随机森林做回归器),本讲第 6 节算法的直接来源。
  • M. Riedmiller, Neural Fitted Q Iteration (ECML, 2005) — 用神经网络做 fitted Q-iteration 的早期工作,DQN 的前身。
  • Offline Reinforcement Learning: Tutorial, Review, and Perspectives on Open Problems (2020) — Levine 等人写的离线 RL 综述,第 7.1 节提到的「$\max_{a'}$ 查询到数据外动作」问题在这里被完整展开。

深度 Q-learning(下一讲的预习)