DRL---------DQN详解

总结一下DQN.

在传统的强化学习中,例如Q_learning以及Sarsa都需要一张由状态S以及行为A组成的Q表,行为的种类一般较少,比如常见的前进后退两种或上下左右四种等,也就是Q表的列一般还好,可是状态的话就不一定了,有些场景的状态多到可怕,就比如围棋等等,也就是Q表的行数过多,导致的结果就是难以维护如此大的一张Q表。

现在假设有一个函数 f(x)

如果输入状态S就可以得到每个行为的Q值即 Q(S)= f(S)

这不就解决了吗?只要知道这个函数,就不必再去维护那张很大的Q表。

那么怎么找到这一函数模型呢?那就是神经网络了,由于这是深度学习(DL)和强化学习(RL)的结合,所以也叫作DRL,而DQN就是DRL的一种,其是神经网络和Q_learning的一种结合,当然DQN已经有了很多改进版本,先从最基本的DQN说起。

其有两个关键技术:

冻结targetNet

experience replay(经验池)

冻结targetNet就是说每隔一段时间将训练好的神经网络参数保存下来,这里实际就是定义两个完全相同的神经网络Net1和Net2,然后Net1作为实时训练的网络,里面包括loss以及optimizer,而Net2有着与Net1相同的模型结果,但没有loss以及optimizer,没隔一段时间,就将Net1中训练到目前为止的权值和偏置值保存到Net2。

experience replay它存储了带标签的一个个数据样本,然后神经网络通过随机抽样解决了相关性及非静态分布问题。训练神经网络是需要带标签的样本的,experience replay是通过将( S , A , R , S')(当前状态,基于当前状态采取的下一行动,采取A后的奖励值,采取A后到达的下一步状态)作为一个带标签的样本,先看一下Q_learning的更新Q表公式:

Q(S,a)+=\alpha (R+\gamma max_{a}Q(S^{'},a')-Q(S,a))

这里就是将R+\gamma max_{a'}Q(S',a')作为每个样本的label,将max_{a}Q(S,a)作为S输入后的得到的预测值。

然后loss=E[(R+\gamma max_{a'}Q(S',a')-max_{a}Q(S,a))^{2}],只不过代码在这里实现的时候,要注意的就是常常不是真真取出行动最大的Q单独值做相加,而是矩阵相减,神经网络的输入是状态S,输出是该状态对应下的所有行为的Q值(当然也可以是这样:输入是状态和采取某一行为,输出是在该状态下采取这一某行为的Q值,这里我们仅按第一种情况说明。)

下面通过一个简单的例子说明:

假设该场景的每个状态有三种动作(a0,a1,a2对应0,1,2)可选

假设我们随机从experience replay抽取出一个batch(大小为4)为:

batch_1s_1a_1r_1s'_1
batch_2s_2a_2r_2s'_2
batch_3s_3a_3r_3s'_3
batch_4s_4a_4r_4s'_4

这里的a_1,a_2,a_3,a_4假设分别为0,1,1,2

r_1,r_2,r_3,r_4假设分别为2,2,2,2

即s_1是通过执行a0到达s'_1的,并且该步得到的奖励值为2,s_2是通过执行a1到达s'_2的并且该步得到的奖励值也为2,依次类推.................

那么将该batch的s作为输入到Net1得到输出为prediction:

a0a1a2
prediction_batch_1430
prediction_batch_2564
prediction_batch_3130
prediction_batch_4089

将batch的 S' 输入到Net2得到输出为target:

a0a1a2
target_batch_1260
target_batch_2420
target_batch_3249
target_batch_4325

那么先让label矩阵=prediction,然后根据a_1,a_2,a_3,a_4改变要改变的值即红色的

a0a1a2
label_batch_1430
label_batch_2564
label_batch_3130
label_batch_4089

接下来(假设\lambda =0.9

label_{-}batch_{-}1(a0)=r_{-}1+\lambda max_{a}target_{-}batch_{-}1=2+0.9\times 6=7.4

label_{-}batch_{-}2(a1)=r_{-}2+\lambda max_{a}target_{-}batch_{-}2=2+0.9\times4=5.6

label_{-}batch_{-}3(a1)=r_{-}3+\lambda max_{a}target_{-}batch_{-}3=2+0.9\times 9=10.1

label_{-}batch_{-}4(a2)=r_{-}4+\lambda max_{a}target_{-}batch_{-}4=2+0.9\times 5=6.5

即操作后label为:

a0a1a2
label_batch_17.430
label_batch_255.64
label_batch_3110.10
label_batch_4086.5

然后label-prediction即为:

a0a1a2
label_batch_13.400
label_batch_20-0.40
label_batch_307.10
label_batch_400-2.5

loss就是要优化这个矩阵,例如tensorflow框架下可以通过tf.reduce_mean(tf.squared_difference(label-prediction))进行优化,以及选什么optimizer都可以属于优化问题了,这里不做讨论。

注意:

(1)通过随机抽取experience replay中几个样本作为一个batch就解决了相关性,因为状态之间原先都是有相关性的,通过随机抽取就打乱了

(2)可以规定experience replay的大小,比如100,那么这个经验池就最多存100条记录,如果再从101时,可以采取将101替换掉现在存储的第一条,依次来不断刷新经验池

(3)每隔多长时间将Net1训练好的参数保存到Net2以及每隔多长时间训练一次神经网络都是可以设定的,这些也属于优化问题了

(4)其实一开始最容易想到的不是DQN这种框架而是只有一个Net1,那么通过将S和S'都输入到Net1来得到相应的输出进行loss计算并反向传播,但是这样就容易导致数据间存在关联性,从而使训练不稳定,所以就再用一个神经网络Net2,即由原来的r+\gamma max_{a'}Q(S',a',\Theta )-Q(S,a,\Theta )改为r+\gamma max_{a'}Q(S',a',{\color{Red} \Theta^{-}} )-Q(S,a,,\Theta)

(5)Loss以及Net1更新到Net2的部分是分时间段进行一次,experience replay是实时进行的。

(6)关于为什么能用S'作为标签让S去不断逼近,这个还是要回到Q_learning 算法,可以参考Reinforcement Learning(强化学习)Sarsa/Q_learning_爱吃火锅的博客-CSDN博客_强化学习 莫凡,注意里面max下脚表可能是a不是a',但无本质区别意思都是取最大的奖励对应的动作值。

最后一个问题就是怎么根据当前状态S选取下一步的行为,以前是有Q表,现在不需要了,因为已经通过神经网络训练了Net1(这个网络就是开头说的 f(x)),所以只需要将状态S输入到Net1中就可得到所有下一步行动的Q值,再从中挑取做大的就好了。

例如将S输入到Net1后得到:

a0a1a3
S123

那么就选a3作为下一步的行动,然后到环境中根据当前状态S和采取的下一步行动就可以得到当前奖励值r和一下步的状态S'啦,是不是很方便,当然记得要用这四个值去更新经验池,以便为训练神经网络提供样本!!!!!!!

流程图大概就是:

 其中草绿色就是两个关键技术

##############################################################################################

改进DQN版本:Double DQN

改进的地方是在如下地方:

它不在选择最大的Q值,即max_{a}target_{-}batch_{-}1作为行动值,而是将s'_1所谓Net1的输入得到输出比如输出为:

a0a1a2
s'625

那么我们就选定a0即label_{-}batch_{-}1(a0)=r_{-}1+\lambda target_{-}batch_{-}1(a0)=2+0.9\times2=3.8

其他的类似,总结一下就是:

r+\gamma max_{a'}Q(S',a',{\color{Red} \Theta^{-}} )-Q(S,a,,\Theta)改为:r+\gamma max_{a'}Q(S',argmax_{a}Q(S_{t+1},a,{\color{Red} {\color{Cyan} }\Theta} ),{\color{Red} \Theta^{-}} )-Q(S,a,,\Theta)

框架为:

所以总结一下要改变的主要就是loss部分

###################################################################################################

改进DQN版本:Dueling DQN

这里是在神经网络的输出层做了文章,原来输出层是维数是:

[batch,n_actions]

下载是这样,先预算出两个:

[batch,1]和[batch,n_actions]

然后再合并两者,这里为了避免[batch,n_actions]学习最后结果为0,所以在合并的时候将[batch,n_actions]-E([batch,n_actions]),

它的主要思想就是拆分为2个,一个看作是当前状态的价值[batch,1],另一个是采取行动所得的奖励[batch,n_actions],最后将两者相加即可。对比原先的DQN的[batch,n_actions]这里就是多了一个[batch,1]

所以总结一下要改变的主要就是神经网络模型(输出部分)

######################################################################################################

改进DQN版本:Prioritised Replay DQN

这个是在神经网络抽取样本的时候做文章,原先是使用Sample的随机抽取方法,现在呢?是要将experience replay中的样本按重要性排一下顺序然后按重要性进行抽取,而不是随机,这里的重要性是用'Loss'来体现的,Loss越大,说明越需要学习,那么其重要性就对应的越高。

核心的东西就是在experience replay构建中加了一个TD-error其实就是loss

每个样本除了以前的参数还加上了这一个loss

构建的数据结构是Tree

这里应用:莫凡(【莫烦Python】强化学习 Reinforcement Learning_哔哩哔哩_bilibili

假设我们设定experience replay就是8(就是叶子结点数),其中的数值就是重要等级数。

当进来一个样本的刷新的时候,就从叶子结点左到右依次更新,比如这次更新了上图中红色的这个,下次再有新的样本进来,那么就该替换绿色的啦。当然更新后因为绿色地方的重要等级变了,所以相应的紫色都得改变。

抽取的时候,这里就直接看一下莫凡给的类子吧,很好理解:

注意:这里的走法实际就是拿当前的值(比如这里一开始是24)每次在两个孩子结点中选取最大的那条路走,如果最大值对应的路是走左面那就顺着走就可以,如果是右面那么就要减去当前的左孩子节点的值,(如这里的24-13),如此以往直到直到叶子结点。

所以总结一下就是:主要要改一下experience replay中存储方式即memory,可以参考:

AI-blog/Seaquest-DDQN-PER.py at master · jaromiru/AI-blog · GitHub当中的Memory Class

其中用到的Tree结构可以参考:

AI-blog/SumTree.py at master · jaromiru/AI-blog · GitHub

还有就是learn(就是训练)中记得算abs_errors(errors的绝对值),然后和样本一起更新到memory中。

看到很多小伙伴私信和关注,为了不迷路,欢迎大家关注笔者的微信公众号,会定期发一些关于NLP的干活总结和实践心得,当然别的方向也会发,一起学习:


​​​​​​​

 

  • 7
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值