经验回放(experience replay)
在DQN算法中,为了打破样本之间关联关系,通过经验池,采用随机抽取经历更新参数。但是,对于奖励稀疏的情况,只有N多步正确动作后才有奖励的问题,会存在能够激励Agent进行正确学习的样本很少,采用随机抽取经历得方式,效率会很低,很多样本都奖励为0的,没什么区别。
解决这个问题的主要从两方法考虑,经验存储方法,经验抽取的方法,目前主要采用经验抽取的方法。
优先经验回放
优先经验回放就是抽取经历时,优先抽取最有价值的经历,但是又不能只抽取最有价值,不然会造成过拟合,应该是价值越高的,抽取到的概率越大,价值最低的,也有一定的概率抽到。
衡量经验的价值
如何确定一个经验的价值呢?在DQN中,核心更新公式
Q
w
(
s
t
,
a
t
)
=
Q
w
(
s
t
,
a
t
)
+
[
r
t
+
1
+
γ
m
a
x
a
Q
w
(
s
t
+
1
,
a
t
+
1
)
−
Q
w
(
s
t
,
a
t
)
]
Q_w(s_t,a_t)=Q_w(s_t,a_t)+[r_{t+1}+\gamma max_aQ_w(s_{t+1},a_{t+1})-Q_w(s_t,a_t)]
Qw(st,at)=Qw(st,at)+[rt+1+γmaxaQw(st+1,at+1)−Qw(st,at)]
其中,TD-error:
δ
t
=
r
t
+
1
+
γ
m
a
x
a
Q
w
(
s
t
+
1
,
a
t
+
1
)
−
Q
w
(
s
t
,
a
t
)
\delta_t=r_{t+1}+\gamma max_aQ_w(s_{t+1},a_{t+1})-Q_w(s_t,a_t)
δt=rt+1+γmaxaQw(st+1,at+1)−Qw(st,at)
我们的目标就是让TD—error近可能小,如果TD-error比较大,意味着我们当前的Q函数离目标的Q函数差距还很大,应该多进行更新,因此用TD-error来衡量经验的价值。
为了不让网络过拟合,通过概率方式进行抽取经验,保证即使是TD-error为0的经验也能被抽取到。令每个经验的优先值为:
P
(
i
)
=
p
i
∑
p
i
P(i)={p_i \over \sum p_i}
P(i)=∑pipi
其中
p
i
=
∣
δ
t
+
ϵ
∣
p_i=|\delta_t+\epsilon|
pi=∣δt+ϵ∣,其中
ϵ
\epsilon
ϵ是一个很小的值,防止TD-error为0的经验被抽取到的概率不会为0。
高效优先经验抽取
给每个经验都打上了各自的被抽取到的优先值,如何进行高效的抽取经验呢,遍历整个经验池选择优先值高的,显然会耗费大量的计算资源,反而造成模型训练变慢。一种方法为sum-tree的数据结构。
把每个经验的优先值当做叶子节点,两节点一直往上叠加,构成一个二叉树,树根的值就是所有经验的优先值的和。
抽样时,就将根节点的总的优先值除以batch_size,划分为batch_size个区间,每个区间随机抽取一个数,从根节点处往下搜寻叶子节点。假设总的优先值是42的话, 我们如果抽6个样本, 这时的区间可能是这
[0-7], [7-14], [14-21], [21-28], [28-35], [35-42]
然后在每个区间里随机选取一个数. 比如在区间[21-28]里选到了24, 就按照这个 24 从最顶上的42开始向下搜索. 首先看到最顶上42下面有两个 child nodes, 拿着手中的24对比左边的 child29, 如果 左边的 child 比自己手中的值大, 那我们就走左边这条路, 接着再对比29下面的左边那个点13, 这时, 手中的 24 比13大, 那我们就走右边的路, 并且将手中的值根据13修改一下, 变成 24-13 = 11. 接着拿着 11 和16左下角的12比, 结果12比 11 大, 那我们就选 12 当做这次选到的 priority, 并且也选择 12 对应的数据。
代码实现
待续
————————————————
参考:
原文链接:https://blog.csdn.net/yyyxxxsss/article/details/80858127