我一直在尝试逐个研究PyTorch中的所有损失函数,并从头开始构建它们,以更好地理解它们。但我遇到了一个问题,不知道是我的重建有问题,还是PyTorch的实现有问题。
根据PyTorch的SmoothL1Loss文档,它简单地说明,如果预测值与真实值的绝对差值小于beta,我们使用上面的方程。否则,我们使用下面的方程。请查看文档以了解方程的详细信息。
以下是我以最小测试形式实现的代码:
import torchimport torch.nn as nnimport numpy as nppredictions = torch.randn(3, 5, requires_grad=True)target = torch.randn(3, 5)def l1_loss_smooth(predictions, targets, beta = 1.0): loss = 0 for x, y in zip(predictions, targets): if abs(x-y).mean() < beta: loss += (0.5*(x-y)**2 / beta).mean() else: loss += (abs(x-y) - 0.5 * beta).mean() loss = loss/predictions.shape[0]output = l1_loss_smooth(predictions, target)print(output)Gives an output of:tensor(0.7475, grad_fn=<DivBackward0>)
现在是PyTorch的实现:
loss = nn.SmoothL1Loss(beta=1.0)output = loss(predictions, target)Gives an output of:tensor(0.7603, grad_fn=<SmoothL1LossBackward>)
我无法找出实现中的错误所在。
在深入研究_C
模块中的smooth_l1_loss函数
(文件:smooth_c_loss_op.cc
)后,我注意到文档字符串提到这是一种Huber Loss的变体,但SmoothL1Loss
的文档说它是Huber Loss。
总的来说,我对它的实现方式感到困惑,不知道它是SmoothL1Loss和Huber Loss的组合,仅仅是Huber Loss,还是其他什么东西。
回答:
文档中的描述是正确的。您的实现错误地在数据的平均值上应用了情况选择。应该是对每个元素进行选择(如果您考虑到普通L1损失的实现,以及平滑L1损失的动机)。
以下代码给出了一个一致的结果: