我一直在Pytorch中试验L1和MSE损失,并注意到L1Loss的性能更好,因为它对异常值更健壮。我发现SmoothL1Loss似乎是两全其美。我知道它的行为类似于错误小于1的MSELoss,否则类似于L1Loss。我的数据集只包含0到1之间的值。因此,最大可能的错误是1。这是否意味着函数的行为与MSELoss相同?无论如何,是否有可能调整阈值以更好地解决我的问题?
最佳答案
是的,在这种情况下,它的行为就像torch.nn.MSELoss
一样,总共被称为Huber Loss
。
由于其性质,threshold
并没有多大意义,让我们看一下为什么会这样的示例:
怎么运行的
让我们比较在1.0
和MSELoss
情况下大于SmoothL1Loss
的错误。假设我们的绝对误差(|f(x) - y|
)是10
。 MSELoss
将赋予它100
的值(或者在实现50
的情况下为pytorch
),而SmoothL1Loss
仅给出该10
的值,因此对于大型模型而言,它不会付出太多代价错误。
如果值小于1.0
,则SmoothL1Loss
惩罚模型小于L1Loss
。例如。 0.5
将成为0.5*0.5
,因此,对于Huber来说是0.25
,对于0.5
是L1Loss
。
这不是“两全其美”,它取决于您的追求。 Mean Squared Error
-放大较大的错误,而对较小的错误轻描淡写,L1Loss
将错误赋予“相等”的权重。
自定义损失功能
尽管通常不会这样做,但是您可以根据自己的目标使用任何损失函数(阈值在这里实际上没有意义)。例如,如果您希望较小的错误更加严重,则可以执行以下操作:
import torch
def fancy_squared_loss(y_true, y_pred):
return torch.mean(torch.sqrt(torch.abs(y_true - y_pred)))
对于值
0.2
,您将得到~0.447
,对于0.5
~0.7
,依此类推。实验并检查手头任务是否存在任何特定的损失函数,尽管我认为这些实验不太可能显着提高L1Loss
的价值。自定义阈值
如果您确实想为
MSELoss
和L1Loss
设置自定义阈值,则可以自己实现:import torch
class CustomLoss:
def __init__(self, threshold: float = 0.5):
self.threshold = threshold
def __call__(self, predicted, true):
errors = torch.abs(predicted - true)
mask = errors < self.threshold
return (0.5 * mask * (errors ** 2)) + ~mask * errors
低于
threshold
的所有内容都将变为MSELoss
,高于上方的所有内容均具有L1Loss
。关于python - 针对特定情况实现SmoothL1Loss,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60252902/