计算机

SAC 算法

最大熵强化学习

参考:Soft Actor-Critic — Spinning Up documentation

引入

在 Markov 决策过程 的框架下,强化学习的目标就是寻找一个较好的策略 \pi,使得各种状态下回报 G_t(折扣的奖励和)的期望尽可能的高;理想情况下,可以找到 Bellman 最优策略 \pi^*,它在所有状态下的回报期望(状态价值)都优于其他策略。

而最大熵强化学习则是把奖励和这个目标直接修改了。在一步转移 s_t \xrightarrow{a_t} s_{t+1} 下,我们除了获得环境的奖励 r(s_t, a_t, s_{t+1}),还会额外获得一个基于策略的熵的奖励:

r_t = r(s_t, a_t, s_{t+1}) + \alpha \mathbb{H}[\pi(\cdot | s_t)].

这里 \pi(\cdot | s_t) 是状态 s_t 下的动作策略,而 \mathbb{H} 则是分布的 熵:

\mathbb{H}[p] = - \int_{\mathbb{R}} p(x) \log p(x) \mathrm{d} x.

它可以衡量分布的随机程度。

也就是说,最大熵强化学习不仅鼓励奖励,还鼓励模型采取更多样化的路径。

最大熵 Markov 决策过程

在引入最大熵之后,Markov 决策过程的优化目标修改为了,最大化最大熵修正的回报:

G_t = R_t + \gamma R_{t + 1} + \cdots, \quad R_t = r(S_t, A_t, S_{t + 1}) + \alpha \mathbb{H}[\pi(\cdot | S_t)].

状态价值关于回报的定义不变:

V(s) = \mathbb{E}[G_t | S_t = s], Q(s, a) = \mathbb{E}[G_t | S_t = s, A_t = a].

但是动作价值的定义略有改变,此时往往不计算当前状态的熵,所以需要改为:

Q(s, a) = \mathbb{E}[(r(S_t, A_t, S_{t+1}) + \gamma r(S_{t+1}, A_{t+1}, S_{t+2} + \cdots) + \alpha (\gamma \mathbb{H}[\pi(\cdot | S_{t + 1})] + \cdots) | S_t = s, A_t = a].

也就是说:

Q(s, a) = \mathbb{E}[G_t | S_t = s, A_t = a] - \alpha \mathbb{H}[\pi(\cdot | s)].

此时,Bellman 方程也有所改变,需要改为:

Q(s, a) = \sum_{s' \in \mathcal{S}} p(s' | s, a) \left [r(s, a, s') + \gamma \left(\alpha \mathbb{H}[\pi(\cdot | s')] + \sum_{a' \in \mathcal{A}} \pi(a' | s') Q(s', a') \right) \right].

SAC 算法

直观理解

SAC(soft actor-critic)算法,是在最大熵 Markov 决策过程的数学基础上,结合 Sarsa、DQN 和 Actor-Critic 架构 的一种强化学习算法。

作为 offline RL 算法,SAC 可以找到很多 DQN 的要素,例如经验回放池(replay buffer)和

首先第一步就是利用 Replay Buffer 的动作,估计出一个 Q 网络 Q_{\omega}(s, a),它就是 SAC 中的 Critic。

然后我们再训练一个策略网络 \pi_{\theta},得到:

\pi_{\theta}(a_t | s_t) = 0

数学推导

在以 (链接未公开) 为代表的策略梯度算法中,我们有优化目标:

\max_{\pi} \mathbb{E}_{\pi} \left[ \sum_{t = 0}^{\infty} \gamma^t R_t \right];

而基于前面最大熵的思想,我们的最大化目标需要有所改变:

\max_{\pi} \mathbb{E}_{\pi} \left[ \sum_{t = 0}^{\infty} \gamma^t ( R^{\text{raw}}_t + \alpha \mathbb{H}[\cdot | S_t] ) \right];

Critic——策略迭代

在这个目标下,我们可以尝试之前的算法。例如, 固定 \pi_k 时,对当前策略的策略迭代(policy iteration)算法的 EMA 版本仍然成立:

Q_{k + 1}(s, a) = Q_k(s, a) + \alpha_{0} \left[ r + \alpha h + \gamma Q_k(s', a') - Q_k(s, a) \right].

我们可以结合使用 DQN 的 Q 网络建模,引入 TD 误差和目标网络,从而对连续状态、连续动作空间进行建模:

L(\theta) = \| Q_{\omega}(s, a) - (r + \alpha h + \gamma Q_{\omega^-} (s', a')). \|

这就是朴素的 deep SARSA 算法。

再引入经验回放池,每次算法运行时,从经验池取出 (s, a, r, s'),从当前策略 \pi(\cdot | s') 采样得到一个 a',然后计算误差:

L(\theta) = \| Q_{\omega}(s, a) - (r + \alpha h + \gamma Q_{\omega^-} (s', a')). \|

使用完全类似于 DQN 的计算方法,反向传播更新 Q 网络,并且每隔一定的时间复制一份目标网络,Q 网络就会不断地逼近当前策略的动作价值函数 Q。

Actor——策略提升

假设我们已经有一个较好地估计当前策略的 Q 网络 Q_{\omega},现在我们尝试来估计一个更好的 policy。如果是一般的 RL,我们就有策略提升定理:

\pi'(a | s) = \delta_{\arg \max Q(s, \cdot)\}}(a).

这里我们使用的是当前策略的 Q 函数 Q_{\pi},但据此导出了一个更好的策略 \pi'。由于策略提升定理的特点,这里构造的是一个确定性策略 \pi'。

而最大熵 RL 中,策略提升定理需要做一定的修改。我们依然是用当前的策略的 Q 函数导出一个更好的策略,但是由于优化目标多了一个熵项,我们要做的问题变成了这样的一个优化:

\max_{\pi'(\cdot | s)} \mathbb{E} [Q^{\pi}(s, A) - \alpha \log \pi'(A | s)].

其中 A \sim \pi'(\cdot | s),是当前策略在状态 s 下的动作。

上述这个优化在 A 离散时有解析解,但是复杂度和动作空间的大小有关;而连续动作则涉及积分,一般无法计算。所以,我们采用一步采样来代替上述优化。经过数学推导,这一步优化等价于最小化目标

\min_{\pi'} \mathbb{E} [\alpha \log \pi'(A | s) - Q^{\pi} (s, A)], \quad \forall s \in \mathcal{S}.

这一步优化的结果一般不再是一个确定性策略,这就是 soft 的一种体现。

而如果我们把 s 也改为一个随机变量 S,优化就成为了:

\min_{\theta} \mathbb{E} [\alpha \log \pi_{\theta}(A | S) - Q_{\omega} (S, A)].

这就是 SAC 的 loss 函数,其中 S 的分布 d(s) 有相当的自由性,只要保证其支集覆盖了状态空间的所有状态(即所有状态出现的概率密度都非 0),我们就能在数学上保证两个最小化是等价的。

在深度学习中,我们只能用有限的数据集(也就是 Replay Buffer)去代替这里的任意的 s 或者随机变量 S,期望它的泛化能力能够使得它学会其中的内在规律,就像朴素的图像分类算法一样。写成随机变量的形式也更加方便看出理论公式和深度学习间的联系。

需要注意的是,在 loss 函数

L(\theta) = \mathbb{E} [\alpha \log \pi_{\theta}(A | S) - Q_{\omega} (S, A)]

中,A 同样是一个取决于参数 \theta 的随机变量:

A \sim \pi_{\theta}(\cdot | s).

由于“采样”不是一个可以反向传播的计算过程,我们需要引入重参数化(reparameterization)方法,变成:

A = f_{\theta}(\varepsilon, S), \quad \varepsilon \sim \mathcal{N}(0, I).

因此,反向传播时,Q_{\omega} 虽然参数冻结,但仍然必须反传梯度。

SAC——广义策略迭代

现在我们尝试把 Actor 和 Critic 组合起来。我们发现,之前在 Sarsa 出现过的问题在这里再次出现:我们需要先估计一个准确的 Q (Critic),再对 policy (actor) 进行提升。那么这里的解决方法也是相似的,我们用广义策略迭代算法,实现边估计边提升。算法的大致步骤如下:

循环:

  1. 根据当前策略 \pi_{\theta},大量执行 s \xrightarrow{a} s',获得奖励 r,放入 Buffer
  2. 从 Buffer 中采样若干个 s, a, r, s',从当前策略采样 a',直接用 TD 误差更新 Q 网络 Q_{\omega}
  3. 冻结 Q_{\omega} 的参数 \omega,从 Buffer 中采样若干个 s,再从当前策略 \pi_{\theta} 采样 \tilde{a}(注意重参数化),依据 SAC 的 Loss 更新策略
BEYOND THE ARTICLE

读完了,有什么想法?

阅读已保存的问答示例,并循着引用回到原文。

查看公开问答示例
— 本文完 — 返回文章列表