首先,这是为了进行实践和比较,我知道比线性网格更有效的方式来平铺状态空间。
要运行某种强化学习算法,我想线性地绘制状态和动作空间。结果,我希望每个空间动作对都具有数组形式。问题是,存在具有不同状态空间和动作空间尺寸的不同(gym)环境。因此,我不喜欢使用硬编码的变量或尺寸。因此,我需要给每个状态-动作对分别指定最小和最大值。
我基本上已经解决了简单的问题,但是没有一个解决方案是“漂亮的”。
首先让我们计算状态和动作空间。从最小到最大,用linspace平铺该区域。我为一个随机测试环境提供了变量。
import numpy as np
NOF_ACTION_SPACE_TILES = 20
NOF_STATE_SPACE_TILES = 10
action_low = np.array([-2])
state_low = np.array([-1, -1, -8])
action_space = np.vstack([*[x.flatten() for x in (np.meshgrid(*(np.linspace(action_low, action_high, NOF_ACTION_SPACE_TILES).T)))]]).T
state_space = np.vstack([*[x.flatten() for x in (np.meshgrid(*(np.linspace(state_low, state_high, NOF_STATE_SPACE_TILES).T)))]]).T
这将按预期方式工作,并自行给出状态和动作的所有可能组合。有什么办法可以更直接地做到这一点吗?我需要使用* []两次,因为np.meshgrid返回了多个矩阵并试图展平向量。
现在有趣的部分...
最后,我想拥有每个可能的状态-动作对。每个州的每一个行动。使用for循环可以非常快速地进行编码,但是好吧... numpy和for循环不是快速的朋友。所以这是我的解决方法,适用于一维动作空间:
s_s, a_s = np.meshgrid(state_space, action_space)
state_action_space = np.concatenate((
s_s.reshape(-1, state_space.shape[1]),
a_s.reshape(state_space.shape[1], action_space.shape[1], -1)[0].T), axis=1)
[state_space.shape[1]
表示单个状态/动作的暗淡。
一个问题,np.meshgrid
为3个状态空间维中的每一个返回a_s,并且像上面那样重塑它不起作用,因为我们需要将状态重塑为3xn,将动作重塑为1xn。
这甚至比上面的代码还要糟糕,但是目前可以使用。是否有人建议如何正确快速地使用meshgrid或其他?
最后,对于第二步,它只是两个矩阵的每一行的组合。必须有更好的方法...
感谢上述两个答案,这里是我的最终结果。我仍然必须使用*()来为gridgrid分解linspace,但是现在看起来更容易理解了。状态操作代码之前的最大问题是我试图使它过于复杂。它只是将数组彼此复制。因此,只要在操作空间中有不同的操作,就只需复制(或平铺)状态空间数组即可。这与ACTION_SPACE_SIZE^(action-dims)
相同。
action_space = np.stack(np.meshgrid(*(np.linspace(env.action_space.low, env.action_space.high, ACTION_SPACE_SIZE)).T), -1).reshape(-1, env.action_space.shape[0])
state_space = np.stack(np.meshgrid(*(np.linspace(env.observation_space.low, env.observation_space.high, STATE_SPACE_SIZE)).T), -1).reshape(-1, env.observation_space.shape[0])
state_action_space = np.concatenate((
np.tile(state_space, (action_space.shape[0])).reshape(-1, state_space.shape[1])
np.tile(action_space, (state_space.shape[0], 1))
), axis=1)