| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 人工智能 -> 强化学习(四):Prioritized Replay DQN、Dueling DQN,附源码解读 -> 正文阅读 |
|
[人工智能]强化学习(四):Prioritized Replay DQN、Dueling DQN,附源码解读 |
强化学习(四):Prioritized Replay DQN、Dueling DQN,附源码解读本次将带来另外两个DQN算法的变种,Prioritized Replay DQN和Dueling DQN; 1 Prioritized Replay DQN 之前的DQN算法中在经验回访中利用的是均匀分布采样,而这种方式看上去并不高效,对于智能体而言,这些数据的重要程度并不一样,因此提出优先回放(Prioritized Replay)的方法。优先回放的基本思想就是打破均匀采样,赋予学习效率高的样本以更大的采样权重。 一个理想的标准是智能体学习的效率越高,权重越大。符合该标准的一个选择是TD偏差δ。TD偏差越大,说明该状态处的值函数与TD目标的差距越大,智能体的更新量越大,因此该处的学习效率越高。 优先回放DQN主要有三点改变: (1)为了方便优先回放存储与及采样,采用sumTree树来存储;
算法流程:
sumTree的结构如图示,其中序号表示节点的索引值index,从0开始。要存储的优先级放在树的叶结点上,也就是最下面一层,其中叶节点同时还存储<s、a、r、s_>等信息。叶节点上面的父节点存储的是左右子节点的优先级值之和。
在sumTree中存在一个data结构,其存储的就是<s、a、r、s_>的信息。
设置一个write来对应p值对应的data信息存储,每存一个信息,write就加1,所以p值的data信息索引值即为write,并且p值的索引值与叶子节点的索引值之差为capacity-1。 父节点的索引值:每两个子节点对应一个父节点,所以父节点的索引值=(左边子节点的索引值-1)/ 2; 每添加一个p值,整棵树都需要更新一下与这个p值有关的所有父节点; 定义一个根据数字s来描述采样节点的算法:从根节点开始比较,即index=0,如果左边的子节点的p值比s大,则走左边子节点这条,如果左边子节点小于s,则走右子节点,但s值要减去左子节点的p值,按照这个规则,一直找到叶结点,返回其索引,以及对应的q值,还有对应的data。 2 Dueling DQN Dueling DQN尝试通过优化神经网络的结构来优化算法,将Q网络分成两部分,第一部分与状态s有关,而与具体要采用的动作无关,这部分叫做价值函数部分,第二部分同时与状态s和动作a有关,这部分叫做优势函数部分,最终的价值函数表示: 价值函数:
最终的价值函数表示:
源码解读 其中Dueling DQN代码跟之前的DQN代码差不多,在此不做分析; 这里主要讲一下Prioritized Replay DQN代码中的sumTree部分,莫烦大佬这里写的不是特别好理解,我结合了网上的概念以及github上的源码进行理解; 首先是sumTree中,其中的data_pointer就是前面理论部分里的write,指的就是叶节点的位置; __init__函数定义了tree和data,data是叶节点的,用于存储数据的,tree是整个树的节点总数,代码中叶节点有10000个,所以tree的数据是19999个; add函数: tree_idx计算的是叶节点的”坐标“;在前面理论部分可以看到,叶节点的"坐标"是与write差capacity-1的,而write就是代码中的data_pointer;
update函数:
这里的change是更新了叶节点的优先级p值后,其父节点的p值也要更新,所以就是父节点原本的p值+change; tree_idx = (tree_idx - 1) // 2 计算的就是父节点,前面理论部分有介绍; get_leaf函数: 该函数返回的是数据data、叶节点的索引值index以及对应的优先级p值; 这里是一个从顶点向叶节点的搜索过程,可以结合前面的理论部分理解这段代码
total_p函数具体作用还是很迷,它的值好像一直是10000?就是说是叶节点的总数。 然后是Memory,这一部分比sumTree的理解要难一些; 刚开始定义几个值,然后__init__函数就是建立树sumTree; store函数:
讲一下self.tree.tree[-self.tree.capacity:],为什么是-self.tree.capacity,因为这一行代码找的是叶节点,但是tree中不仅包含了叶节点,还有其父节点,比如有19999个节点,叶节点的个数是10000个,那么按照存储规则来看的话叶节点是最后10000个数据,所以是-self.tree.capacity,意思就是从最后一个数据开始找,从最后往前开始数10000个数据,就都是叶节点的数据了; sample函数:
第二行代码pri_seg = self.tree.total_p / n,这里就涉及到了sumTree取数据了。比如我要取两个数据,整体的优先级p值是100,那么我就要从[0,50)中取一个数据,再从[50,100)中取一个数据,就是说先均匀分割整个树,分割的数量按照你需要的数据数量来,然后再从每一个分割后的树中按p值选取一个数据;这就是这一步的作用,就是分割的作用; 后面的代码就没细看的,有的跟计算权重ISWeight有关; batch_sample函数的作用是选取完数据后更新tree中的优先级p值,当然除了叶节点之外其父节点也要对应更新。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/17 22:41:56- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |