Offline RL 也叫 Batch RL,它和常见的在线强化学习最大的区别在于:训练时不再和环境交互,而是只能使用一个固定的数据集
$$ \mathcal{D} = \{(s_i, a_i, r_i, s'_i, d_i)\}_{i=1}^{N} $$其中 $d_i$ 表示 episode 是否结束。
在线 RL 可以一边试错一边收集新数据,所以即使当前策略很差,也有机会通过 exploration 找到更好的动作。但是 Offline RL 的策略一旦选择了数据集中很少出现甚至没有出现过的动作,就没有真实环境可以告诉它这个动作到底好不好。
这会带来一个核心问题:distribution shift。
训练数据来自行为策略 $\pi_\beta(a|s)$,而我们最终想学习一个新策略 $\pi(a|s)$。如果 $\pi$ 选择了 $\pi_\beta$ 很少选择的动作,那么对应的 Q 值估计很容易被函数逼近误差放大,最终得到一个看起来 Q 值很高、实际表现很差的策略。
因此 Offline RL 的关键目标不是简单地做 Bellman backup,而是在学习回报的同时控制策略不要离数据分布太远。
Offline RL 的基本流程
一个典型 Offline RL 过程可以写成
收集固定数据集 D
|
v
分析 D 中覆盖的状态和动作
|
v
在 D 上训练 policy 或 Q function
|
v
限制策略不要选择数据外动作
|
v
离线验证或少量在线评估
如果用 Bellman 形式训练 Q function,基本目标仍然是
$$ y = r + \gamma (1-d) \max_{a'} Q_{\bar{\theta}}(s', a') $$$$ \mathcal{L}_{TD}(\theta) = \mathbb{E}_{(s,a,r,s',d)\sim \mathcal{D}} \left[ \left(Q_{\theta}(s,a)-y\right)^2 \right] $$但是在 Offline RL 中,直接使用 $\max_{a'} Q(s', a')$ 有风险,因为 $\max$ 很容易选到数据集中没有覆盖的动作。BC、BCQ 和 CQL 可以看作三种不同的处理方式:
| 方法 | 核心做法 | 是否使用 reward | 如何处理数据外动作 |
|---|---|---|---|
| BC | 直接模仿数据动作 | 否 | 策略天然贴近数据分布 |
| BCQ | 只在数据可能动作集合里做 Q 最大化 | 是 | 用生成模型限制候选动作 |
| CQL | 学 Q function 时惩罚过高的 OOD Q 值 | 是 | 对未被数据支持的动作保持保守 |
Behavior Cloning
BC 是最简单的 Offline RL baseline。它不把问题看作 RL,而是看作 supervised learning:给定状态 $s$,预测数据集中出现的动作 $a$。
数据集可以简化为
$$ \mathcal{D}_{BC} = \{(s_i, a_i)\}_{i=1}^{N} $$策略网络输出
$$ \pi_\theta(a|s) = \mathrm{softmax}(f_\theta(s))_a $$训练目标是最大化数据动作的似然,等价于最小化负对数似然
$$ \mathcal{L}_{BC}(\theta) = - \mathbb{E}_{(s,a)\sim \mathcal{D}} \left[ \log \pi_\theta(a|s) \right] $$对于离散动作,这就是交叉熵损失。
BC 算法流程
输入: 固定数据集 D = {(s, a)}
初始化策略网络 pi_theta(a|s)
repeat:
从 D 中采样一个 batch: {(s_i, a_i)}
计算 logits = f_theta(s_i)
计算损失 L_BC = - mean(log pi_theta(a_i|s_i))
用梯度下降更新 theta
输出: pi_theta
BC 的优点是稳定、简单、不容易产生数据外动作。缺点是它完全不看 reward,因此无法区分“数据中出现过的动作”和“真正长期回报高的动作”。如果数据由次优策略产生,BC 往往只能学到这个次优策略。
Batch-Constrained Q-learning
BCQ 的核心思想是:可以做 Q-learning,但不能在所有动作里随便取最大值,只能在数据分布支持的动作附近取最大值。
普通 Q-learning 的 target 是
$$ y = r + \gamma \max_{a'} Q_{\bar{\theta}}(s', a') $$Offline 场景中这个 $\max$ 很危险,因为它可能选择数据集中没见过的 $a'$。BCQ 用一个生成模型 $G_\omega(a|s)$ 学习行为策略附近的动作分布,然后只从生成模型产生的候选动作中选 Q 值最大的动作。
对于连续动作场景,BCQ 通常包含三个部分:
- 生成模型 $G_\omega(a|s)$,通常用 VAE 学习数据动作分布
- 扰动模型 $\xi_\phi(s,a)$,对生成动作做小幅修正
- Q 网络 $Q_\theta(s,a)$,在候选动作集合上做 Bellman backup
生成候选动作可以写成
$$ a_j \sim G_\omega(s), \quad j=1,\dots,n $$扰动后的动作
$$ \tilde{a}_j = a_j + \xi_\phi(s,a_j) $$其中扰动幅度会被限制在一个很小的范围
$$ \|\xi_\phi(s,a)\|_\infty \leq \Phi $$BCQ 的 target 变成
$$ y = r + \gamma(1-d) \max_{j=1,\dots,n} Q_{\bar{\theta}}(s', \tilde{a}'_j) $$Q 网络的损失仍然是 TD loss
$$ \begin{aligned} \mathcal{L}_{Q}(\theta) &= \mathbb{E}_{\mathcal{D}} \left[ \left(Q_\theta(s,a)-y\right)^2 \right] \end{aligned} $$BCQ 算法流程
输入: 固定数据集 D = {(s, a, r, s', d)}
初始化生成模型 G_omega、扰动模型 xi_phi、Q 网络 Q_theta
第一阶段:
用 D 中的 (s, a) 训练 G_omega(a|s),让它生成数据分布附近的动作
第二阶段 repeat:
从 D 中采样 batch: (s, a, r, s', d)
对每个 s',用 G_omega 生成 n 个候选动作 a'_1 ... a'_n
用 xi_phi 对候选动作做小幅扰动,得到 tilde(a)'_j
用 max_j Q_target(s', tilde(a)'_j) 构造 target
更新 Q_theta
更新 xi_phi,使候选动作的 Q 值更高
输出:
pi(s) = argmax over generated candidate actions
BCQ 的重点是动作约束:策略只能从生成模型认为“像数据动作”的候选集合里挑动作。这样既能利用 reward 学习比 BC 更好的策略,又能避免普通 Q-learning 选择完全不可靠的数据外动作。
Conservative Q-Learning
CQL 的思路和 BCQ 不同。它不一定显式限制策略只能选哪些动作,而是在训练 Q function 时让 Q 值更加保守:降低所有动作的 Q 值,同时相对提高数据中真实动作的 Q 值。
普通 TD loss 仍然存在
$$ \begin{aligned} \mathcal{L}_{TD}(\theta) &= \mathbb{E}_{\mathcal{D}} \left[ \left(Q_\theta(s,a) - \left(r + \gamma(1-d)\max_{a'} Q_{\bar{\theta}}(s',a')\right) \right)^2 \right] \end{aligned} $$对于离散动作空间,CQL 常见的保守正则项可以写成
$$ \begin{aligned} \mathcal{L}_{CQL}(\theta) &= \mathbb{E}_{s\sim \mathcal{D}} \left[ \log \sum_a \exp(Q_\theta(s,a)) \right] \quad{}- \mathbb{E}_{(s,a)\sim \mathcal{D}} \left[ Q_\theta(s,a) \right] \end{aligned} $$最终目标是
$$ \mathcal{L}(\theta) = \mathcal{L}_{TD}(\theta) \quad{}+ \alpha \mathcal{L}_{CQL}(\theta) $$其中 $\alpha$ 控制保守程度。
这个正则项的直觉是:
- $\log \sum_a \exp(Q(s,a))$ 会受到所有动作 Q 值的影响,尤其是较大的 Q 值
- $Q(s,a_{data})$ 只对应数据中真实出现的动作
- 最小化二者差值,会压低那些没有数据支持但 Q 值很高的动作
CQL 算法流程
输入: 固定数据集 D = {(s, a, r, s', d)}
初始化 Q 网络 Q_theta 和 target Q 网络 Q_bar
repeat:
从 D 中采样 batch: (s, a, r, s', d)
计算 Bellman target:
y = r + gamma(1-d) max_a' Q_bar(s', a')
计算 TD loss:
L_TD = mean((Q_theta(s,a) - y)^2)
计算保守正则:
L_CQL = mean(logsumexp_a Q_theta(s,a)) - mean(Q_theta(s,a_data))
计算总损失:
L = L_TD + alpha L_CQL
更新 theta
周期性更新 target network
输出:
pi(s) = argmax_a Q_theta(s,a)
CQL 的重点是值函数约束:不直接规定策略必须像数据,而是让 Q function 对数据外动作保持低估或保守估计。这样在策略做 $\arg\max_a Q(s,a)$ 时,不太容易被虚高的 OOD action 吸引。
BCQ 和 CQL 的对比
BCQ 和 CQL 都是在解决 Offline RL 中的 distribution shift,但它们约束的位置不同。
| 对比项 | BCQ | CQL |
|---|---|---|
| 约束对象 | 策略可选择的动作集合 | Q function 的数值估计 |
| 核心机制 | 用生成模型产生数据分布附近的候选动作 | 用 conservative penalty 压低 OOD 动作 Q 值 |
| Bellman backup | 在候选动作中取 max | 通常仍可在动作空间中取 max,但 Q 值被保守化 |
| 策略形式 | 从生成候选动作中选 Q 最大的动作 | 对 Q function 做贪心或 actor 改进 |
| 依赖模块 | 需要行为建模,如 VAE 或动作生成器 | 不一定需要显式行为模型 |
| 直觉 | 不要选没见过的动作 | 没见过的动作不要估太高 |
| 适合理解为 | policy/action constraint | value constraint |
更直观地说:
BCQ:
先问: 数据里可能会做哪些动作?
再问: 这些动作里哪个 Q 最大?
CQL:
先训练 Q,但惩罚不可靠动作的高 Q 值
再问: 在保守 Q function 下哪个动作最好?
BCQ 的优点是动作约束非常直接,尤其适合连续动作空间,因为它避免了对整个连续动作空间直接取最大值。缺点是需要额外训练生成模型,如果行为策略分布学得不好,候选动作质量也会受影响。
CQL 的优点是思想更通用,实现上可以直接加到 Q-learning 或 actor-critic 框架中,不一定需要单独建模行为策略。缺点是保守系数 $\alpha$ 比较关键;如果太小,仍然可能过估计 OOD action,如果太大,则可能过于保守,学不到比数据策略更好的行为。
总结一下:BCQ 是从动作选择层面避免 OOD action,CQL 是从 Q 值估计层面惩罚 OOD action。