Prioritized DQN

1.简介

Prioritized DQN 是为了解决当在memory中均匀采样时候学习效率低下的问题。原因主要有两个:

1.我们想让new transition立马用于更新,因为这样的new experience对于explore很重要。

2.我们想让large td-error的transition立马用于更新(比如有99次失败的经历和1次成功的经历,我们希望立马学习这个成功的经历)

显然uniform sampling无法做到这两点。
于是便有了伟大的Prioritized Experience Replay.

论文在这里。
代码在这里。
简单介绍在这里。

下面我将分享自己学习这篇论文的时候一些经验。请读完论文和简单介绍后,如有困惑,再阅读以下部分。

2.关键点

Prioritized DQN能够成功的主要原因有两个:sum tree这种数据结构带来的采样的O(log n)的高效率,和Weighted Importance sampling的正确估计。后者,我现在还没有完全搞明白原理。

我简单由谈下自己对于sum tree数据结构的理解。 sum tree存储的元素是样本的优先级,其思想是根据累积概率密度(因此叫sum)来抽取样本。从最左方开始,优先级累积逐渐增大,如果我们的段>左子孩子,(递归地)就在右子孩子中寻找(这时候要做减法,以便又是新的累积优先级)。

如果把累积优先级(离散地)画出来,我们就会发现,高优先级对应的直线段斜率最大,被抽取到的概率最大。(可以以下图为例,自己在每个段中取数字进行验证)。

sum tree.png

3.代码解读

原代码注释较少,我这里列出几个点,方便大家阅读代码。

  • 代码实现的是DQN, 而不是Double DQN。
  • 在插入new transition更新sum tree的时候, 是根据新样本与原来位置的样本的优先级差来更新。(详见SumTree.add)
  • 在memory中插入new transition的时候,给予new transition最大的优先级,因为我们想让new experience立马用于学习。(详见Memory.store)
  • 在memroy中抽取n个samples后,我们会根据nn计算出来的TD-error来更新那些抽取到的样本的优先级,这样的话new transition就不会一直被学习。(详见Memory.batch_update)。

大家最好照着源码自己敲一编(时间大概2~3小时),我这里给出自己在搬砖过程中写的一点注释(也可以自己下载,照着看)。

import numpy as np
import tensorflow as tf

np.random.seed(1)
tf.set_random_seed(1)


class SumTree(object):
    data_pointer = 0

    def __init__(self, capacity):
        self.capacity = capacity
        self.tree = np.zeros(2 * capacity - 1)
        # [------------ Parent nodes -------------][------ leaves to recode priority ----------]
        #            size: capacity - 1                  size: capacity
        self.data = np.zeros(capacity, dtype=object)
        # [------------ data frame ---------------]
        #            size: capacity

    # memory store_transition的时候使用
    def add(self, p, data):                     # p is the new priority, data is transition
 
    # memory batch_update的时候使用
    def update(self, tree_idx, p):

    # memory 分段采样的时候使用
    def get_leaf(self, v):
        parent_idx = 0
        while True:
            cl_idx = 2 * parent_idx + 1
            cr_idx = cl_idx + 1
            if cl_idx >= len(self.tree):   # 此时parent就是叶子结点
                leaf_idx = parent_idx
                break
            else:
                if v <= self.tree[cl_idx]:  # <= 左子孩子,就向左前进
                    parent_idx = cl_idx
                else:
                    v -= self.tree[cl_idx]  # > 右子孩子,需要重新当作一颗累积树,因此要减去左子孩子的值
                    parent_idx = cr_idx

        data_idx = leaf_idx - (self.capacity + 1)
        return leaf_idx, self.tree[leaf_idx], self.data[data_idx]

    @property
    def total_p(self):
        return self.tree[0]   # the root


class Memory(object):
    epsilon = 0.01     # small amount to avoid zero priority
    alpha = 0.6         # [0, 1] convet the importance of TD error to priority
    beta = 0.4          # importance sampling, from intial value increasing to 1
    beta_increment_per_sampling = 0.001
    abs_err_upper = 1   # clipped abs error

    def __init__(self, capacity):
        self.tree = SumTree(capacity)

    # 向sum tree的transitions 中加入 new transition
    def store(self, transition):

    # 从sum tree中采取n个样本
    def sample(self, n):

    # 更新采样过的样本的priority(基于abs_error)
    def batch_update(self, tree_idx, abs_error):
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,719评论 0 33
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,424评论 25 707
  • 风不停地敲打着半掩的窗户,室内凉爽了许多,吃完药虽口苦但胃暖了许多,入眠也就更容易了。 半夜忽被重...
    雪舞冰封阅读 232评论 0 1
  • 十里春风透衣裳, 穿过风雨的忧伤, 卸下负累的行囊。 在芳菲深处与你邂逅流年暗香, 暖阳扫枯黄一场风花梦蝶的乐章,...
    陶韵阅读 124评论 0 0
  • 阳光正好 微风不燥 你刚好微笑 我恰好爱上
    锑锅盖盖儿阅读 297评论 0 0