我应该如何为我的类似网格世界的环境定义状态?
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 实现中存在错误。如果可行,您可以开始扩展网格的大小和网络的大小。
我要解决的问题其实没有这么简单,但这是一种玩具游戏,可以帮助我解决更大的问题。
所以我有一个 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 实现中存在错误。如果可行,您可以开始扩展网格的大小和网络的大小。