Logo
Section 1 / 4

损失函数

了解损失函数的基本概念。

导入

损失函数

了解损失函数的基本概念。

损失函数用于评估我们的算法对数据集的建模效果。它计算单个训练样本中模型预测输出与真实标签(ground truth)之间的差异,也被称为误差函数。

它反映了预测输出偏离期望输出的程度。我们可以将损失函数理解为未能得到正确输出所付出的“惩罚”。

大多数优化问题都会使用损失函数,其主要目标是最小化损失,从而最大化模型的准确性。损失越低,说明模型表现越好。

给定以下合成数据,我们可以通过以下步骤计算金属价格预测($/盎司)的总损失:

  • 将预测值与实际值相减;
  • 取差值的绝对值。
金属预测值实际值总损失
黄金
铂金
1995.80
998.32
1998.30
999.34
3.52(黄金2.50,铂金1.02)
黄金
铂金
2003.12
999.34
1998.30
999.34
4.82(黄金4.82,铂金0)
黄金
铂金
1998.05
995.81
1998.30
999.34
3.78(黄金0.25,铂金3.53)

注意:损失函数不关心误差的方向,仅关注偏差大小。

PyTorch Image Models 提供了以下标准损失函数:

  • LabelSmoothingCrossEntropy
  • SoftTargetCrossEntropy

LabelSmoothingCrossEntropy 函数

LabelSmoothingCrossEntropy 函数的工作方式与负对数似然损失(NLL Loss)相同,但多了一个 smoothing 参数。NLL 损失的公式为:

L(y)=−log⁡(y)L(y) = -\log(y)

下图展示了负对数似然损失的取值范围:

...
当输入为0时损失趋近于无穷大,输入为1时损失趋近于0

以下预测及其对应的总 NLL 损失值,展示了真实标签与负对数似然损失之间的关系。

注意:加粗文字表示正确的类别(真实标签),每个类别下方的数值代表该类别的预测概率。

类别1类别2类别3总损失
0.710.260.040.34
0.490.490.020.71
0.020.000.980.02

假设某图像的真实类别为类别1,模型预测结果如下:

  • 类别1(真实类别):0.71
  • 类别2:0.26
  • 类别3:0.04

此时,负对数似然损失值为 0.34。

注意:对正确类别的预测置信度越高,总损失越低。

标签平滑(Label Smoothing)

标签平滑是机器学习中处理数据集中错误标签的一种特殊技术。

LabelSmoothingCrossEntropy 类提供了一个 smoothing 参数用于此类场景。该参数接受一个介于 0 和 1 之间的浮点数。当数据集中可能存在较多错误标签时,应设置较高的 smoothing 值。

smoothing 参数会在预测正确时增加损失,在预测错误时减少损失,从而使模型在预测出错时受到的“惩罚”更轻。以下代码通过比较 smoothing=0.0 和 smoothing=0.1 的结果来说明这一点:

1import timm 2import torch 3import torch.nn.functional as F 4from timm.loss import LabelSmoothingCrossEntropy 5 6x = torch.eye(2) 7x_i = 1 - x 8y = torch.arange(2) 9 10# smoothing 值为 0.0 11print('Tensor for smoothing value of 0.0 is:') 12print(LabelSmoothingCrossEntropy(0.0)(x,y), LabelSmoothingCrossEntropy(0.0)(x_i,y)) 13 14# smoothing 值为 0.1 15print('Tensor for smoothing value of 0.1 is:') 16print(LabelSmoothingCrossEntropy(0.1)(x,y), LabelSmoothingCrossEntropy(0.1)(x_i,y))

每次调用返回一个张量,表示经过标签平滑后的平均损失。

SoftTargetCrossEntropy 函数

SoftTargetCrossEntropy 是一种特殊的 log_softmax 函数,通常与 mixup 数据增强方法配合使用。

可通过调用 mixup_target 函数实现标签平滑,并可调节目标标签混合的程度:

1y = mixup_target(torch.tensor([1,4]), 5, lam=0.7)
  • target:目标张量;
  • num_classes:类别总数;
  • lam:Cutmix 的 lambda 值(默认为 1.0);
  • smoothing:平滑系数(默认为 0.0);
  • device:运行设备(GPU 或 CPU,默认为 cuda)。
1import timm 2import torch 3import torch.nn.functional as F 4from timm.loss import SoftTargetCrossEntropy 5from timm.data.mixup import mixup_target 6 7x = torch.tensor([[[0,1.,0,0,1.]], [[1.,1.,1.,1.,1.]]], device='cpu') 8 9# 使用默认平滑值 0.0 10print('Tensor for smoothing value of 0.0 is:') 11y1 = mixup_target(torch.tensor([1,4], device='cpu'), 5, lam=0.7, device='cpu') 12print(y1) 13 14# 使用平滑值 0.1 15print('Tensor for smoothing value of 0.1 is:') 16y2 = mixup_target(torch.tensor([1,4], device='cpu'), 5, lam=0.7, smoothing=0.1, device='cpu') 17print(y2)

注意:如果在没有 GPU 的机器上运行,请务必设置 device='cpu'。

对于每个输入张量,该函数返回对应 MixUp 增强后的标签张量,随后可调用 SoftTargetCrossEntropy 函数进行损失计算。

1import timm 2import torch 3import torch.nn.functional as F 4from timm.loss import SoftTargetCrossEntropy 5from timm.data.mixup import mixup_target 6 7x = torch.tensor([[[0,1.,0,0,1.]], [[1.,1.,1.,1.,1.]]], device='cpu') 8 9# 使用默认平滑值 0.0 10y = mixup_target(torch.tensor([1,4], device='cpu'), 5, lam=0.7, device='cpu') 11 12# 输出张量1和张量2的平均损失 13print('The mean loss output for tensor 1 and 2 is:') 14print(SoftTargetCrossEntropy()(x[0],y),SoftTargetCrossEntropy()(x[1],y))

输出结果为一个张量,表示计算得到的平均损失值。

附录

非对称损失