Плохая производительность двойного DQN по сравнению с ванильным DQN - PullRequest
0 голосов
/ 01 ноября 2019

Я сейчас пытаюсь оптимизировать навигацию моего робота. Сначала я использовал ванильный DQN, где оптимизировал параметры. Симуляция робота позволила ему достичь 8000 целей после 5000 эпизодов и показала удовлетворительные результаты обучения. Теперь, когда DQN является «не лучшим» в изучении подкрепления, я добавил DoubleDQN. К сожалению, этот выступал очень плохо в тех же условиях. Тогда мой первый вопрос: если я правильно и DDQN внедрил, как часто следует оптимизировать целевую сеть? Прямо сейчас, это оптимизировано после каждого эпизода. Один эпизод может идти до 500 шагов (если не произойдет сбоя). Я могу представить, чтобы обновлять цель гораздо чаще (то есть каждые 20 шагов). Но я не знаю, как тогда цель сможет запретить завышение поведения исходной сети?

Вот обычная обучающая часть DQN:

def getQvalue(self, reward, next_target, done):
        if done:
            return reward
        else:
            return reward + self.discount_factor * np.amax(next_target)
def getAction(self, state):
        if np.random.rand() <= self.epsilon:
            self.q_value = np.zeros(self.action_size)
            return random.randrange(self.action_size)
        else:
            q_value = self.model.predict(state.reshape(1, len(state)))
            self.q_value = q_value
            return np.argmax(q_value[0])
def trainModel(self, target=False):
        mini_batch = random.sample(self.memory, self.batch_size)
        X_batch = np.empty((0, self.state_size), dtype=np.float64)
        Y_batch = np.empty((0, self.action_size), dtype=np.float64)

        for i in range(self.batch_size):
            states = mini_batch[i][0]
            actions = mini_batch[i][1]
            rewards = mini_batch[i][2]
            next_states = mini_batch[i][3]
            dones = mini_batch[i][4]

            q_value = self.model.predict(states.reshape(1, len(states)))
            self.q_value = q_value

            if target:
                next_target = self.target_model.predict(next_states.reshape(1, len(next_states)))

            else:
                next_target = self.model.predict(next_states.reshape(1, len(next_states)))

            next_q_value = self.getQvalue(rewards, next_target, dones)

            X_batch = np.append(X_batch, np.array([states.copy()]), axis=0)
            Y_sample = q_value.copy()

            Y_sample[0][actions] = next_q_value
            Y_batch = np.append(Y_batch, np.array([Y_sample[0]]), axis=0)

            if dones:
                X_batch = np.append(X_batch, np.array([next_states.copy()]), axis=0)
                Y_batch = np.append(Y_batch, np.array([[rewards] * self.action_size]), axis=0)

        self.model.fit(X_batch, Y_batch, batch_size=self.batch_size, epochs=1, verbose=0)

Вот обновление дляDouble DQN:

def getQvalue(self, reward, next_target, next_q_value_1, done):
         if done:
             return reward
         else:
             a = np.argmax(next_q_value_1[0])
             return reward + self.discount_factor * next_target[0][a]
def getAction(self, state):
        if np.random.rand() <= self.epsilon:
            self.q_value = np.zeros(self.action_size)
            return random.randrange(self.action_size)
        else:
            q_value = self.model.predict(state.reshape(1, len(state)))
            self.q_value = q_value
            return np.argmax(q_value[0])
def trainModel(self, target=False):
        mini_batch = random.sample(self.memory, self.batch_size)
        X_batch = np.empty((0, self.state_size), dtype=np.float64)
        Y_batch = np.empty((0, self.action_size), dtype=np.float64)

        for i in range(self.batch_size):
            states = mini_batch[i][0]
            actions = mini_batch[i][1]
            rewards = mini_batch[i][2]
            next_states = mini_batch[i][3]
            dones = mini_batch[i][4]

            q_value = self.model.predict(states.reshape(1, len(states)))
            self.q_value = q_value

            if target:
                next_q_value_1 = self.model.predict(next_states.reshape(1, len(next_states)))
                next_target = self.target_model.predict(next_states.reshape(1, len(next_states)))
            else:
                next_q_value_1 = self.model.predict(next_states.reshape(1, len(next_states)))
                next_target = self.model.predict(next_states.reshape(1, len(next_states)))

            # next_q_value = self.getQvalue(rewards, next_target, next_q_value_1, dones)

            X_batch = np.append(X_batch, np.array([states.copy()]), axis=0)
            Y_sample = q_value.copy()

            Y_sample[0][actions] = next_q_value
            Y_batch = np.append(Y_batch, np.array([Y_sample[0]]), axis=0)

            if dones:
                X_batch = np.append(X_batch, np.array([next_states.copy()]), axis=0)
                Y_batch = np.append(Y_batch, np.array([[rewards] * self.action_size]), axis=0)

        self.model.fit(X_batch, Y_batch, batch_size=self.batch_size, epochs=1, verbose=0)

По сути, изменение происходит в части getQvalue, где я выбираю действие из исходной сети, но затем выбираю значение действия для этого действия из целевой сети. если цель гарантирует, что целевая сеть используется только после 2000 глобальных шагов. Прежде чем это должно иметь смысл (~ первые 10 эпизодов) С наилучшими пожеланиями и заранее спасибо!

1 Ответ

0 голосов
/ 07 ноября 2019

Не следует обновлять целевую сеть в каждом эпизоде. Потому что добавление целевой сети вводится для стабилизации значения q обучения. Частота обновления должна быть между 100, 1000 или 10000 в зависимости от среды.

Вы можете проверить этот вопрос. Я изменил код вопроса: Увеличение потерь Cartpole-v0 с использованием DQN

...