我正在尝试复制 DeepMind 论文的结果,所以我实现了自己的 DQN。我让它在 SpaceInvaders-v4 (OpenAI-Gym) 上训练了超过 400 万帧(超过 2000 集),但它无法完成一集。我尝试了两种不同的学习率(0.0001 和 0.00125),似乎使用 0.0001 效果更好,但中值分数从未超过 200。我使用的是双 DQN。这是我的代码和我每次会议得到的图表的一些照片。在会话之间,我正在保存网络权重;我每 1000 步更新一次目标网络。我看不出我是否做错了什么,所以任何帮助将不胜感激。我使用与 DQN 论文相同的 CNN 结构。
这是动作选择功能;它使用一批 4 个 80x80 处理过的灰度体验来选择动作(s_batch 表示状态批处理):
def action_selection(self, s_batch):
action_values = self.parallel_model.predict(s_batch)
best_action = np.argmax(action_values)
best_action_value = action_values[0, best_action]
random_value = np.random.random()
if random_value < AI.epsilon:
best_action = np.random.randint(0, AI.action_size)
return best_action, best_action_value
这是我的训练功能。它以过去的经验为训练;我试图实现,如果它失去任何生命,它不会得到任何额外的奖励,所以理论上,代理会尽量不死:
def training(self, replay_s_batch, replay_ns_batch):
Q_values = []
batch_size = len(AI.replay_s_batch)
Q_values = np.zeros((batch_size, AI.action_size))
for m in range(batch_size):
Q_values[m] = self.parallel_model.predict(AI.replay_s_batch[m].reshape(AI.batch_shape))
new_Q = self.parallel_target_model.predict(AI.replay_ns_batch[m].reshape(AI.batch_shape))
Q_values[m, [item[0] for item in AI.replay_a_batch][m]] = AI.replay_r_batch[m]
if np.all(AI.replay_d_batch[m] == True):
Q_values[m, [item[0] for item in AI.replay_a_batch][m]] = AI.gamma * np.max(new_Q)
if lives == 0:
loss = self.parallel_model.fit(np.asarray(AI.replay_s_batch).reshape(batch_size,80,80,4), Q_values, batch_size=batch_size, verbose=0)
if AI.epsilon > AI.final_epsilon:
AI.epsilon -= (AI.initial_epsilon-AI.final_epsilon)/AI.epsilon_decay
replay_s_batch 它是一批 (batch_size) 体验重播状态(每包 4 个体验),而 replay_ns_batch 它充满了 4 个下一个状态。批量大小为 32。
以下是训练后的一些结果:
蓝色表示损失(我认为它是正确的;它接近于零)。红点是不同的匹配分数(如您所见,它有时会匹配得很好)。绿色,中位数(本次训练中接近 190,学习率 = 0.0001)
这是最后一次训练,lr = 0.00125;结果更糟(中位数约为 160)。无论如何,这条线几乎是直的,无论如何我都看不到任何变化。所以任何人都可以指出我正确的方向吗?我用钟摆尝试了类似的方法,它工作正常。我知道使用 Atari 游戏需要更多时间,但一周左右我认为就足够了,而且似乎卡住了。如果有人需要查看我的代码的另一部分,请告诉我。
编辑:根据提供的建议,我修改了 action_selection 函数。这里是:
def action_selection(self, s_batch):
if np.random.rand() < AI.epsilon:
best_action = env.action_space.sample()
else:
action_values = self.parallel_model.predict(s_batch)
best_action = np.argmax(action_values[0])
return best_action
为了澄清我的最后一次编辑:使用 action_values 您可以获得 q 值;使用 best_action 您可以获得对应于最大 q 值的操作。我应该返回那个还是只返回最大 q 值?