Skip to content

近似方法 (Function Approximation)

在前面的章节中,我们一直使用表格(Tabular)方式来存储价值函数:一张Q表,或一张V表,每个状态(或状态-动作对)对应一个格子。这种方法在Grid World这种小任务中非常好用,但当我们走向真实世界时,表格方法会迅速崩溃。本章介绍Sutton & Barto第9-11章的核心内容:函数近似。

为什么需要函数近似

维度灾难 (Curse of Dimensionality)

考虑一个围棋棋盘:19x19的棋盘上每个位置有三种状态(黑、白、空),总状态数约为\(3^{361}\),这是一个天文数字。即便是简单一些的Atari游戏,屏幕分辨率210x160,每个像素有256种颜色,状态空间也是\(256^{210 \times 160}\)。显然,我们不可能为每一个状态都单独维护一个Q值。

表格方法的核心假设是:每个状态都是独立的,状态A的经验完全不能帮助状态B。但在现实中,相似的状态往往具有相似的价值。比如在Atari的Pong游戏中,球在屏幕左上角和球在屏幕左上角偏右一个像素,这两个"不同的状态"对应的最优动作几乎完全相同。

泛化 (Generalization)

函数近似的核心优势在于泛化:当我们访问过一个状态并更新了它的价值后,与它相似的状态的价值估计也会随之改善。这是因为我们不再为每个状态单独存一个数字,而是用一个函数(带参数\(\mathbf{w}\))来拟合整个价值函数:

\[ \hat{v}(s, \mathbf{w}) \approx v_\pi(s) \]
\[ \hat{q}(s, a, \mathbf{w}) \approx q_\pi(s, a) \]

其中\(\mathbf{w}\)是参数向量。通过调整\(\mathbf{w}\),我们希望函数\(\hat{v}\)在所有状态上都尽可能接近真实的价值函数。


值函数近似

问题设定

我们的目标是找到一组参数\(\mathbf{w}\),使得近似函数\(\hat{v}(s, \mathbf{w})\)尽可能接近真实价值\(v_\pi(s)\)。自然地,我们可以定义一个目标函数(均方误差):

\[ \overline{VE}(\mathbf{w}) = \sum_{s \in \mathcal{S}} \mu(s) [v_\pi(s) - \hat{v}(s, \mathbf{w})]^2 \]

其中\(\mu(s)\)是状态分布,表示我们有多在乎每个状态上的误差。这个目标函数在强化学习中被称为Mean Squared Value Error

用SGD(随机梯度下降)来最小化这个目标:

\[ \mathbf{w}_{t+1} = \mathbf{w}_t - \frac{1}{2} \alpha \nabla_\mathbf{w} [v_\pi(S_t) - \hat{v}(S_t, \mathbf{w}_t)]^2 \]
\[ = \mathbf{w}_t + \alpha [v_\pi(S_t) - \hat{v}(S_t, \mathbf{w}_t)] \nabla_\mathbf{w} \hat{v}(S_t, \mathbf{w}_t) \]

问题是,我们并不知道真实的\(v_\pi(S_t)\)。这正是不同算法的分歧所在:用什么来替代\(v_\pi(S_t)\)

线性函数近似

最简单的函数近似形式是线性函数。我们先为每个状态\(s\)构造一个特征向量(feature vector):

\[ \mathbf{x}(s) = (x_1(s), x_2(s), \dots, x_d(s))^\top \]

然后用参数\(\mathbf{w}\)与特征向量做内积:

\[ \hat{v}(s, \mathbf{w}) = \mathbf{w}^\top \mathbf{x}(s) = \sum_{i=1}^{d} w_i \cdot x_i(s) \]

这种形式下,梯度计算非常简单:

\[ \nabla_\mathbf{w} \hat{v}(s, \mathbf{w}) = \mathbf{x}(s) \]

SGD更新公式变为:

\[ \mathbf{w}_{t+1} = \mathbf{w}_t + \alpha [v_\pi(S_t) - \hat{v}(S_t, \mathbf{w}_t)] \cdot \mathbf{x}(S_t) \]

线性函数近似的优势在于:它有良好的理论收敛保证,在on-policy预测问题中,线性TD(0)一定会收敛到一个全局最优解附近。它的劣势也很明显:表达能力有限,需要人工设计好的特征。

非线性函数近似 (Neural Networks)

当我们把\(\hat{v}(s, \mathbf{w})\)替换成一个神经网络时,就进入了深度强化学习的领域。神经网络可以自动从原始输入(如像素)中学习特征,不需要人工设计。

以DQN(Deep Q-Network)为例,它的核心思想就是用一个卷积神经网络来近似Q函数:

\[ \hat{q}(s, a, \mathbf{w}) \approx q_*(s, a) \]

网络输入是游戏画面(状态\(s\)),输出是每个动作的Q值。DQN的成功离不开两个关键技巧:

  1. Experience Replay:将经验\((s, a, r, s')\)存入一个缓冲区,训练时随机抽样。这打破了样本之间的时序相关性,使得SGD的i.i.d.假设更加合理。
  2. Target Network:使用一个延迟更新的目标网络来计算TD Target,避免"追逐移动靶子"的不稳定问题。

非线性函数近似的理论保证远不如线性情况,但在实践中表现极为强大。


策略近似

参数化策略 (Parameterized Policy)

除了近似价值函数,我们也可以直接对策略进行参数化。使用参数\(\boldsymbol{\theta}\)定义一个参数化策略:

\[ \pi(a|s, \boldsymbol{\theta}) = \Pr\{A_t = a | S_t = s, \boldsymbol{\theta}_t = \boldsymbol{\theta}\} \]

对于离散动作空间,最常见的参数化方式是Softmax策略:

\[ \pi(a|s, \boldsymbol{\theta}) = \frac{e^{h(s, a, \boldsymbol{\theta})}}{\sum_{b} e^{h(s, b, \boldsymbol{\theta})}} \]

其中\(h(s, a, \boldsymbol{\theta})\)是偏好函数(可以是线性函数\(\boldsymbol{\theta}^\top \mathbf{x}(s,a)\)或神经网络)。

对于连续动作空间(如机器人控制),常用高斯策略:

\[ \pi(a|s, \boldsymbol{\theta}) = \frac{1}{\sigma(s, \boldsymbol{\theta})\sqrt{2\pi}} \exp\left(-\frac{(a - \mu(s, \boldsymbol{\theta}))^2}{2\sigma(s, \boldsymbol{\theta})^2}\right) \]

其中均值\(\mu\)和标准差\(\sigma\)都是状态的函数,由参数\(\boldsymbol{\theta}\)控制。

策略近似与值函数近似的关系是互补的:在Actor-Critic框架中,两者会同时使用,这在策略梯度一章中有更详细的讨论。


预测问题 (Prediction)

预测问题的目标是:给定一个策略\(\pi\),学习该策略的价值函数\(v_\pi\)。在函数近似下,这意味着调整参数\(\mathbf{w}\)使得\(\hat{v}(s, \mathbf{w}) \approx v_\pi(s)\)

梯度蒙特卡洛 (Gradient MC)

最直接的方法是用MC采样的回报\(G_t\)来替代真实的\(v_\pi(S_t)\)

\[ \mathbf{w}_{t+1} = \mathbf{w}_t + \alpha [G_t - \hat{v}(S_t, \mathbf{w}_t)] \nabla_\mathbf{w} \hat{v}(S_t, \mathbf{w}_t) \]

由于\(G_t\)\(v_\pi(S_t)\)的无偏估计(\(\mathbb{E}[G_t | S_t = s] = v_\pi(s)\)),所以这个更新方向在期望上就是真实梯度的方向。因此,Gradient MC是一个真正的梯度方法,在一般条件下可以保证收敛到一个局部最优解(线性情况下是全局最优)。

Gradient MC的缺点与MC方法一样:方差大、必须等到episode结束才能更新。

半梯度TD (Semi-gradient TD)

将TD Target \(R_{t+1} + \gamma \hat{v}(S_{t+1}, \mathbf{w}_t)\)作为\(v_\pi(S_t)\)的替代:

\[ \mathbf{w}_{t+1} = \mathbf{w}_t + \alpha [\underbrace{R_{t+1} + \gamma \hat{v}(S_{t+1}, \mathbf{w}_t)}_{\text{TD Target}} - \hat{v}(S_t, \mathbf{w}_t)] \nabla_\mathbf{w} \hat{v}(S_t, \mathbf{w}_t) \]

这个方法被称为半梯度(Semi-gradient),原因在于:TD Target本身也依赖于参数\(\mathbf{w}\)(通过\(\hat{v}(S_{t+1}, \mathbf{w}_t)\)),但我们在求梯度时没有对TD Target求导,只对\(\hat{v}(S_t, \mathbf{w}_t)\)求了导。换句话说,我们在计算梯度的时候,把bootstrapped target当作了一个常数,忽略了它对\(\mathbf{w}\)的依赖。

为什么要这样做?如果我们对TD Target也求导,就会得到一个更复杂的更新规则(称为residual gradient方法),实际效果反而不好。半梯度TD虽然不是真正的梯度下降,但在线性函数近似下,on-policy的半梯度TD(0)被证明是收敛的。

直观对比:

方法 用什么替代\(v_\pi(S_t)\) 是否真梯度 是否需要完整episode
Gradient MC \(G_t\)(真实回报)
Semi-gradient TD(0) \(R_{t+1} + \gamma \hat{v}(S_{t+1}, \mathbf{w})\)

函数近似中的收敛性

函数近似引入了表格方法中不存在的收敛性问题。特别重要的是致命三要素(Deadly Triad)

当以下三个因素同时出现时,学习算法可能发散(参数\(\mathbf{w}\)趋向无穷大):

  1. 函数近似 (Function Approximation):用参数化函数代替表格
  2. 自举 (Bootstrapping):用估计值来更新估计值(如TD方法)
  3. 离策略学习 (Off-policy Learning):用行为策略\(b\)的数据来学习目标策略\(\pi\)的价值

这三个因素中,任意去掉一个,都可以保证收敛:

  • 去掉函数近似(用表格):Tabular Q-learning收敛
  • 去掉Bootstrapping(用MC):Gradient MC收敛
  • 去掉Off-policy(用on-policy):Semi-gradient TD(0) on-policy收敛

这就解释了为什么DQN需要那么多技巧(Experience Replay、Target Network、梯度裁剪等)才能稳定训练——DQN恰好同时具备了三个致命因素。


控制问题 (Control)

控制问题的目标是直接学习最优策略。在函数近似下,我们用\(\hat{q}(s, a, \mathbf{w})\)来近似最优动作价值函数\(q_*(s, a)\)

半梯度Sarsa (Episodic Semi-gradient Sarsa)

将Semi-gradient TD(0)从预测推广到控制:使用\(\hat{q}\)代替\(\hat{v}\),用SARSA的更新方式:

\[ \mathbf{w}_{t+1} = \mathbf{w}_t + \alpha [R_{t+1} + \gamma \hat{q}(S_{t+1}, A_{t+1}, \mathbf{w}_t) - \hat{q}(S_t, A_t, \mathbf{w}_t)] \nabla_\mathbf{w} \hat{q}(S_t, A_t, \mathbf{w}_t) \]

其中\(A_{t+1}\)是根据当前策略(通常是\(\epsilon\)-greedy on \(\hat{q}\))实际选取的动作。这是一个on-policy方法。

算法流程:

初始化参数向量 w
对每个episode:
    初始化状态 S,根据 epsilon-greedy 选择动作 A
    对每一步:
        执行 A,观察 R, S'
        如果 S' 是终止状态:
            w <- w + alpha * [R - q_hat(S, A, w)] * grad q_hat(S, A, w)
            退出循环
        根据 epsilon-greedy 选择 A'
        w <- w + alpha * [R + gamma * q_hat(S', A', w) - q_hat(S, A, w)] * grad q_hat(S, A, w)
        S <- S', A <- A'

深度Q网络的雏形

从Semi-gradient Sarsa到DQN的演变:

  1. \(\hat{q}\)从线性函数换成神经网络
  2. 从on-policy(SARSA)换成off-policy(Q-learning),即用\(\max_{a'} \hat{q}(S', a', \mathbf{w})\)替代\(\hat{q}(S', A', \mathbf{w})\)
  3. 加入Experience Replay和Target Network来对抗Deadly Triad

DQN的TD Target为:

\[ Y_t = R_{t+1} + \gamma \max_{a'} \hat{q}(S_{t+1}, a', \mathbf{w}^{-}) \]

其中\(\mathbf{w}^{-}\)是Target Network的参数,每隔若干步才从主网络\(\mathbf{w}\)复制过来。这实质上是把一个快速移动的目标变成一个相对静止的目标,从而稳定训练。


特征构造

在线性函数近似中,特征向量\(\mathbf{x}(s)\)的设计至关重要。好的特征可以让线性方法达到非线性方法的效果;差的特征则会让学习变得困难甚至不可能。

多项式特征

对于一个连续状态\(s = (s_1, s_2)\),多项式特征就是用状态变量的各种幂次组合来构造特征向量。例如二次多项式:

\[ \mathbf{x}(s) = (1, s_1, s_2, s_1 s_2, s_1^2, s_2^2)^\top \]

优点是简单直观,缺点是特征数量随阶数和维度指数增长,高维空间中不实用。

傅里叶特征

用傅里叶基函数作为特征:

\[ x_i(s) = \cos(\pi \mathbf{c}_i^\top s) \]

其中\(\mathbf{c}_i\)是频率向量。傅里叶特征可以表达价值函数中的周期性模式和全局结构。在许多基准任务上,傅里叶特征的表现优于多项式特征,而且不需要太多人工调参。

Tile Coding (瓦片编码)

Tile Coding是实践中最常用的线性特征构造方法之一。它的思路很直观:

  1. 将连续的状态空间用多个重叠的网格(tiling) 覆盖
  2. 每个tiling把状态空间划分成若干瓦片(tile)
  3. 对于一个给定状态,在每个tiling中,它恰好落在一个tile里
  4. 特征向量就是一个二值向量:被激活的tile对应的分量为1,其余为0

比如一个二维状态空间\([0,1] \times [0,1]\),我们用8个tiling覆盖,每个tiling有\(4 \times 4 = 16\)个tile,那么特征向量的维度为\(8 \times 16 = 128\),其中恰好有8个分量为1。

Tile Coding的优势:

  • 计算高效:特征向量是稀疏的二值向量,内积计算等价于查表求和
  • 分辨率可控:通过调整tile的大小来控制泛化的程度
  • 多分辨率:不同的tiling可以用不同的tile大小,实现粗细结合

Tile Coding的示意:

Tiling 1:          Tiling 2 (偏移):
+---+---+---+      +---+---+---+
|   |   |   |        |   |   |   |
+---+---+---+      +---+---+---+
|   | * |   |        | * |   |   |
+---+---+---+      +---+---+---+

状态 * 在Tiling 1中激活第5号tile
状态 * 在Tiling 2中激活第4号tile
特征向量中只有第5号和第4号位置为1

在线性函数近似下:

\[ \hat{v}(s, \mathbf{w}) = \mathbf{w}^\top \mathbf{x}(s) = \sum_{i \in \text{active tiles}} w_i \]

即价值估计等于所有被激活的tile对应的权重之和。更新时只需要调整被激活的那几个\(w_i\),计算量很小。


总结

函数近似是从Tabular RL走向现代深度强化学习的桥梁。核心思想可以概括为以下几点:

概念 表格方法 函数近似
存储方式 每个状态一个格子 参数化函数\(\hat{v}(s, \mathbf{w})\)
泛化能力 无(状态间独立) 有(相似状态共享参数)
可扩展性 仅限小状态空间 适用于大规模/连续空间
收敛保证 较强 需要额外条件
更新方式 直接修改表格 SGD调整参数\(\mathbf{w}\)

从本章的视角来看,之前学过的所有算法(MC、TD(0)、SARSA、Q-learning)都可以被看作函数近似的特例——只不过它们用的"函数"是一张巨大的查找表。而DQN、PPO、SAC等现代方法,则是在函数近似的框架下,用神经网络作为近似器,配合各种技巧来克服收敛性问题。


评论 #