我正在尝试实现一个 A3C 强化学习程序,我使用来自 MorvanZhou 的代码作为样板。然而,根据我发现的这个问题,pytorch 优化器现在似乎使用单例而不是整数(无论这意味着什么)。
我有一个与 A3C 示例完全相同的 Net 类,我正在根据 Net 的损失函数计算损失,如下所示:
def v_wrap(np_array, dtype=np.float32):
if np_array.dtype != dtype:
np_array = np_array.astype(dtype)
return torch.from_numpy(np_array)
loss = lnet.loss_func(
v_wrap(np.vstack(bs)),
v_wrap(np.vstack(ba)),
v_wrap(np.array(buffer_v_target)[:, None]))
# calculate local gradients and push local parameters to global
opt.zero_grad()
loss.backward()
for lp, gp in zip(lnet.parameters(), gnet.parameters()):
gp._grad = lp.grad
opt.step()
它继续正确,但在
opt.step()
行中它抛出异常:
RuntimeError: API has changed, "state_steps" argument must contain a list of singleton tensors
我在 issue 中看到,他们通过获取优化器的 state_dict() 然后将其转换回单例来进行快速修复。
osd = optimizer.state_dict()
for _, bufs in osd["state"].items():
if "step" in bufs.keys():
# convert state_step back from int into a singleton tensor
bufs["step"] = torch.tensor(bufs["step"])
我只是不确定在哪里将这些值转换为整数,或者我可以在哪里应用该“修复”
对于上下文:我正在 torch.multiprocessing 进程中运行基于文本的模拟,该进程运行整个情节,然后尝试根据每个步骤的操作、状态和奖励的内存计算损失和梯度。它有一个全局网络和一个全局优化器,它使用梯度来更新全局网络参数。
全局优化器就是这个:
import torch
class SharedAdam(torch.optim.Adam):
def __init__(self, params, lr=1e-3, betas=(0.9, 0.99), eps=1e-8,
weight_decay=0):
super(SharedAdam, self).__init__(params, lr=lr, betas=betas, eps=eps, weight_decay=weight_decay)
# State initialization
for group in self.param_groups:
for p in group['params']:
state = self.state[p]
state['step'] = 0
state['exp_avg'] = torch.zeros_like(p.data)
state['exp_avg_sq'] = torch.zeros_like(p.data)
# share in memory
state['exp_avg'].share_memory_()
state['exp_avg_sq'].share_memory_()
整个代码都在这个 git repo 文件夹中,以防有帮助:https://github.com/SebsCubs/energy-plus-DRL/tree/deep_copy/A3C_refactor
我尝试将状态更改为我的特定环境,模拟运行良好,内存保存正确,我期望能够使用优化器更新全局网络,但我无法正确执行此操作。
使用 torch 1.13.1 实现 A3C 时遇到同样的问题。通过使用 torch==1.11.0 解决了这个问题。
将行 'state['step'] = 0' 更改为 'state['step'] = torch.zeros(1)' 对我有用。