我正在训练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
我创建其中两个。一个用于在线网络,一个用于目标。
答案 0 :(得分:1)
逐步执行代码,它发生的原因是所有不需要更新的Q值(我们没有采取的操作的值)略有增加。我的理解是,在训练期间将网络自己的输出传递到网络应该保持输出相同,而不是增加或减少它。
下面我画了一个非常简单的神经网络,有3个输入节点,3个隐藏节点和3个输出节点。假设您仅为第一个操作设置了新目标,并仅将现有预测再次用作其他操作的目标。这导致第一个动作/输出中只有非零(为简单起见,我只假设大于零)错误(在图像中用delta
表示),并且0
的错误为其他。
我已经绘制了连接,通过该连接,此错误将以粗体从输出传播到隐藏层。请注意隐藏层中的每个节点如何仍然出错。当这些节点然后将它们的错误传播回输入层时,它们将通过所有输入和隐藏层之间的连接来完成此操作,因此所有这些权重都可以改性。
所以,想象所有这些权重都得到了更新,现在想象用原始输入做一个新的前锋传球。您是否期望输出节点2和3具有与以前完全相同的输出?不,可能不是;从隐藏节点到最后两个输出的连接可能仍具有相同的权重,但所有三个隐藏节点将具有不同的激活级别。所以不,其他输出不能保证保持不变。
我是否可以通过某种方式屏蔽更新,以便只更新相关的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。
除此之外,众所周知,DQN仍然倾向于高估Q值(尽管它通常不应该完全爆炸)。这可以通过使用Double DQN来解决(注意:这是后来在DQN之上添加的改进)。
答案 1 :(得分:0)
我在双重DQN中遇到了类似的问题。降低学习率可以解决问题。