深度 Q 网络
深度 Q 网络(Deep Q Network,DQN)是一种基于 Q-Learning 和深度学习的算法,是第一个深度强化学习(Deep Reinforcement Learning, DRL)的算法,于 2015 年提出。
动机
表格型强化学习存在的问题:
- 维度灾难
- 泛化性差。对于未探索过的状态—动作对,表格中的数值完全没有更新过,导致 agent 的表现很差。
原理
使用深度神经网络代替原本 Q-Learning 中的 Q 表,即称为深度 Q 网络。
下面介绍的这种方法直接将 Q-Learning 与深度学习结合,为了与其他优化的方法区分,称为 Classic DQN。
损失函数
用 DNN 代替表格后,关键在于如何更新神经网络。
由于 Q 表的更新公式是:
当算法接近收敛时,Q 表将几乎不再更新,代表 TD 误差 r_t + \gamma \max_{a' \in \mathcal{A}} Q(s', a') - Q(s, a) 一项接近于 0。
因此,可以想到将 Q 网络的损失直接定义为 TD 误差:
上式可以视为 r_i + \gamma \max_{a' \in \mathcal{A}} Q(s'_i, a') 与 Q(s_i, a_i) 之间的均方误差。
直接用上述损失函数,配合反向传播算法,代替 Q-Learning 中表格的参数更新步骤,得到的算法称为 Naive DQN。这种算法的训练过程非常不稳定,具体将在下文解释。
经验回放
Naive DQN 的训练样本不满足独立同分布。在一个 episode 中,上一步和下一步的相关性很强,导致训练不稳定。经验回放(experience replay)是一种解决样本不独立同分布的方法。
每次通过环境交互采样得到四元组 (s, a, r, s') 后,存入缓存 \mathcal{B},然后在训练时随机从缓存 \mathcal{B} 随机采样。
经验回放池的一种通常实现是:固定容量,当数据超过容量时,删除最旧的数据,再加入新数据。实现上,通常除了四元组 s, a, r, s' 还记录是否是终止状态(done)。以下是实现的代码:
class ReplayBuffer:
def __init__(self, capacity):
self.capacity = capacity
self.buffer = deque(maxlen=capacity) # <- 使用 deque 实现快速删除
def add(self, state, action, reward, next_state, done):
if len(self.buffer) >= self.capacity:
self.buffer.popleft()
self.buffer.append((state, action, reward, next_state, done))
def sample(self, batch_size):
indices = np.random.choice(len(self.buffer), batch_size)
batch = [self.buffer[i] for i in indices]
return zip(*batch)
def __len__(self):
return len(self.buffer)
经验回放池中,给定 s, a 后,r, s' 实际上都由环境模型决定,因此其中所有的数据都是“真实”数据,都可用于训练,并不需要在目标网络的参数更新后重新采样。
但是 s, a 的取值则与采样策略(如 \epsilon-greedy)有关,需要尽可能让网络接触“有价值”的数据。
目标网络
严格来说,Q 网络的损失函数并不是梯度下降方法。对于损失函数:
当 Q 网络的参数 \theta 更新时,其拟合的目标 \max_{a' \in \mathcal{A}} Q(s'_i, a') 也在变动,导致训练很不稳定。
因此准备两套网络:实时更新的网络和目标网络,目标网络的结构与实时网络完全相同,只是使用了较旧的、固定的参数 \theta^-,因此记为 Q_{\theta^-}。目标网络用于计算损失函数的目标值,损失函数公式变为:
目标网络的存在使得训练更加稳定。
DQN 的改进
Double DQN
在 Classic DQN 中,Q 值容易被过高估计(overestimation)。
使用两个 Q 网络,一个估计动作的价值,一个更新参数。具体地说,计算 Q 值和损失函数时,我们首先由当前的网络选出最优动作:
然后再计算损失函数:
实际上这又产生了 Naive DQN 的训练不稳定问题,但实践证明,Double DQN 通常比标准DQN更稳定,性能也更好,因为它能得到更准确的价值估计。
Dueling DQN
优先经验回放
对具有较高 TD 误差的四元组 (s_i, a_i, r_i, s_i') 给予较高的优先级。
优缺点
DQN 通常仅用于具有离散动作的环境。
读完了,有什么想法?
阅读已保存的问答示例,并循着引用回到原文。