因此,即使先前状态的资格跟踪值不为零,在上述情况下,delta 的值也将为零(因为最初奖励和效用函数初始化为 0)。那么,先前的状态如何在第一次更新时获得除零以外的其他效用值?
你是对的,在第一次更新中,所有的奖励和更新仍然是0
(除非我们已经设法一步达到目标,那么奖励将不会是0
)。
但是,资格痕迹e_t
将继续“记住”或“记住”我们之前访问过的所有状态。因此,一旦我们确实设法达到目标状态并获得非零奖励,资格跟踪仍将记住我们经历的所有状态。这些状态在资格跟踪表中仍将具有非零条目,因此一旦您观察到第一个奖励,就会立即获得非零更新。
资格跟踪表在每个时间步都会衰减(乘以gamma * lambda_
),因此很久以前访问过的状态的更新幅度将小于我们最近访问过的状态的更新幅度,但我们将继续记住所有这些状态,它们将有非零条目(假设gamma > 0
和lambda_ > 0
)。这允许更新所有访问状态的值,而不是在我们到达那些状态时,而是在我们观察到非零奖励时(或者,在第一个时期之后的时期中,一旦我们达到一个状态在某个较早的时间点访问它们之后,我们已经有一个现有的非零预测值).
同样在给定的 python 实现中,在单次迭代后给出以下输出:
[[ 0. 0.04595 0.1 0. ]
[ 0. 0. 0. 0. ]
[ 0. 0. 0. 0. ]]
这里只更新了 2 个值,而不是如图所示的所有 5 个先前状态。我在这里缺少什么?
他们的代码的第一部分如下所示:
for epoch in range(tot_epoch):
#Reset and return the first observation
observation = env.reset(exploring_starts=True)
因此,每个新纪元,他们首先使用exploring_starts
标志重置环境。如果我们看一下他们的环境的实现,我们会看到这个标志的使用意味着我们总是从一个随机的初始位置开始。
因此,我怀疑,当运行代码以生成该输出时,初始位置只是随机选择为目标左侧两步的位置,而不是左下角的位置。如果初始位置被随机选择为已经更接近目标,则代理只会访问您看到非零更新的那两个状态,因此这些也是资格表中唯一具有非零条目的状态跟踪,因此是唯一具有非零更新的状态。
如果初始位置确实是左下角的位置,那么算法的正确实现确实会更新沿该路径的所有状态的值(假设没有添加额外的技巧,例如将条目设置为0
如果它们碰巧得到“足够接近”0
由于腐烂)。
我还想指出,该页面上的代码实际上存在一个错误:他们没有将资格跟踪表的所有条目重置为0
重置环境/开始新纪元时。应该这样做。如果不这样做,资格跟踪仍将记住在先前 epoch 期间访问过的状态,并且仍然会更新所有这些状态,即使它们在新 epoch 中没有再次访问。这是不正确的。他们的代码的正确版本应该像这样开始:
for epoch in range(tot_epoch):
#Reset and return the first observation
observation = env.reset(exploring_starts=True)
trace_matrix = trace_matrix * 0.0 # IMPORTANT, added this
for step in range(1000):
...