首先我必须说我知道,Dropout 在强化学习(RL)中并不常见。在这里您可以阅读有关该主题的更多信息以及为什么它可能有意义:
https://towardsdatascience.com/generalization-in-deep-reinforcement-learning-a14a240b155b
我不确定如何在 Keras DQN 中实现 Dropout。通常(在监督学习中)Keras 负责打开/关闭 Dropout 层的任务,具体取决于您是在训练还是测试。就我而言(使用 RL 进行交易),我在 TRAIN 数据上进行训练,并在保留数据上进行测试,但它们并不相等。该模型确实过度拟合 TRAIN 数据并且不能很好地概括。我可以看到它过度拟合,只需查看训练结果 - 它“记忆”并完美地交换训练数据。这就是为什么我想使用 Dropout。
编辑:由于“krenrd”给出了一种不同的方法来实现该功能,我将在这里总结所有 4 种(对我来说)已知的方法:将 K.set_learning_phase() 与 K.set_learning_phase(0) 或 K.set_learning_phase(1) 一起使用
方式2:(https://stackoverflow.com/a/57439143/11122466) 使用K(后端)功能:
func = K.function(model.inputs + [K.learning_phase()], model.outputs)
在 dropout 层处于活动状态的情况下运行模型,即learning_phase=1
preds = func(list_of_input_arrays + [1])
在 dropout 层处于非活动状态的情况下运行模型,即learning_phase=0
preds = func(list_of_input_arrays + [0])
(https://stackoverflow.com/a/57439143/11122466) “另一种方法是定义一个具有相同架构但不设置training=True的新模型,然后将权重从训练好的模型转移到这个新模型。”这对我来说非常慢,每个副本大约需要 1.5 毫秒。因为它很慢,我不喜欢这个解决方案。
方式4(由“krenrd”建议):
“用 model(x,training=True) 调用模型”这里我得到一个值错误:使用不是符号张量的输入调用 Layer INPUT。收到的类型:。
我的输入是一个 numpy 数组,我必须将其转换为张量。
class DQNAgent:
def __init__(self, state_size, action_size):
self.state_size = state_size
self.action_size = action_size
self.memory = deque(maxlen=2000)
self.gamma = 0.95 # discount rate
self.epsilon = 1.0 # exploration rate
self.epsilon_min = 0.01
self.epsilon_decay = 0.995
self.learning_rate = 0.001
self.model = self._build_model()
def _build_model(self):
model = Sequential()
model.add(Dense(24, input_dim=self.state_size, activation='relu'))
model.add(Dense(24, activation='linear'))
model.add(Dropout(0.05))
model.add(ReLU())
model.add(Dense(self.action_size, activation='linear'))
model.compile(loss='mse',optimizer=Adam(lr=self.learning_rate))
return model
def act(self, state):
if np.random.rand() <= self.epsilon:
return random.randrange(self.action_size)
act_values = self.model.predict(state)
return np.argmax(act_values[0]) # returns action
def replay(self, batch_size):
minibatch = random.sample(self.memory, batch_size)
for state, action, reward, next_state, done in minibatch:
target = reward
if not done:
target = (reward + self.gamma *
np.amax(self.model.predict(next_state)[0]))
target_f = self.model.predict(state)
target_f[0][action] = target
self.model.fit(state, target_f, epochs=1, verbose=0)
if self.epsilon > self.epsilon_min:
self.epsilon *= self.epsilon_decay
我们在replay()函数中调用predict()两次,一次用于“state”,一次用于“next_state”(创建我们的目标/标签),并且我们在act()中调用predict()。我们是否为 replay() 中的两个 Predict() 调用启用 Dropout?我们是否为 act() 中的 Predict() 调用启用 Dropout?
测试数据:无探索,Epsilon = 0。仅使用 act() 来评估未见数据的性能。来自 TEST 的数据不保存在重放缓冲区中。我想我们这里不使用Dropout?
2 个问题:
model.predict(x)
自动忽略仅训练层,例如推理中的 Dropout 或 BatchNormalization。如果您希望应用 dropout 进行预测,则必须使用
model(x,training=True)
。使用 Training=fasle 编写代码,model(x,training=False)
与 model.predict(x)
执行相同的操作。因此,对于训练中使用的所有 model.predict()
,您必须将其替换为
model(x,training=True)
。