Как будто вы пытаетесь получить доступ к объекту, который является null
. Рассмотрим ниже пример:
TypeA objA;
. В это время вы только что объявили этот объект, но не инициализировали или не инициализировали. И всякий раз, когда вы пытаетесь получить доступ к каким-либо свойствам или методам в нем, он будет генерировать NullPointerException
, что имеет смысл.
См. Также этот пример:
String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
Я думаю, что проблема состоит в том, что Вы обнуляете градиенты прямо прежде, чем звонить назад, после вперед распространение. Обратите внимание для автоматическое дифференцирование необходимость в графике вычисления и промежуточных результатах, что Вы производите во время Вашего вперед передачу.
Так обнуляют градиенты прежде Ваша ошибка TD и предназначаются для вычислений! И не после того, как Вы закончены Ваш вперед распространение.
for cur_step in range(1):
action = M_Agent(state, flag)
next_state, r = env.step(action)
optimizer_M.zero_grad() # zero your gradient here
# calculate TD Error
TD_error = M_Agent.cal_td_error(r, next_state)
# calculate Target
target = torch.FloatTensor([M_Agent.cal_target(TD_error)])
logit = M_Agent.cal_logit()
loss = criterion(logit, target)
# update value Func
TD_error.backward()
optimizer_M.step()
# update Actor Func
loss.backward()
optimizer_M.step()
Для ответа на второй вопрос алгоритм DDPG, например, использует ошибку в квадрате (см. бумага ).
Другая рекомендация. Во многих случаях значительные части значения и сетей политики совместно используются в глубоких агентах критика агента: Вы имеете те же слои до последнего скрытого слоя и используете единственный линейный вывод для прогноза значения и softmax слой для распределения действия. Это особенно полезно, если у Вас есть высокие размерные визуальные исходные данные, поскольку это действует как вид многозадачного изучения, но тем не менее можно попробовать. (Поскольку я вижу, что у Вас есть низко-размерный вектор состояния).