我应该如何为我的类似网格世界的环境定义状态?

how should i define the state for my gridworld like environment?

我要解决的问题其实没有这么简单,但这是一种玩具游戏,可以帮助我解决更大的问题。

所以我有一个 5x5 矩阵,其值都等于 0 :

structure = np.zeros(25).reshape(5, 5)

代理的目标是将所有值都变成 1,所以我有:

goal_structure = np.ones(25).reshape(5, 5)

我创建了一个 class 玩家,有 5 个动作可以向左、向右、向上、向下或翻转(将值 0 变为 1 或将 1 变为 0)。对于奖励,如果代理将值 0 更改为 1,则它获得 +1 奖励。如果它把 1 变成 0 in 得到负奖励(我尝试了从 -1 到 0 甚至 -0.1 的许多值)。如果它只是向左、向右、向上或向下移动,它会获得奖励 0。

因为我想将状态提供给我的神经网络,所以我将状态重塑如下:

reshaped_structure = np.reshape(structure, (1, 25))

然后我将代理的规范化位置添加到这个数组的末尾(因为我想代理应该知道它在哪里):

reshaped_state = np.append(reshaped_structure, (np.float64(self.x/4), np.float64(self.y/4)))
state = reshaped_state

但我没有得到任何好结果!它就像它的随机性!我尝试了不同的奖励函数,不同的优化算法,例如经验回放,目标网,双DQN,决斗,但似乎都没有用!我想问题在于定义状态。谁能帮我定义一个好的状态?

非常感谢!

ps:这是我的阶跃函数:

class Player:

def __init__(self):
    self.x = 0
    self.y = 0

    self.max_time_step = 50
    self.time_step = 0
    self.reward_list = []
    self.sum_reward_list = []
    self.sum_rewards = []

    self.gather_positions = []
    # self.dict = {}

    self.action_space = spaces.Discrete(5)
    self.observation_space = 27

def get_done(self, time_step):

    if time_step == self.max_time_step:
        done = True

    else:
        done = False

    return done

def flip_pixel(self):

    if structure[self.x][self.y] == 1:
        structure[self.x][self.y] = 0.0

    elif structure[self.x][self.y] == 0:
        structure[self.x][self.y] = 1

def step(self, action, time_step):

    reward = 0

    if action == right:

        if self.y < y_threshold:
            self.y = self.y + 1
        else:
            self.y = y_threshold

    if action == left:

        if self.y > y_min:
            self.y = self.y - 1
        else:
            self.y = y_min

    if action == up:

        if self.x > x_min:
            self.x = self.x - 1
        else:
            self.x = x_min

    if action == down:

        if self.x < x_threshold:
            self.x = self.x + 1
        else:
            self.x = x_threshold

    if action == flip:
        self.flip_pixel()

        if structure[self.x][self.y] == 1:
            reward = 1
        else:
            reward = -0.1



    self.reward_list.append(reward)

    done = self.get_done(time_step)

    reshaped_structure = np.reshape(structure, (1, 25))
    reshaped_state = np.append(reshaped_structure, (np.float64(self.x/4), np.float64(self.y/4)))
    state = reshaped_state

    return state, reward, done

def reset(self):

    structure = np.zeros(25).reshape(5, 5)

    reset_reshaped_structure = np.reshape(structure, (1, 25))
    reset_reshaped_state = np.append(reset_reshaped_structure, (0, 0))
    state = reset_reshaped_state

    self.x = 0
    self.y = 0
    self.reward_list = []

    self.gather_positions = []
    # self.dict.clear()

    return state

我会将代理位置编码为这样的矩阵:

0 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0

(代理在中间)。当然,对于网络,您也必须将其展平。所以你的总状态是 50 个输入值,25 个用于单元格状态,25 个用于代理位置。

当您将位置编码为两个浮点数时,网络必须解码浮点数的确切值。如果你使用像上面那样的显式方案,网络就会非常清楚代理的确切位置。这是位置的 "one-hot" 编码。

例如,如果您查看 atari DQN 论文,代理位置总是使用每个可能位置的神经元明确编码。

另请注意,对于您的智能体来说,一个非常好的策略是保持静止并不断翻转状态,这样做每一步可获得 0.45 奖励(+1 表示 0 到 1,-0.1 表示 1 到 0,拆分超过 2 个步骤)。假设一个完美的策略它只能得到 25,但这个策略将得到 22.5 的奖励并且很难忘记。我建议代理人因取消奖励而获得 -1。


你提到代理没有学习。我可以建议你尽量简化。第一个建议是 - 将 episode 的长度减少到 2 或 3 个步骤,并将网格的大小减少到 1。看看代理是否可以学习将单元格始终设置为 1。同时,将代理的大脑简化为尽可能多。将它减少到只有一个输出层——一个带有激活的线性模型。这应该非常快速且易于学习。如果代理在 100 集中没有学习到这一点,我怀疑您的 RL 实现中存在错误。如果可行,您可以开始扩展网格的大小和网络的大小。