如何修复TF代理中policy_state和policy_state_spec之间的TypeError



我正在开发一个PPO代理,它使用TF代理播放(好吧,应该(末日。作为对代理的输入,我试图给它一个由4个图像组成的堆栈。我的完整代码位于以下链接中:https://colab.research.google.com/drive/1chrlrLVR_rwAeIZhL01LYkpXsusyFyq_?usp=sharing

不幸的是,我的代码无法编译。它在下面显示的行中返回一个TypeError(它正在Google Colaboratory中运行(。

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-10-d1571cbbda6b> in <module>()
8   t_step = tf_env.reset()
9   while (episode_steps <= max_steps_per_episode or (not t_step.is_last())):
---> 10     policy_step = agent.policy.action(t_step)
11     t_step = tf_env.step(policy_step.action)
12     episode_steps += 1
5 frames
/usr/local/lib/python3.7/dist-packages/tf_agents/utils/nest_utils.py in assert_same_structure(nest1,     nest2, check_types, expand_composites, message)
112     str2 = tf.nest.map_structure(
113         lambda _: _DOT, nest2, expand_composites=expand_composites)
--> 114     raise exception('{}:n  {}nvs.n  {}'.format(message, str1, str2))
115 
116 
TypeError: policy_state and policy_state_spec structures do not match:
()
vs.
{'actor_network_state': ListWrapper([., .])}

这个错误的原因是,就我在TF Agents文档中所读到的内容而言,用户不应该对policy_state做任何事情,因为它是基于代理的网络自动生成的。

这是我发现的一个类似的错误,但似乎并没有解决我的问题,尽管它在一个尝试过的解决方案中暗示了我:py_environment';time_step';不会';t匹配';time_step_spec';

在阅读了上面的问题和答案后,我意识到我承诺要进行这样的观察:

self._observation_spec = array_spec.BoundedArraySpec(shape=(4, 160, 260, 3), dtype=np.float32, minimum=0, maximum=1, name='screen_observation')

但我传递的是一个由4个np.array组成的列表,shape=(160260,3(:

self._stacked_frames = []
for _ in range(4):
new_frame = np.zeros((160, 260, 3), dtype=np.float32)
self._stacked_frames.append(new_frame)

我这样做是因为我认为;形状";我的数据不会改变,因为列表中的元素数量总是与observationspec的第一个维度相同。列表更容易删除过去的帧并添加新的帧,比如:

def stack_frames(self):
#This gets the current frame of the game
new_frame = self.preprocess_frame()
if self._game.is_new_episode():
for frame in range(4):
self._stacked_frames.append(new_frame)
#This pop was meant to clear an empty frames that was already in the list
self._stacked_frames.pop(0)
else:
self._stacked_frames.append(new_frame)
self._stacked_frames.pop(0)
return self._stacked_frames

我以前只尝试使用np.arrays,但无法删除过去的帧并添加新的帧。也许我做得不对,但我觉得自己就是这样_stacked_frames与观察规范的形状相同,不能简单地删除或添加新数组。

self._stacked_frames = np.zeros((4, 160, 260, 3), dtype=np.float32)
def stack_frames(self):
new_frame = self.preprocess_frame()

if self._game.is_new_episode():
for frame in range(4):
#This delete was meant to clear an empty frames that was already in the list
self._stacked_frames = np.delete(self._stacked_frames, 0, 0)
#I tried "np.concatenate((self._stacked_frames, new_frame))" as well
self._stacked_frames = np.vstack((self._stacked_frames, new_frame))
else:
self._stacked_frames = np.delete(self._stacked_frames, 0, 0)
#I tried "np.concatenate((self._stacked_frames, new_frame))" as well
self._stacked_frames = np.vstack((self._stacked_frames, new_frame))
return self._stacked_frames

这里的这种方法不起作用。就像我说的,可能我做错了。我认为有三种方法可以解决这个僵局:

  1. 我将observation_spec声明为四个帧的列表,每个帧声明为np.array(160260,3(
  2. 我像以前一样声明了observation_spec,但从self中删除和添加了帧_以正确的方式堆叠帧(不确定这是可能的,因为self._stacked_frames将被声明为np.array(4160260,3(,并且我不确定它是否可以在返回到np.arrays(41602260,3(之前变成np.arrand(31602260,2(或np.arration(51602260,4(
  3. 我仍然像以前一样声明observation_spec,但我不会删除或添加帧。我做了一个循环,将第二个帧(进入第二个插槽中的stack_frames函数(复制到第一个插槽中,将第三个帧复制到第二个槽中,第四个帧复制在第三个槽中。下图所示:
self._stacked_frames Slot: 1 | 2 | 3 | 4
Game image inside self._stacked_frames: A | B | C | D
New game image: E
New game image's positions (step 1): B | B | C | D
New game image's positions (step 2): B | C | C | D
New game image's positions (step 3): B | C | D | D
New game image's positions (step 4): B | C | D | E
New self._stacked_frames: B | C | D | E

考虑到我对问题的理解是正确的,最后一个似乎是解决问题的最确定的方法。我尝试了一下,但TypeError仍然存在。我这样试过:

self._stacked_frames = np.zeros((self._frame_stack_size, 160, 260, 3), dtype=np.float32)

然后:

def stack_frames(self):
new_frame = self.preprocess_frame()
if self._game.is_new_episode():
for frame in range(self._frame_stack_size):
self._stacked_frames[frame] = new_frame
else:
for frame in range((self._frame_stack_size) - 1):
self._stacked_frames[frame] = self._stacked_frames[frame + 1]
self._stacked_frames[self._frame_stack_size - 1] = new_frame
return self._stacked_frames

两个问题:

  1. 考虑到我对所呈现的TypeError的看法是正确的,修复它的三种方法中哪种是最好的?那么,我尝试第三种可能性的解决方案的方式有什么问题吗
  2. 考虑到我可能对TypeError的看法不正确,那么这个错误是关于什么的

我在调用policy.action(time_step)时也遇到了同样的问题。Action采用可选参数policy_state,默认情况下为";((";。

我打电话给解决了这个问题

policy.action(time_step, policy.get_initial_state(batch_size=BATCH_SIZE))

我刚开始使用TF特工,所以,我希望这不会有一些不希望的影响。

相关内容

  • 没有找到相关文章