前言
Deep Q-learning(深度Q学习),也叫做Deep Q-network(深度Q网络),最早也是最成功的将强化学习和深度神经网络结合起来的算法。
推荐阅读2015年,发表在nature上的论文(首次发表在2013年),跳转论文~
Q-learning
在介绍DQN之前,先简单了解一下Q-learning,其实从名字就能看出来两者之间的关系,DQN实质上就是在Q-learning中引入了深度神经网络~
Q-learning属于一种时序差分学习算法,也就是我们所熟悉的TD-learning,从下图关于TD算法的表达式中可以看出来:

1、TD算法在干什么——在无模型的情况下求解贝尔曼公式(关于贝尔曼公式,如有疑惑,跳转至这里~)
2、TD算法的目的——求解给定策略下的状态价值
类似于蒙特卡洛算法,Q-learning算法本质上是在无模型的情况下对最优动作价值进行近似,从而学习最优策略。我们给出Q-learning的算法表达式,能看出什么?

对比一下,可以很直观的得出Q-learning的特点:
1、Q-learning在干什么——在无模型的情况下求解贝尔曼最优公式
2、Q-learning的目的——对最优的动作价值进行估计
在低维离散的状态和动作空间下,Q-learning一般是使用一个Q-table来存储Q值,进行迭代优化。但是当状态和动作空间高维连续时,使用基于表格的方法就不太现实(毕竟总不能把所有的Q值都一一列出来~),基于此,采用函数拟合的方式。而面对高维且连续的情况,使用深度神经网络来提取特征就十分合适了。
DQN
在DQN算法中,我们首先需要确定一个目标函数,也就是损失函数。
回顾一下Q-learning,是对最优贝尔曼公式的求解,可以视为损失函数中的 target。

因此,我们构造的损失函数如下:

给出损失函数构造框图:

DQN的目标,就是不断的学习更新参数
w
w
w,使得损失函数(error)最小。当损失函数为 0时,此时所采用的神经网络近似为 target,可以认为预测值(由神经网络得到)
q
^
(
S
,
A
,
w
)
\hat{q}(S,A,w)
q^(S,A,w)和最优动作价值
R
+
γ
m
a
x
q
^
(
S
′
,
a
,
w
)
R+{\gamma}max\hat{q}(S',a,w)
R+γmaxq^(S′,a,w)相等。
那么如何最小化损失函数呢?——梯度下降
其实,从本质上来讲,DQN算法就是使用深度神经网络 q ^ ( S , A , w ) \hat{q}(S,A,w) q^(S,A,w) 来代替Q-learning中的 q t ( s t , a t ) q_t(s_t,a_t) qt(st,at),那么DQN就到此结束了吗?
怎么可能……
使用非线性函数逼近器(如神经网络)来表示动作价值函数,算不得什么创新之举,真正有意思的地方在于发 nature 的大佬解决了这么两个问题:
1、相关性
2、自举
容我娓娓道来~
相关性
在训练DQN的时候,每次我们用一个四元组对DQN中的参数进行一次更新。我们希望相邻两次使用的四元组是独立的,但是当智能体收集经验的时候,相邻两个四元组 ( s t , a t , r t , s t + 1 ) (s_t,a_t,r_t,s_{t+1}) (st,at,rt,st+1) 和 ( s t + 1 , a t + 1 , r t + 1 , s t + 2 ) (s_{t+1},a_{t+1},r_{t+1},s_{t+2}) (st+1,at+1,rt+1,st+2) 有着很强的相关性。因此依次使用这些强相关的四元组训练DQN时,训练效果往往会很差。
解决方法——经验回放!
经验回放(experience replay)是强化学习中一个重要的技巧,可以大幅度提升强化学习的表现。
经验回放的意思是把智能体与环境交互的记录(经验)储存到一个数组中,时候反复利用这些经验训练智能体。
这个数组被称为经验回放数组(replay buffer)。

具体来讲,将智能体的轨迹分为 ( s t , a t , r t , s t + 1 ) (s_t,a_t,r_t,s_{t+1}) (st,at,rt,st+1) 这样的四元组,存入一个数组。需要认为指定数组的大小( b b b),数组中只保留最近 b b b 条数据。
当数组存满之后,删除掉最旧的数据。数组大小 b b b 是个需要调节的超参数,会影响训练的结果。通常设置 b b b 为 1 0 5 10^5 105~ 1 0 6 10^6 106。
经验回放每次从数组中随机抽取一个四元组,用来对DQN参数做一次更新。
这样做的好处:
1、对数据进行随机化,消除观测序列中的相关性,并平滑数据分布的变化;
2、充分提高数据的利用率;
给出一个收敛曲线

注:经验回放只能用于异策略。
自举
从DQN的损失函数中,不知道各位盲生能不能发现什么华点。——有没有发现,我们要更新的
w
w
w,出现了两次?
有人说,出现了两次,有什么大不了的,冲就完事儿了。
可是各位,我们来分解一下。
q
^
(
S
′
,
a
,
w
)
\hat{q}(S',a,w)
q^(S′,a,w)是属于损失函数中的target部分,而
q
^
(
S
,
A
,
w
)
\hat{q}(S,A,w)
q^(S,A,w)是我们要用来拟合的DQN。TD算法中的target部分基于了DQN自己做出的估计,然后再去用DQN去拟合target?
这就相当于用DQN自己做出的估计去更新DQN自己!——自举
另外,从赵世钰老师的《强化学习的数学原理》来讲,这样求导也不太方便。
我们回到“自举”产生的原因——DQN的更新使用了和DQN相关的target网络。那这样的话就简单明了,想要切断“自举”,可以用另一个神经网络计算TD目标,而不是用DQN自己计算TD目标。另一个神经网络被称为目标网络(target network),将其表示为
q
^
(
S
′
,
a
,
w
T
)
\hat{q}(S',a,w_T)
q^(S′,a,wT),这样的话,损失函数就可以表示为

上图可以看出,红色的target网络和蓝色的Q值网络中的参数分别为 w T w_T wT 和 w w w。
说明:
Q值网络用来计算策略选择的Q值和Q值迭代更新,梯度下降以及反向传播等。
target网络用来计算TD target中下一状态的Q值,网络参数更新来自Q值网络参数复制。
步骤阐明:
1、使用Q值网络
q
^
(
S
,
A
,
w
)
\hat{q}(S,A,w)
q^(S,A,w) 进行正向传播;

2、使用target网络 q ^ ( S ′ , a , w T ) \hat{q}(S',a,w_T) q^(S′,a,wT) 进行正向传播;

3、计算TD target 和TD error;

4、对Q值网络做反向传播,得到梯度
∇
q
^
(
S
,
A
,
w
)
\nabla \hat{q}(S,A,w)
∇q^(S,A,w);
5、进行梯度下降,跟新Q值网络参数;

6、更新目标网络中的参数。
以上是结合了经验回放和双网络的DQN。
总结
给出文中DQN完整伪代码:

给出算法流程框图:

本文仅仅讨论算法原理,并不涉及代码复现,目前网上相关代码学习挺多,可以移步 这里 参考~
参考资料
Zhao, S… Mathematical Foundations of Reinforcement Learning. Springer Nature Press and Tsinghua University Press.
王树森——深度强化学习
参考博客:https://blog.csdn.net/u013236946/article/details/72871858?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task