dqn系列梳理_强化学习--从DQN到PPO, 流程详解

说在前面

本文只讲述强化学习常见算法的实现流程, 不涉及原理推倒, 原理上的东西, 推荐看李宏毅老师的强化学习课程。

本文包括:

Nature DQN, Double DQN, Prioritized Replay DQN, Dueling DQN, Policy Gradient, Actor-Critic, DDPG, PPO算法的流程。

本文流程是基于莫凡的RL代码进行梳理。

(建议同时打开两个页面,一边看流程图, 一边看流程说明)

Nature DQN

1、将环境信息s输入到eval网络, 输出为action的Q值,选择最大Q值对应的action, 或者随机生成一个action(所谓的探索),将action输入环境, 得到奖励r和下一个环境信息s_, 存储当前环境s, 选择的action, 得到的奖励r这4个信息, 然后再将s_输入到eval网络, 循环步骤1, 直到存储了一定量的[(s, a, r, s_), …], 注意这个过程中eval网络没有更新。

2、从存储的[(s, a, r, s_), …]中sample出一部分(s, a, r, s_) ,将sample出来的多个s做为batch输入到eval 网络, 得到batch的action的Q值q_eval, 然后根据sample出来的action选出其在q_eval中对应的Q值q_action_eval(对应gather过程)。

3、将sample出来的多个s_做为batch输入到target网络(eval与target有相同的网络结构), 得到batch的action的Q值q_next, 取q_next中最大的Q值(dim=1)并乘以一个系数gamma, 然后再加上sample出来的奖励r, 得到q_target。

4、计算loss:loss 为第2步的结果q_action_eval与第3步的结果q_target的MSE, 然后根据loss反向传播更新eval网络。

5、循环1到4步骤, 每过一定的步数后,将eval网络的权重更新到target网络上。

Double DQN

Double DQN 大部分和Nature DQN是一样的, 只是在计算q_target的时候不一样:

Nature DQN计算q_target时, 直接将sample的s_输入到target网络, 得到动作的Q值, 选出最大Q值。

而Double DQN 计算q_target,是先将sample的s_输入到target网络, 得到动作的Q值q_next, 同时将sample的s_输入到eval网络,得到动作的Q值q_eval`, 选出其最大Q值对应的动作, 再通过这个动作找到对应q_next中的Q值(图中蓝色线表示的部分)也就是说用当前的Q网络来选择动作,用目标Q网络来计算目标Q值

Prioritized Replay DQN

Prioritized Replay DQN 与DQN不同的地方:

1、在于对记忆的选取是按照TD error相关的, TD error较大的记忆被选择的概率也会大一些,用sumtree这种二叉树比较容易实现这个功能。

2、loss由

改成

其中

是第j个样本的优先级权重。

下面介绍Sumtree是如何实现的:

Sumtree:设记忆量为capacity = 8, 也就是只能存储8条信息,sumtree实现上会使用2* capacity -1个节点去存储,其中最下面capacity个叶子节点存储capacity条记忆的优先级值,上面的每个节点值只是自己两个孩子节点值的和。

第一次batch sample并更新:假设batch为4, sample到7, 9, 11, 14节点(第一次因为优先级全是1, sample到的节点概率是一样的, 后面会讲解到如何进行sample),并假设这个batch经过DQN出来的td_error算出优先级为

[0.23729765, 0.30110887, 0.3370803, 0.2293545]

简写为[0.23, 0.30, 0.33. 0.22],则此时更新suntree树如下:

存储新的记忆:每learn一步后, 又会和环境互动一步,然后存储一步记忆, 记忆是在叶子节点循环存储的, 因首次存储时已经循环完一遍, 那么本次存储就循环到7号节点(7号节点为存储记忆的第一个节点, 0-6号只是算加和), 存储新记忆时, 使用的优先值为所有记忆有限值的最大值, 这里为便是1了,图如下:

那么上面batch sample, updata, store新记忆这三个步骤循环, 就是Prioritized Replay DQN了。

如何batch sample呢?

假设batch=4, 当前的sumtree如下图:

先将总的优先级值5.85分为4份为:

(0, 1.4625), (1.4625, 2.925), (2.925, 4.3875), (4.3875, 5.85),

然后在每个区间随机选一个值, 假设选的分别是:1.01,1.98, 3.50, 5.11, 那么 1.01比左边3.30小, 则选3.30, 然后又比左边2小, 则选2,然后比左边1大,则选右边8号节点的1做为样本1。1.98同理选到8号节点为样本2。

来看看3.50:比3.30大, 选2.55, 但此时3.50要减去3.30剩0.20, 0.20再去和5号节点比,小于1.33,选1.33, 然后又小于0.33,最终则选择11号节点为样本3。同理可选到13号节点为样本4.

其实这种算法的直观解释是:叶子节点的值(优先级)表示的是区间长度(如上图最下面的两排区间表示), 值越大区间长度就越长, 落在这个区间的概率就越大,1.01落在区间(1,2),那么选的就是8号节点, 3.50落在区间 (3.3,3.63) ,所以选择的就是节点11。

Dueling DQN

Dueling DQN仅仅涉及神经网络的中间结构的改进, 这里就不讲解了。

Policy Gradient

Policy Gradient是一个回合完了才会learn, 也就是更新网络。

1、将环境信息s输入到NN网络, 经过softmax后输出为action的概率(经过softmax后概率之和为1),选择概率比较大的对应的action, ,将action输入环境, 得到奖励r和下一个环境信息s_, 存储当前环境s, 选择的action, 得到的奖励r这4个信息, 然后再将s_输入到eval网络, 循环步骤1, 直到一个回合结束, 注意这个过程中NN网络没有更新。

2、回合结束后:

i. 将存储的所有s组合为一个batch输入到NN,经过softmax后输出为actions的概率actions_prob。

ii.将存储的所有action组合为actions, 然后将actions 转化为one hot形式actions_label(当前动作的位置为1(概率), 其他位置为0, 也就相当于是label了)。

iii. 将存储的奖励r经过如下公式:

R[i] = r[i]+ σ*r[i+1]+ σ2 * r[i+2]+……+ σt-i * r[t]

得到R = [R[0], R[1],…,R[t],…,R[T]]

iv. 求loss, loss = mean(cross_entropy(actions_prob, actions_label) * R)

v. 更新NN网络。

3、循环1和2。

Actor-Critic

Actor用来选动作, critic用来评估选出来的动作作用在环境上后, 得到的状态是好是坏。

1、将环境信息s输入到actor网络NN1, 输出为action的概率action_prob,选择较大概率对应的action,将action输入环境, 得到奖励r和下一个环境信息s_。

2、将s和s_分别输入到critic网络NN2, 得到输出v和v_ (评估状态的好坏)。

3、计算td_error = r + gamma * v_ - v

4、计算actor的loss = mean(td_error * (log(第一步action对应的那个概率action_prob))), 并反向传播更新actor网络NN1。

5、 计算critic的loss=square(td_error), 并反向传播更新critic网络NN2。

6、循环1-5。

DDPG

1、将环境信息s输入到actor eval网络, 输出为action, 将action输入环境, 得到奖励r和下一个环境信息s_, 存储当前环境s, 选择的action, 得到的奖励r这4个信息, 然后再将s_输入到actor eval网络, 循环步骤1, 直到存储了一定量的记忆[(s, a, r, s_), …], 注意这个过程中actor eval网络没有更新。

2、从第一步中存储的记忆中sample出部分[(s, a, r, s_), …]

3、将sample出来的s输入到actor eval网络中得到action, 再将此action与s输入到critic eval网络中得到q值。

4、求a_loss = mean(q), 反向传播更新actor eval网络(注:虽然a_loss是通过actor eval网络和critic eval网络最终求得, 但是此处只更新actor eval网络)。

5、重复步骤3, 得到更新actor eval网络后算出来的q值。

6、将sample出来的s_输入到actor target网络得到action_。

7、将sample出来的s_和第6步得到的action_一起输入critic target网络, 得到q_值。

8、计算q_target = sample出来的r + gamma * q_ 。

9、计算c_loss = MSE(第5步的结果q, q_target) 。

10、通过c_loss反向传播更新critic eval网络(注:虽然c_loss是通过actor eval、critic eval、actor target、critic target四个网络最终求得, 但是此处只更新critic eval网络)

11、循环1-10步骤, 在一定步骤后更新actor target、critic target网络,更新方式为:

W(actor target) = W(actor eval) * μ + W(actor target) * (1- μ)

W(critic target) = W(critic eval) * μ + W(critic target) * (1- μ)

也就是说actor target、critic target网络权重只是小步幅更新。

PPO

这里只介绍莫凡的简单实现, openai官网在实现上网络架构不太一样,比莫凡实现的要复杂一些,等熟读openai官网代码后再作专门解析。

1、将环境信息s输入到actor-new网络, 得到两个值, 一个是mu, 一个是sigma, 然后将这两个值分别当作正态分布的均值和方差构建正态分布(意义是表示action的分布),然后通过这个正态分布sample出来一个action, 再输入到环境中得到奖励r和下一步的状态s_,然后存储[(s,a,r),…], 再将s_输入到actor-new网络,循环步骤1, 直到存储了一定量的[(s, a, r), …], 注意这个过程中actor-new网络没有更新。

2、将1循环完最后一步得到的s_输入到critic-NN网络中, 得到状态的v_值, 然后计算折扣奖励:

R[t] = r[t] + γ*r[t+1] + γ2 * r[t+1] + … + γT-t+1 * r[T-1] + γT-t * v_, 得到R = [R[0], R[1],…,R[t],…,R[T]],其中T为最后一个时间步。

3、将存储的所有s组合输入到critic-NN网络中, 得到所有状态的V_值, 计算At = R – V_ (论文公式10, openai官网代码则实现的是论文公式11和12)

4、求c_loss = mean(square(At )), 然后反向传播更新critic-NN网络。

5、将存储的所有s组合输入actor-old和actor-new网络(网络结构一样), 分别得到正态分布Normal1和Normal2, 将存储的所有action组合为actions输入到正态分布Normal1和Normal2, 得到每个actions对应的prob1和prob2, 然后用prob2除以prob1得到important weight, 也就是ratio。

6、根据论文公式7计算a_loss = mean(min((ration* At, clip(ratio, 1-ξ, 1+ξ)* At))), 然后反向传播, 更新actor-new网络。

7、循环5-6步骤, 一定步后, 循环结束, 用actor-new网络权重来更新actor-old网络(莫凡代码是在循环开始前更新的, 效果是一样的)。

8、循环1-7步骤。

OVER...

你可能感兴趣的:(dqn系列梳理)