Pytorch: Como criar uma regra de atualização que não vem de derivativo

Eu quero implementar o seguinte algoritmo, retirado deeste livro, seção 13.6:

Não entendo como implementar a regra de atualização no pytorch (a regra para w é bastante semelhante à do theta

Até onde eu sei, a tocha requer uma perda paraloss.backwward().

Este formulário parece não se aplicar ao algoritmo citad

inda tenho certeza de que existe uma maneira correta de implementar essas regras de atualização no pytorc

Apreciaria muito um trecho de código de como os pesos w devem ser atualizados, dado que V (s, w) é a saída da rede neural, parametrizada por w.

EDITAR Chris Holland sugeriu uma maneira de implementar, e eu a implementei. Ele não converge no Cartpole, e me pergunto se fiz algo errad

O crítico converge na solução para a funçãogamma*f(n)=f(n)-1 que é a soma da sériegamma+gamma^2+...+gamma^inf significado, gama = 1 diverge. gama = 0,99 converge em 100, gama = 0,5 converge em 2 e assim por diante. Independentemente do ator ou política.

O código

def _update_grads_with_eligibility(self, is_critic, delta, discount, ep_t):
    gamma = self.args.gamma
    if is_critic:
        params = list(self.critic_nn.parameters())
        lamb = self.critic_lambda
        eligibilities = self.critic_eligibilities
    else:
        params = list(self.actor_nn.parameters())
        lamb = self.actor_lambda
        eligibilities = self.actor_eligibilities

    is_episode_just_started = (ep_t == 0)
    if is_episode_just_started:
        eligibilities.clear()
        for i, p in enumerate(params):
            if not p.requires_grad:
                continue
            eligibilities.append(torch.zeros_like(p.grad, requires_grad=False))

    # eligibility traces
    for i, p in enumerate(params):

        if not p.requires_grad:
            continue
        eligibilities[i][:] = (gamma * lamb * eligibilities[i]) + (discount * p.grad)
        p.grad[:] = delta.squeeze() * eligibilities[i]

expected_reward_from_t = self.critic_nn(s_t)
probs_t = self.actor_nn(s_t)
expected_reward_from_t1 = torch.tensor([[0]], dtype=torch.float)
if s_t1 is not None:  # s_t is not a terminal state, s_t1 exists.
    expected_reward_from_t1 = self.critic_nn(s_t1)

delta = r_t + gamma * expected_reward_from_t1.data - expected_reward_from_t.data

negative_expected_reward_from_t = -expected_reward_from_t
self.critic_optimizer.zero_grad()
negative_expected_reward_from_t.backward()
self._update_grads_with_eligibility(is_critic=True,
                                    delta=delta,
                                    discount=discount,
                                    ep_t=ep_t)
self.critic_optimizer.step()

EDIT 2: solução de Chris Holland funciona. O problema se originou de um bug no meu código que causou a linha

if s_t1 is not None:
    expected_reward_from_t1 = self.critic_nn(s_t1)

para sempre ser chamado, assimexpected_reward_from_t1 nunca foi zero e, portanto, nenhuma condição de parada foi especificada para a recursão da equação de bellma

Sem engenharia de recompensa,gamma=1, lambda=0.6, e uma única camada oculta do tamanho 128 para ator e crítico, isso convergiu para uma política ideal bastante estável em 500 episódio

Muito mais rápido comgamma=0.99, como mostra o gráfico (a melhor recompensa com episódio com desconto é de cerca de 86,6

BIG, obrigado a Chris Holland, que "fez uma tentativa"

questionAnswers(1)

yourAnswerToTheQuestion