多维状态动作 space 平铺比 np.meshgrid 更有效?

More efficient way for multidimensional state-action space tiling than with np.meshgrid?

首先,这是为了练习和比较,我知道平铺状态 space 比线性网格更有效。

为了运行一些强化学习算法,我想平铺我的状态和动作space线性。结果,我希望每个 space-action-pair 都以数组形式存在。问题是,不同的(健身房)环境具有不同的状态和动作 space 维度。因此我不喜欢硬编码变量或维度。 所以我需要计算每个状态-动作对,只给出每个状态-动作对的最小值和最大值。

我解决了大部分简单的问题,但 none 的解决方案是 "pretty"。

首先让我们计算状态和动作 space。用 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 循环不是快速的朋友。 所以这是我的解决方法,适用于 1D 动作 space:

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 returns a_s 对于 3 个状态-space 维度中的每一个,像上面那样重塑它是行不通的,因为我们需要将状态重塑为 3xn,将动作重塑为 1xn。

这比上面的代码还要糟糕,但现在可以用了。有没有人建议如何正确快速地使用 meshgrid 或其他东西?

最后,对于第二步,它只是将两个矩阵的每一行进行组合。必须有更好的方法...

感谢以上两个答案,这里是我的最终结果。 我仍然不得不使用 *() 来反汇编 linspace for meshgrid,但它现在看起来更易于阅读。 之前状态动作代码的一个大问题是我试图把它复杂化。它只是将数组复制到彼此之上。因此,只需复制(或在这种情况下平铺)state-space 数组,只要您在 action-space.This 中有不同的操作即可,与 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)