В многозадачности не может создать новый график вычислений после обратного распространения - PullRequest
1 голос
/ 11 мая 2019

Справочная информация: я использую DQN и DDPG для одновременного решения двух задач state(input) DQN и DDPG - это две части. Одна часть - это состояния окружающей среды, а другая - состояния, абстрагированные от среды CNN + LSTM. Две части объединены в forward_dqn(), forward_actor() и forward_critic() соответственно.

Question1: Я возвращаю в обратном порядке последовательности loss_dqn, loss_ddpg_actor и loss_ddpg_critic и получаю сообщение об ошибке «Попытка выполнить обратный просмотр графа во второй раз, но буферы уже освобождены». в обратном распространении loss_ddpg_actor. Так как после обратного распространения loss_dqn, вычислительный граф был освобожден, поэтому я снова перешёл вперед CNN + LSTM, чтобы вычислить loss_ddpg_actor. Почему вычислительный граф не может быть создан снова? Спасибо.

Модель: (env: environment)

output_cnnlstm = cnnlstm.forward(env)
DQN_output = dqn.forward(cat(output_cnnlstm, state_env))
Actor_output = actor.forward(cat(output_cnnlstm, state_env))
Critic_output = critic.forward(cat(output_cnnlstm, state_env))

Код 1 (Q1):

    # dqn
    # forward: cnnlstm
    s_cnnlstm_out, _, _ = self.model.forward_cnnlstm(s_cnnlstm, flag_optim=True)
    # forward: dqn
    q_eval_dqn = self.model.forward_dqn_eval(s_dqn, s_cnnlstm_out).gather(1, a_dqn)
    q_next_dqn = self.model.forward_dqn_target(s_dqn_next, s_cnnlstm_out).detach()
    q_target_dqn = r + GAMMA_DQN * q_next_dqn.max(dim=1)[0].reshape(SIZE_BATCH * SIZE_TRANSACTION, 1)
    # optimzie: dqn
    loss_dqn = self.loss_dqn(q_eval_dqn, q_target_dqn)
    self.optimizer_cnnlstm.zero_grad()
    self.optimizer_dqn.zero_grad()
    loss_dqn.backward()
    self.optimizer_cnnlstm.step()
    self.optimizer_dqn.step()
    loss_dqn = loss_dqn.detach().numpy()
    # ddpg
    # actor
    # forward: cnnlstm
    s_cnnlstm_out, _, _ = self.model.forward_cnnlstm(s_cnnlstm, flag_optim=True)
    # forward: ddpg: actor
    a_eval_ddpg = self.model.forward_actor_eval(s_ddpg, s_cnnlstm_out)
    # optimze: ddpg: cnnlstm + actor
    loss_ddpg_actor = - self.model.forward_cirtic_eval(s_ddpg, a_eval_ddpg, s_cnnlstm_out).mean()
    self.optimizer_cnnlstm.zero_grad()
    self.optimizer_actor.zero_grad()
    loss_ddpg_actor.backward()
    self.optimizer_cnnlstm.step()
    self.optimizer_actor.step()
    loss_ddpg_actor = loss_ddpg_actor.detach().numpy()

Вопрос2: Я пишу демо-версию для тестирования процесса распространения, и демо-версия, кажется, работает хорошо, так как потери снижаются нормально, а ошибка теста низкая. Поэтому я хочу спросить разницу между двумя кодами и моделями.

Модель:

output_model1 = model1.forward(x)
output_model21 = model21.forward(cat(output_model1, x1))
output_model22 = model221.forward(cat(output_model1, x2))

по сравнению с моделью Q1, output_model1 ~ cnnlstm, output_model21 ~ DQN, output_model22 ~ Actor

Question3: Я устанавливаю точку останова в демоверсии после loss1.backward() и до optimizer1.step(). Однако, с одной стороны, вес линейного слоя Model21 изменяется с оптимизацией. С другой стороны, x._grad - это тензор градиента, а x1._grad - None. Поэтому мне интересно, оптимизированы ли параметры Model21, и почему x1._grad отсутствует.

Код 2 (Q2 и Q3):

for i in range(NUM_OPTIM):
    # optimize task 1
    y1_pred = self.model.forward_task1(x, x1)
    loss1 = self.loss_21(y1_pred, y1)
    self.optimizer1.zero_grad()
    self.optimizer21.zero_grad()
    loss1.backward()
    self.optimizer1.step()
    self.optimizer21.step(
    # optimze task 2
    y2_pred = self.model.forward_task2(x, x2)
    loss2 = self.loss_22(y2_pred, y2)
    self.optimizer1.zero_grad()
    self.optimizer22.zero_grad()
    loss2.backward()
    self.optimizer1.step()
    self.optimizer22.step()
...