【问题标题】:Implementing Dropout in a Keras DQN (reinforcement learning)在 Keras DQN 中实现 Dropout(强化学习)
【发布时间】:2021-03-18 14:48:24
【问题描述】:

首先我必须说我知道,Dropout 在强化学习 (RL) 中并不常见。您可以在此处阅读有关该主题的更多信息以及为什么它可能有意义:

https://towardsdatascience.com/generalization-in-deep-reinforcement-learning-a14a240b155b

我不确定如何在 Keras DQN 中实现 Dropout。通常(在监督学习中)Keras 负责打开/关闭 Dropout 层的任务,具体取决于您是在训练还是在测试。就我而言(与 RL 进行交易),我确实训练了 TRAIN 数据并测试了坚持数据,但它们并不相等。该模型确实过度拟合了 TRAIN 数据并且不能很好地概括。只需查看训练结果,我就可以看到它过度拟合 - 它记忆并完美地交易训练过的数据。这就是我想使用 Dropout 的原因。


编辑:由于“krenerd”提供了一种不同的方式来实现该功能,我将在这里总结所有 4 种(对我而言)已知方式:

方式 1: 将 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])

方式 3: (https://stackoverflow.com/a/57439143/11122466) “另一种方法是定义一个具有相同架构但不设置 training=True 的新模型,然后将权重从经过训练的模型转移到这个新模型。”这对我来说非常慢,每个副本大约需要 1.5 毫秒。因为它很慢,所以我不喜欢那个解决方案。

方式 4(由“krenerd”建议): “使用模型(x,training = True)调用模型”在这里我得到一个值错误:使用不是符号张量的输入调用了层 INPUT。收到的类型:。 我的输入是一个 numpy 数组,我必须将其转换为张量。


如果您查看以下 DQN 的简单示例,修改/取自:

https://github.com/keon/deep-q-learning/blob/master/dqn.py

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() 两次,一次用于“状态”,一次用于“next_state”(创建我们的目标/标签),我们调用 predict () 在 act() 中。我们是否为 replay() 中的两个 predict() 调用启用 Dropout?我们是否为 act() 中的 predict() 调用启用 Dropout?

ON TEST DATA: 无探索,Epsilon = 0。仅使用 act() 来评估未见数据的性能。来自 TEST 的数据不保存在重放缓冲区中。我想我们这里不使用 Dropout?

2 个问题:

您将如何/在何处插入 Dropout 层?在第一个 Dense 层之前或之后和/或在 Activation 层之前/之后?

哪些 predict() 调用必须在 training = True / learning_phase = 1 的情况下进行,哪些不需要?

提前致谢!

【问题讨论】:

  • 几个问题:你的状态空间和动作空间的维度?您在代码中的哪个位置更新目标估计器,如果是,多久更新一次?你的缓冲区有多大?此外,评估 DQN 代理的方法是提取策略并根据您认为更好的另一个策略评估该策略。
  • 亲爱的 siddhant,感谢您的评论。抱歉,回答这个问题不需要“状态/动作空间和缓冲区大小的维度”吗?我不明白你为什么需要这些信息?没有“目标估计器”,我展示的示例是一个简单的 DQN。而且它不是“我的代码”,它是一个简单的示例来解释实现 DROPOUT 的问题。 “评估 DQN 代理的方法是提取策略并根据另一策略评估该策略”-> 我不明白,因为代理用于查找策略-因为我没有更好的策略?
  • 嗨 Anna,实际上在 DQN 任务中使用 dropout 是没有意义的。 Dropout 本质上是为了避免过度拟合,在监督学习场景中也是如此。 DQN 的整个想法是让 Q-Learning 看起来更像监督学习。在 DQN 中,这是通过使用目标估计器和我问你的其他 DQN 参数来完成的。在 RL 的世界中,没有这样的训练和测试数据。您可以参考this answer 了解更多信息。
  • 我对策略的意思是,您必须有另一个策略来比较您的 DQN 策略。让我们称之为您的“基准”政策。对于每个状态,您所采取的行动都可以根据基准策略评估您的 DQN 策略,并查看哪个策略可以为您提供更好的奖励。基本上它针对基准策略对 DQN 的策略评估。您的基准可以是 SARSA,甚至是离散状态和动作空间上的 Q-learning。
  • 我们能否结束关于“辍学在这里是否有意义”的理论讨论?有一些迹象表明这种技术可能会成功,我只是想知道如何正确实施它。我很清楚,这个应用领域超出了正常规范。我知道解决这些问题更像是一门艺术而不是科学。我的目的是找出如何在技术上实现这一点,而不是讨论它在理论上是否有意义。它可能不起作用,但我想自己测试一下。然而,为了能够对其进行测试,它必须正确实施。

标签: python keras reinforcement-learning


【解决方案1】:

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)

【讨论】:

  • “所以对于你训练中使用的所有model.predict(),你必须把它替换成model(x,training=True)。”谢谢你的回答,你能解释一下为什么吗?我从不同的人那里得到不同的答案,有人说你可以在这里使用没有 Dropout 的普通 predict()。他们说只有在 fit() 运行时才使用 Dropout。这就是令人困惑的地方......
  • 亲爱的克伦德,你的回答包含了很多我想知道的东西。您为什么认为:“对于训练中使用的所有 model.predict(),您必须将其替换为 model(x,training=True)”。如果您能更详细地解释这一点,那将是非常好的,并有一个合理的解释,我会接受答案。但我想了解我在做什么。
  • @anna12345 抱歉回复晚了。我忙了一阵子。我们可以将model.predict() 函数称为推理函数,通常在测试时使用。 DroupoutBatchNormalization 等一些操作仅适用于训练,而不适用于测试/评估。
  • @anna12345 您在训练时使用了model.predict 函数,尽管 Python 期望您在经过训练的模型上进行评估,因此忽略了不必要的层:dropout 层。通过model(x,training=True)进行预测,可以告诉模型不要关闭dropout层:)
猜你喜欢
  • 2019-06-03
  • 2021-05-06
  • 1970-01-01
  • 2010-10-18
  • 2014-12-23
  • 2016-06-15
  • 2021-02-12
  • 2018-03-22
  • 2019-03-31
相关资源
最近更新 更多