【问题标题】:Custom PyTorch optimizer is not working properly and am unable to access gradients自定义 PyTorch 优化器无法正常工作,无法访问渐变
【发布时间】:2020-12-10 05:14:03
【问题描述】:

我正在尝试实现Deep Learning with Elastic Averaging SGD 论文中的弹性平均随机梯度下降 (EASGD) 算法,但遇到了一些麻烦。

我正在使用 PyTorch 的 torch.optim.Optimizer 类并引用 official implementation of SGDofficial implementation of Accelerated SGD 以便从某个地方开始。

我的代码是:

import torch.optim as optim


class EASGD(optim.Optimizer):
    def __init__(self, params, lr, tau, alpha=0.001):
        self.alpha = alpha

        if lr < 0.0:
            raise ValueError(f"Invalid learning rate {lr}.")

        defaults = dict(lr=lr, alpha=alpha, tau=tau)
        super(EASGD, self).__init__(params, defaults)

    def __setstate__(self, state):
        super(EASGD, self).__setstate__(state)

    def step(self, closure=None):
        loss = None
        if closure is not None:
            with torch.enable_grad():
                loss = closure()

        for group in self.param_groups:
            tau = group['tau']

            for t, p in enumerate(group['params']):
                x_normal = p.clone()
                x_tilde = p.clone()

                if p.grad is None:
                    continue

                if t % tau == 0:
                    p = p - self.alpha * (x_normal - x_tilde)
                    x_tilde = x_tilde + self.alpha * (x_normal - x_tilde)

                d_p = p.grad.data
                p.data.add_(d_p, alpha=-group['lr'])

        return loss

当我运行此代码时,我收到以下错误:

/home/user/github/test-repo/easgd.py:50:UserWarning:正在访问不是叶张量的张量的.grad 属性。在autograd.backward() 期间不会填充其 .grad 属性。如果您确实想要非叶张量的梯度,请在非叶张量上使用.retain_grad()。如果您错误地访问了非叶张量,请确保您访问的是叶张量。有关详细信息,请参阅 github.com/pytorch/pytorch/pull/30531。

阅读 this PyTorch Discussion 有助于了解叶变量和非叶变量之间的区别,但我不确定应该如何修复代码以使其正常工作。

任何关于做什么或在哪里看的提示都表示赞赏。谢谢。

【问题讨论】:

  • 您确定for t, p in enumerate(group['params']): 中的p 是叶张量吗?

标签: pytorch


【解决方案1】:

我认为问题是你在这一行复制p

p = p - self.alpha * (x_normal - x_tilde)

如果此行被执行(在第一个循环中t=0 的情况下)以下行将引发错误,因为p 不再具有.grad 属性。

您应该改用就地运算符,add_mult_sub_divide_ 等...

for t, p in enumerate(group['params']):
    if p.grad is None:
        continue
    d_p = p.grad.data

    if t % tau == 0:
        d_p.sub_(self.alpha*0.01)

    p.data.add_(d_p, alpha=-group['lr'])

上面,我删除了x_normalx_tilde,因为你没有给它们正确的值。但我希望你能明白。仅在处理 step 函数内的数据时使用 inplace 运算符。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-28
    • 1970-01-01
    相关资源
    最近更新 更多