深度 Q 网络给出相同的 Q 值并且没有改善

数据挖掘 Python 深度学习 喀拉斯 强化学习 q学习
2022-02-22 18:36:22

我正在尝试建立一个深度 Q 网络来玩蛇。我遇到了一个代理不学习的问题,它在训练周期结束时的表现是反复杀死自己。经过一番调试,我发现网络预测的 Q 值每次都是相同的。动作空间是 [up, right, down, left],网络预测 [0, 0, 1, 0]。训练损失确实会随着时间的推移而下降,但似乎并没有什么不同。这是训练代码:

def train(self):
    tf.logging.set_verbosity(tf.logging.ERROR)
    self.build_model()
    for episode in range(self.max_episodes):
        self.current_episode = episode
        env = SnakeEnv(self.screen)
        episode_reward = 0
        for timestep in range(self.max_steps):
            env.render(self.screen)
            state = self.screenshot()
            #state = env.get_state()
            action = None
            epsilon = self.current_eps
            if epsilon > random.random():
                action = np.random.choice(env.action_space) #explore
            else:
                values = self.policy_model.predict(state) #exploit
                action = np.argmax(values)
            experience = env.step(action)
            if(experience['done'] == True):
                episode_reward += experience['reward']
                break
            episode_reward += experience['reward']
            self.push_memory(Experience(experience['state'], experience['action'], experience['reward'], experience['next_state']))
            self.decay_epsilon(episode)
            if self.can_sample_memory():
                memory_sample = self.sample_memory()
                X = []
                Y = []
                for memory in memory_sample:
                    memstate = memory.state
                    action = memory.action
                    next_state = memory.next_state
                    reward = memory.reward
                    max_q = reward + (self.discount_rate * self.replay_model.predict(next_state)) #bellman equation
                    X.append(memstate)
                    Y.append(max_q)
                X = np.array(X)
                X = X.reshape([-1, 600, 600, 2])
                Y = np.array(Y)
                Y = Y.reshape([self.batch_size, 4])
                self.policy_model.fit(X, Y)
        food_eaten = experience["food_eaten"]
        print("Episode: ", episode, " Total Reward: ", episode_reward, " Food Eaten: ", food_eaten)
        if episode % self.target_update == 0:
            self.replay_model.set_weights(self.policy_model.get_weights())
    self.policy_model.save_weights('weights.hdf5')
    pygame.quit()

这是网络架构:

    self.policy_model = Sequential()
    self.policy_model.add(Conv2D(8, (5, 5), padding = 'same', activation = 'relu', data_format = "channels_last", input_shape = (600, 600, 2)))
    self.policy_model.add(Conv2D(16, (5, 5), padding="same", activation="relu"))
    self.policy_model.add(Conv2D(32, (5, 5), padding="same", activation="relu"))
    self.policy_model.add(Flatten())
    self.policy_model.add(Dense(16, activation = "relu"))
    self.policy_model.add(Dense(5, activation = "softmax"))
    rms = keras.optimizers.RMSprop(lr = self.learning_rate) 
    self.policy_model.compile(optimizer = rms, loss = 'mean_squared_error')

以下是超参数:

learning_rate = 1e-4
discount_rate = 0.99
eps_start = 1
eps_end = .01
eps_decay = 1e-5
memory_size = 100000
batch_size = 2
max_episodes = 1000
max_steps = 100000
target_update = 100

我已经让它训练了整整 1000 集,但最后还是很糟糕。我在训练算法上做错了吗?

编辑:忘了提到代理会因前往食物而获得 0.5 的奖励,因吃食物而获得 1 的奖励,因死亡而获得 -1 的奖励

编辑 2:为模型和超参数添加了更新的代码

2个回答

我可以看到您正在使用“普通”deepQ,请考虑使用双深度 Q 或决斗,但首先要使用您当前的实现。

首先,大多数时候问题是一个错误,你能提供分数的历史吗?重要的是要了解代理是否正在学习,或者它可以找到的最佳解决方案是杀死自己以最大程度地减少损失。

根据您的超参数,我建议先增加两个伽玛,然后再缓慢衰减 epsilon。

另一个调整是你的 alpha,稍微降低一点,似乎太高了。

无论如何,我需要更多详细信息来帮助您,例如,您在阅读屏幕吗?如果是,您是否将图像缩小到易于管理的程度?你能提供完整的代码吗?

我正在查看您的超参数,似乎还可以,也许 min epsilon 太高了,但不要认为这是问题所在。你的奖励计划不是最好的。两次前往食物与按时吃食物相同,因此根据食物的距离,保单的回报会有很大差异。换句话说,仅作为一个例子,向食物走 2 次不吃食物然后死比吃食物然后死要好。可能经纪人需要永远打得好。

尝试将您的奖励减少到 0,这将需要更多时间来了解游戏的目标(吃),但会了解最大化什么。