引言
今天在编写强化学习算法时,使用ptan库的时候,发现一个问题(ptan库是一个开源强化学习算法库)。
问题是这样的,在使用ptan库中的experience.py文件时,我发现env发出done=True时,并不会立即在当前步,也就是done时输出总奖励,而是要在下一步才输出总奖励,其原因如下:
while True:
...
...
...
if len(history) == self.steps_count and iter_idx % self.steps_delta == 0:
yield tuple(history)
states[idx] = next_state
if is_done:
# in case of very short episode (shorter than our steps count), send gathered history
if 0 < len(history) < self.steps_count:
yield tuple(history)
# generate tail of history
while len(history) > 1:
history.popleft()
yield tuple(history)
# vectorized envs are reset automatically
self.total_rewards.append(cur_rewards[idx])
self.total_steps.append(cur_steps[idx])
cur_rewards[idx] = 0.0
cur_steps[idx] = 0
states[idx] = env.reset()
...
...
...
由于程序中有yield,因此首先判断是生成器,当每次调用的时候,程序会从yield后继续执行。因此done=True,进入判断函数体,并执行完最后一个yield后,就会将此回合最后一个样本返回。按理说与此同时,总奖励也应该一并给出了。但是如果按照此程序的写法,总奖励和总步数将会和新的状态,也就是reset后的新的状态生成的同时给出,在时间上并不同步。下图证明了在回合结束后,总奖励并未给出,而是当reset,进入下一个回合的时候,才会给出总奖励和总步数。
因此,在考虑了仅在step_count中最后一个样本yield后再对总奖励进行赋值的特点后,对代码进行修改如下:
while True:
...
...
...
if len(history) == self.steps_count and iter_idx % self.steps_delta == 0:
yield tuple(history)
states[idx] = next_state
if is_done:
# in case of very short episode (shorter than our steps count), send gathered history
if 0 < len(history) < self.steps_count:
if len(history) == 1:
self.total_rewards.append(cur_rewards[idx])
self.total_steps.append(cur_steps[idx])
cur_rewards[idx] = 0.0
cur_steps[idx] = 0
yield tuple(history)
# generate tail of history
while len(history)>1:
history.popleft()
if len(history) == 1:
self.total_rewards.append(cur_rewards[idx])
self.total_steps.append(cur_steps[idx])
cur_rewards[idx] = 0.0
cur_steps[idx] = 0
yield tuple(history)
# vectorized envs are reset automatically
states[idx] = env.reset()
...
...
...
代码效果如下:
可以看到已经实现了期望的目标。
在这之后,我考虑将这个改进在github上进行提交给作者,进行参考。将整个PR的过程记录如下:
pull requestS过程
1、我们首先需要将作者的项目fork到自己的仓库中,点击网页上的fork即可;
2、然后clone我们自己远程仓库中的项目到本地,即git clone的环节;
3、新建分支。由于在一个成熟的项目中,通常会有多个分支,在这里一个标准的做法是,根据哪个分支新建分支:
比如在项目中有master和test分支,如果当前在master分支,想基于test分支新建一个新分支并取名为new。可以有三种做法:
git checkout -b new test
或者想基于云端的test分支新建new分支:
git checkout -b new origin/test
或者我们先进入test分支,再新建new分支:
git checkout test
git checkout -b new
4、在新建的分支上进行改进;
5、修改完成后,可以使用git diff进行查看修改是否正确:
6、确认修改无误后,可以进行提交:
git add .
git commit -m "xxx"
7、然后提交到远端仓库,在这里还有一个小细节,由于我们在本地新建了一个分支,但是如果我们提交的时候,想将本地新建的分支提交到远端另一个分支,需要怎么做呢?
git push -u origin xxx(新分支名):master
8、这时本地的工作就做完了,需要在网页端点击pull requests:
再点击:
9、最后写清楚题目和修改说明就可以啦:
May the force be with you!
评论(0)
您还未登录,请登录后发表或查看评论