文章目录
前言
大家好!欢迎来到“从代码学习深度强化学习”系列。在之前的文章中,我们可能已经了解了深度Q网络(DQN)的强大之处,它通过结合深度学习和Q-Learning,成功地让智能体在Atari游戏等复杂环境中达到了超人类水平。
然而,经典的DQN并非完美无缺。为了解决其存在的一些问题(如Q值过高估计、样本效率不高等),研究者们提出了一系列改进版本,共同构成了“DQN家族”。今天,我们将深入探讨其中一个非常重要且高效的改进——Dueling DQN。
Dueling DQN的核心思想非常巧妙,它通过改变网络结构,将状态的价值和每个动作的优势分离开来,使得智能体能够更高效地学习。这在某些状态下,无论采取何种动作都影响不大的场景中尤其有效。
在本篇博客中,我们将首先从理论层面剖析Dueling DQN的架构和原理,然后通过一个完整的PyTorch代码实例,手把手地带您实现一个Dueling DQN智能体,并将其应用于OpenAI Gym的“倒立摆(Pendulum)”环境中。让我们一起开始吧!
完整代码:下载链接
一、Dueling DQN 核心思想
在深入代码之前,我们必须先理解Dueling DQN的理论基础。与传统的DQN直接输出每个动作的Q值不同,Dueling DQN将这个过程分解为了两部分:状态价值函数 V(s) 和 优势函数 A(s, a)。
如上图所述,我们将动作价值函数Q减去状态价值函数V的结果定义为优势函数A,即:
A ( s , a ) = Q ( s , a ) − V ( s ) A(s, a) = Q(s, a) - V(s) A(s,a)=Q(s,a)−V(s)
这个公式直观地告诉我们,优势函数A衡量的是在状态s
下,采取动作a
相比于平均水平有多好。在同一个状态下,所有动作的优势值之和为0,因为所有动作的期望价值就是这个状态的价值。
因此,在Dueling DQN中,Q网络被建模为状态价值V和优势函数A的和:
Q η , α , β ( s , a ) = V η , α ( s ) + A η , β ( s , a ) Q_{\eta,\alpha,\beta}(s, a) = V_{\eta,\alpha}(s) + A_{\eta,\beta}(s, a) Qη,α,β(s,a)=Vη,α(s)+Aη,β(s,a)
这里的 V(s) 是状态价值函数,A(s,a) 是该状态下不同动作的优势函数。这个网络结构通常包含一个共享的前几层网络(参数为η),用于提取状态特征,然后分为两个独立的分支:一个用于输出V值(参数为α),另一个用于输出A值(参数为β)。
Dueling DQN的网络结构如下图所示,输入状态经过共享层后,分流到两个分支,最后再合并得到最终的Q值。
1.1 可辨识性问题(Identifiability Issue)
将Q值分解为V和A虽然巧妙,但也带来了一个问题:V和A的建模不唯一。
如上图所述,对于一个给定的Q值,我们无法唯一地确定V和A。例如,如果我们将V值加上一个任意常数C,再将所有A值减去这个常数C,最终得到的Q值保持不变。这会导致训练过程中的不稳定性。
为了解决这个问题,Dueling DQN引入了一个约束,强制让优势函数分支中被选中的最优动作的优势函数输出为0,即:
Q η , α , β ( s , a ) = V η , α ( s ) + ( A η , β ( s , a ) − max a ′ A η , β ( s , a ′ ) ) Q_{\eta,\alpha,\beta}(s, a) = V_{\eta,\alpha}(s) + (A_{\eta,\beta}(s, a) - \max_{a'} A_{\eta,\beta}(s, a')) Qη,α,β(s,a)=Vη,α(s)+(Aη,β(s,a)−a′maxAη,β(s,a′))
1.2 更稳定的改进方案
虽然最大化操作可以确保V和A的唯一性,但在实际应用中,研究者发现用平均值代替最大化操作会更加稳定。因此,更常用的公式如下:
Q η , α , β ( s , a ) = V η , α ( s ) + ( A η , β ( s , a ) − 1 ∣ A ∣ ∑ a ′ A η , β ( s , a ′ ) ) Q_{\eta,\alpha,\beta}(s, a) = V_{\eta,\alpha}(s) + (A_{\eta,\beta}(s, a) - \frac{1}{|A|} \sum_{a'} A_{\eta,\beta}(s, a')) Qη,α,β(s,a)=Vη,α(s)+(Aη,β(s,a)−∣A∣1a′∑Aη,β(s,a′))
这个公式强制要求优势函数的均值为0。这样做的好处是,每次更新V值时,它会同时影响到所有动作的Q值,而传统的DQN在一次更新中只更新一个动作的Q值。这使得Dueling DQN能够更频繁、更准确地学习状态价值函数。
理论铺垫完成,现在让我们看看如何用代码将这些思想变为现实。
二、PyTorch 代码实践
我们将通过一个完整的项目来展示Dueling DQN的实现,包括辅助函数、核心组件(经验回放池、网络结构)以及训练循环。
2.1 辅助工具
首先,我们定义两个辅助函数:一个用于平滑奖励曲线以便更好地可视化,另一个用于将离散动作映射到连续动作空间,以适应