pytorch 根据输出和目标之间的差异,使用不同的公式为自定义损失函数生成标量输出

vq8itlhq  于 2023-03-02  发布在  其他
关注(0)|答案(1)|浏览(110)

目前正在尝试使用以下逻辑实现线性回归的自定义损失函数:* 如果模型输出值大于或等于目标,则回波损耗为(输出-目标)。* 如果模型输出值小于目标,则回波损耗为(目标-输出)^2

以下是我当前的实现:

import torch.nn as nn
class E_Loss(nn.Module):
    def __init__(self, weight=None, size_average=True):
      super(E_Loss, self).__init__()
    def forward(self, inputs, targets, smooth=1):
      inputs = inputs.view(-1)
      targets = targets.view(-1)
      is_greater = torch.gt(inputs, outputs)
      print(is_greater)
      if is_greater: #torch.gt(inputs, targets):
        loss = (inputs - targets)
      else:
        loss = np.square(targets - outputs)
      return loss

当运行我的模型进行训练时,我在loss. backward()step上得到这个错误:运行时错误:只能为标量输出隐式创建grad
假设它需要一个标量输出,我如何重写我的损失函数来产生这个?重写我的代码不使用数据加载器会更容易吗?

以下是整个模型部分

x一个一个一个一个x一个一个二个x

x3naxklr

x3naxklr1#

你发布的代码没有任何意义

  • is_greater = torch.gt(inputs, outputs)使用了未定义的变量outputs
  • torch.gt是一个基于元素的大于运算,除非inputsoutputs都是标量,否则在条件语句中使用它的结果是没有意义的。由于批处理大小为64,因此应该会得到一个异常RuntimeError: Boolean value of tensor with more than one value is ambiguous
  • 你直接在torchTensor上使用numpy函数np.square。这是不明确的,可能会也可能不会起作用,这取决于它是如何实现的。使用PyTorch函数和PyTorchTensor。Tensor支持大多数python运算符,所以只需要使用x**2x*x来做元素平方。

您提出的错误表明,尽管存在所有明显的错误,您仍然能够运行损失函数代码,但反向传播失败,因为损失函数不是标量值。您发布的代码对我来说无法运行,而且似乎也没有执行任何形式的均值缩减。假设上述问题得到解决,并且它实际上运行。那么我就预料到你会遇到这样的错误。出现这个错误是因为Tensor.backward要求Tensor是标量值,即损失应该是一个数字。通常,这是通过对整个批次的损失求平均值来实现的。
为了解决损失函数的实现问题,如果将所描述的函数视为output - target的函数,则该函数更容易实现。由于output >= target等价于output - target >= 0,因此在令x = output - target之后,我们只需要在x为非负时等于x,否则等于x**2的函数。
这可以通过不同的方法来实现,但一个简单的方法是认识到Tensor.relu可以用来将函数分解为正项和负项x = relu(x) + (-relu(-x))。使用这个恒等式,很有可能很清楚你想要的是loss = relu(x) + relu(-x)**2。解决均值缩减问题以及损失函数的工作版本可以是:

class E_loss(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, outputs, targets):
        x = outputs.flatten() - targets.flatten()
        return (x.relu() + ((-x).relu())**2).mean()

相关问题