diff --git a/docs/ch11/main.md b/docs/ch11/main.md index e44d21e..10772cf 100644 --- a/docs/ch11/main.md +++ b/docs/ch11/main.md @@ -61,7 +61,45 @@ $$ ## TD3 算法 -我们知道 `DDPG` 算法的缺点太多明显,因此后来有人对其进行了改进,这就是我们接下来要介绍的 `TD3` 算法。`TD3` 算法,英文全称为 `Twin Delayed DDPG`,中文全称为双延迟确定性策略梯度算法。相对于 `DDPG` 算法,`TD3` 算法的改进主要做了两点重要的改进,一是 双 `Q` 网络,体现在名字中的 `Twin`,二是 延迟更新,体现在名字中的 `Delayed`。这两点改进都是为了解决 `DDPG` 算法中的一些问题,下面我们分别来看一下。 +我们知道 `DDPG` 算法的缺点太多明显,因此后来有人对其进行了改进,这就是我们接下来要介绍的 `TD3` 算法。`TD3` 算法,英文全称为 `Twin Delayed DDPG`,中文全称为双延迟确定性策略梯度算法。相对于 `DDPG` 算法,`TD3` 算法的改进主要做了三点重要的改进,一是 双 `Q` 网络,体现在名字中的 `Twin`,二是 延迟更新,体现在名字中的 `Delayed`,三是 躁声正则(`Noise Regularisation`),下面我们分别来看一下。 + +### 双 Q 网络 + +双 `Q` 网络的思想其实很简单,就是在 `DDPG` 算法中的 `Critic` 网络上再加一层,这样就形成了两个 `Critic` 网络,分别记为 $Q_{\omega_1}$ 和 $Q_{\omega_2}$,其中 $\omega_1$ 和 $\omega_2$ 分别表示两个网络的参数。这样一来,我们就可以得到两个 `Q` 值,分别记为 $Q_{\omega_1}(s_t, a_t)$ 和 $Q_{\omega_2}(s_t, a_t)$, +然后我们在计算 `TD` 误差的时候,就可以取两个 `Q` 值中较小的那个,即: + +$$ +\begin{aligned} +L(\omega_1) &= \mathbb{E}_{s_t, a_t, r_{t+1}, s_{t+1} \sim D}\left[\left(Q_{\omega_1}(s_t, a_t) - y_t\right)^2\right] \\ +y_t &= r_{t+1} + \gamma \min_{i=1,2} Q_{\omega_i}(s_{t+1}, \mu_{\theta}(s_{t+1})) \\ +\end{aligned} +$$ + +其中 $L$ 表示损失函数,同理,我们也可以得到另一个 `Critic` 网络的损失函数 $L(\omega_2)$,即: + +$$ +\begin{aligned} +L(\omega_2) &= \mathbb{E}_{s_t, a_t, r_{t+1}, s_{t+1} \sim D}\left[\left(Q_{\omega_2}(s_t, a_t) - y_t\right)^2\right] \\ +y_t &= r_{t+1} + \gamma \min_{i=1,2} Q_{\omega_i}(s_{t+1}, \mu_{\theta}(s_{t+1})) \\ +\end{aligned} +$$ + +细心的读者会发现,这跟 `Double DQN` 的原理是一样的,只不过 `Double DQN` 是在 `Q` 网络上做文章,而 `TD3` 算法是在 `Critic` 网络上做文章。这样做的好处是可以减少 `Q` 值的过估计,从而提高算法的稳定性和收敛性。 + +### 延迟更新 + +延迟更新更像是一种实验技巧,即在训练中 `Actor` 的更新频率要低于 `Critic` 的更新频率。在学习过程中,`Critic` 是不断更新的,可以想象一下,假设在某个时刻 `Actor` 好不容易达到一个最高点,这个时候 `Critic` 又更新了,那么 `Actor` 的最高点就被打破了,这样一来 `Actor` 就会不断地追逐 `Critic`,这样就会造成误差的过分累积,进而导致 `Actor` 的训练不稳定,甚至可能会发散。因此,为了避免这种情况,我们就可以在训练中让 `Actor` 的更新频率低于 `Critic` 的更新频率,这样一来 `Actor` 的更新就会比较稳定,不会受到 `Critic` 的影响,从而提高算法的稳定性和收敛性。举个不太恰当的例子,`Critic` 就好比领导,`Actor`则好比员工,领导不断给员工下达目标,员工不断地去完成目标,如果领导的决策经常失误,那么员工就很容易像无头苍蝇一样不知道该完成哪些目标。因此,一个好的解决方式就是让领导学得比员工更快,领导学得更快了之后下达目标的失误率就会更低,这样员工就能够更好地完成目标了,从而提高整个团队的效率。在实践中,`Actor` 的更新频率一般要比 `Critic` 的更新频率低一个数量级,例如 `Critic` 每更新 10 次,`Actor` 只更新 1 次。 + +### 躁声正则 + +更准确地说,在原论文中不叫噪声正则,而是目标策略平滑正则化(`Target Policy Smoothing Regularization`),意思都是一样的,只是笔者在表述的时候做了简化。在延迟更新中,我们的主要思想是通过提高 `Critic` 的更新频率来减少值函数的估计误差,也就是“降低领导决策的失误率”。但是这样其实是治标不治本的做法,因为它只是让 `Critic` 带来的误差不要过分地影响到了 `Actor`,而没有考虑改进 `Critic` 本身的稳定性。因此,我们也可以给 `Critic` 引入一个噪声提高其抗干扰性,这样一来就可以在一定程度上提高 `Critic` 的稳定性,从而进一步提高算法的稳定性和收敛性。注意,这里的噪声是在 `Critic` 网络上引入的,而不是在输出动作上引入的,因此它跟 `DDPG` 算法中的噪声是不一样的。具体来说,我们可以在计算 `TD` 误差的时候,给目标值 $y$ 加上一个噪声,并且为了让噪声不至于过大,还增加了一个裁剪(clip),即: + +$$ +y=r+\gamma Q_{\theta^{\prime}}\left(s^{\prime}, \pi_{\phi^{\prime}}\left(s^{\prime}\right)+\epsilon\right) \epsilon \sim \operatorname{clip}(N(0, \sigma),-c, c) +$$ + +其中 $N(0, \sigma)$ 表示均值为 0,方差为 $\sigma$ 的高斯噪声,$\epsilon$ 表示噪声,$\operatorname{clip}$ 表示裁剪函数,即将噪声裁剪到 $[-c, c]$ 的范围内,$c$ 是一个超参数,用于控制噪声的大小。可以看到,这里噪声更像是一种正则化的方式,使得值函数更新更加平滑,因此笔者称之为噪声正则。 + ## 实战:DDPG 算法