训练DQN时Q值爆炸

时间:2018-02-21 04:18:47

标签: python tensorflow machine-learning neural-network keras

我正在训练DQN来播放OpenAI的Atari环境,但我的网络的Q值很快就会爆炸远远超过现实。

以下是代码的相关部分:

for state, action, reward, next_state, done in minibatch:
        if not done:
            # To save on memory, next_state is just one frame
            # So we have to add it to the current state to get the actual input for the network
            next_4_states = np.array(state)
            next_4_states = np.roll(next_4_states, 1, axis=3)
            next_4_states[:, :, :, 0] = next_state
            target = reward + self.gamma * \
                np.amax(self.target_model.predict(next_4_states))
        else:
            target = reward
        target_f = self.target_model.predict(state)
        target_f[0][action] = target

        self.target_model.fit(state, target_f, epochs=1, verbose=0)

折扣系数为0.99(折扣因子为0.9时不会发生,但也不会收敛,因为它无法提前考虑)。

逐步执行代码,它发生的原因是所有不需要更新的Q值(我们没有采取的操作的值)略有增加。我的理解是,在训练期间将网络自身的输出传递到网络应该保持输出相同,而不是增加或减少它。我的模型有问题吗?有什么方法可以掩盖更新,所以它只更新相关的Q值吗?

编辑:我的模型创建代码在这里:

def create_model(self, input_shape, num_actions, learning_rate):
        model = Sequential()
        model.add(Convolution2D(32, 8, strides=(4, 4),
                                activation='relu', input_shape=(input_shape)))
        model.add(Convolution2D(64, 4, strides=(2, 2), activation='relu'))
        model.add(Convolution2D(64, 3, strides=(1, 1), activation='relu'))
        model.add(Flatten())
        model.add(Dense(512, activation='relu'))
        model.add(Dense(num_actions))

        model.compile(loss='mse', optimizer=Adam(lr=learning_rate))

        return model

我创建其中两个。一个用于在线网络,一个用于目标。

2 个答案:

答案 0 :(得分:1)

哪些预测会更新?

  

逐步执行代码,它发生的原因是所有不需要更新的Q值(我们没有采取的操作的值)略有增加。我的理解是,在训练期间将网络自己的输出传递到网络应该保持输出相同,而不是增加或减少它。

下面我画了一个非常简单的神经网络,有3个输入节点,3个隐藏节点和3个输出节点。假设您仅为第一个操作设置了新目标,并仅将现有预测再次用作其他操作的目标。这导致第一个动作/输出中只有非零(为简单起见,我只假设大于零)错误(在图像中用delta表示),并且0的错误为其他。

我已经绘制了连接,通过该连接,此错误将以粗体从输出传播到隐藏层。请注意隐藏层中的每个节点如何仍然出错。当这些节点然后将它们的错误传播回输入层时,它们将通过所有输入和隐藏层之间的连接来完成此操作,因此所有这些权重都可以改性。

所以,想象所有这些权重都得到了更新,现在想象用原始输入做一个新的前锋传球。您是否期望输出节点2和3具有与以前完全相同的输出?不,可能不是;从隐藏节点到最后两个输出的连接可能仍具有相同的权重,但所有三个隐藏节点将具有不同的激活级别。所以不,其他输出不能保证保持不变。

Example Neural Network

  

我是否可以通过某种方式屏蔽更新,以便只更新相关的Q值?

如果有的话,不容易。问题是最终对之间的连接之外的层对之间的连接不是特定于操作的,我认为你不希望它们也是。

目标网络

  

我的模型有问题吗?

我看到的一件事是您似乎正在更新用于生成目标的同一网络:

target_f = self.target_model.predict(state)

self.target_model.fit(state, target_f, epochs=1, verbose=0)

都使用self.target_model。您应该为这两条线路使用单独的网络副本,并且只有在较长时间后,才会将更新后的网络权重复制到用于计算目标的网络中。有关详细信息,请参阅this post中的添加3。

Double DQN

除此之外,众所周知,DQN仍然倾向于高估Q值(尽管它通常不应该完全爆炸)。这可以通过使用Double DQN来解决(注意:这是后来在DQN之上添加的改进)。

答案 1 :(得分:0)

我在双重DQN中遇到了类似的问题。降低学习率可以解决问题。