【问题标题】:PyTorch - using `param.grad` affects learning process? [Solved]PyTorch - 使用“param.grad”会影响学习过程? [解决了]
【发布时间】:2021-01-25 07:01:56
【问题描述】:

我正在 CIFAR-10 上训练 ResNet34。当我尝试为model.parameters() 操作param.grad 时,我的行为非常奇怪。

下面的函数是所有混乱发生的地方。由于试图了解发生了什么,它目前没有做任何有用的事情。

def add_error(error):
    params = (param for param in model.parameters() if param.requires_grad)
    # [param.grad + err for param, err in zip(params, error)]                        # Line 2
    # new_error = [param.grad + err for param, err in zip(params, error)]            # Line 3
    for param in params:
      param.grad.zero_()
    # new_error = [torch.zeros(param.grad.shape, device=device) for param in params] # Line 6
    return new_error

在梯度下降步骤中使用:

def step(model, optimizer, batch, labels, error):
  optimizer.zero_grad()
  loss = compute_loss(model, batch, labels)
  loss.backward()

  new_error = add_error(error=error)      <- add_error is called here
  optimizer.step()
  return new_error

其中优化器是optim.SGD(model.parameters(), lr=0.1)compute_loss 本质上是在model(batch)labels 上调用nn.CrossEntropyLoss()

我的期望:由于我将梯度设置为 0,所以无论我做什么,都不会改变:损失应该始终在原始值 (2.4) 附近

实际发生的情况

  • 当我只取消注释第 6 行时,一切正常:损失接近常数 2.4
  • 当我只取消注释第 3 行时,学习就像我根本没有调用 add_error 一样发生。 IE。损失以与通常 SGD 相同的速度减少:2.4 -&gt; 1.7 -&gt; 1.3 -&gt; ...(每个 epoch)。换句话说,梯度以某种方式传播。
  • 当我取消注释第 2 行和第 6 行时:最奇怪的事情。损失增加4.3,然后慢慢减少4.3 -&gt; 4.2 -&gt; 4.14 -&gt; 4.1 -&gt; ...(我怀疑这种减少是批量标准化的结果)。

请注意,在这两种情况下,我实际上都没有使用error,实际上我从未使用error 来更新渐变。 此外,像第 2 行这样添加更多行不会影响结果。

问题:发生了什么?

  • 为什么损失会减少?梯度应始终为 $0$。
  • 如何改变损失值本身?

如果有帮助,我可能会尝试生成 MCVE 并将其发布在 pastebin 上(这将是一堵代码墙,太大而无法放在这里)。

【问题讨论】:

    标签: python neural-network pytorch


    【解决方案1】:

    这个问题非常愚蠢:params 是一个生成器,在第一次迭代后就耗尽了。创建一个列表而不是生成器可以解决这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-08
      • 2020-07-09
      • 2020-11-04
      • 1970-01-01
      • 1970-01-01
      • 2021-04-15
      • 2020-11-16
      相关资源
      最近更新 更多