【问题标题】:Custom loss function error: tensor does not have a grad_fn自定义损失函数错误:张量没有 grad_fn
【发布时间】:2021-03-09 18:09:39
【问题描述】:

尝试使用自定义损失函数并收到错误“RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn”。 loss.backward()期间发生错误

我知道所有计算都必须在“require_grad = True”的张量中完成。我在实现它时遇到了麻烦,因为我的代码需要一个嵌套的 for 循环。我相信这可能是 for 循环。有没有办法创建一个空张量并附加它?下面是我的代码。

def Gaussian_Kernal(x, mu, sigma):
  p = (1./(math.sqrt(2. * math.pi * (sigma**2)))) * torch.exp((-1.) * (((Variable(x)**2) - mu)/(2. * (sigma**2))))
  return p

class MEE(torch.nn.Module):
  def __init__(self):
    super(MEE,self).__init__()

  def forward(self,output, target, mu, variance):

    error = torch.subtract(Variable(output),Variable(target))
  
    error_diff = []
    for i in range(0, error.size(0)):
      for j in range(0, error.size(0)):
        error_diff.append(error[i] - error[j])

    error_diff = torch.cat(error_diff)
    torch.tensor(error_diff,requires_grad=True)

    loss = (1./(target.size(0)**2)) * torch.sum(Gaussian_Kernal(Variable(error_diff), mu, variance*(2**0.5)))

    loss = Variable(loss)

    return loss

【问题讨论】:

    标签: python machine-learning deep-learning pytorch recurrent-neural-network


    【解决方案1】:

    只要你对张量进行操作并应用 PyTorch 函数和基本运算符,它应该可以工作。因此无需使用torch.tensorVariable 包装您的变量。后者已被弃用(我相信从 v0.4 开始)。

    变量 API 已被弃用:变量不再是 必须将 autograd 与张量一起使用。自动自动分级 支持将 requires_grad 设置为 True 的张量。 PyTorch docs

    我假设 outputtarget 是张量,而 muvariance 是实数而不是张量?那么outputtarget 的第一个维度就是批次。

    def Gaussian_Kernel(x, mu, sigma):
      p = (1./(math.sqrt(2. * math.pi * (sigma**2)))) * torch.exp((-1.) * (((x**2) - mu)/(2. * (sigma**2))))
      return p
    
    class MEE(torch.nn.Module):
      def __init__(self):
        super(MEE, self).__init__()
    
      def forward(self, output, target, mu, variance):
        error = output - target
    
        error_diff = []
        for i in range(0, error.size(0)):
          for j in range(0, error.size(0)):
            error_diff.append(error[i] - error[j]) # Assuming that's the desired operation
    
        error_diff = torch.cat(error_diff)
        kernel = Gaussian_Kernel(error_diff, mu, variance*(2**0.5))
        loss = (1./(target.size(0)**2))*torch.sum(kernel)
        
        return loss
    

    【讨论】:

    • 你的假设是正确的。 mu 和方差是实数。张量的第一维是批量大小。我认为问题是error_diff 列表。我正在计算批次中每个点的误差差异。我认为从列表到张量的复制会导致错误,但我不确定。有没有办法只用张量来做这个操作?我认为这不是我的网络错误,因为简单的 MSELoss() 效果很好。
    • 那么应该是error[i] - error[j]。我不认为创建一个新列表error_diff 是一个问题,只要您创建一个堆栈或之后将它们连接成一个张量。还是不行吗?
    • 它仍然抛出同样的错误。我维护了错误[i] - 错误[j]。 torch.cat 将列表的副本创建为张量。
    • 如果有帮助,我也可以通过 colab 分享它
    • 它对我有用,请确保在 Gaussian_Kernel 函数中删除 Variable 包裹 x,我想你忘了删除它。
    猜你喜欢
    • 1970-01-01
    • 2018-02-22
    • 2020-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-10
    • 2021-01-03
    相关资源
    最近更新 更多