Pytorch深入浅出(六)之损失函数(Loss Function)

在深度学习的“五步走”流程(数据 -> 模型 -> 损失函数 -> 优化器 -> 迭代训练)中,损失函数是模型的“指挥棒”。它衡量了模型预测值与真实值之间的差距,差距越小,模型越准。
本次笔记不涉及繁杂的数学推导,而是聚焦于PyTorch 中损失函数的选择,特别是如何避开常见的“坑”。

一、基本概念和Pytorch机制

1.基本概念

损失函数简单来说就是用来衡量模型输出(预测值)与真实标签(真实值)的差异的。
有三个概念很容易混淆:
损失函数:衡量单个样本的预测偏差。
Loss=f(y^,y)\text{Loss} = f(\hat{y}, y)Loss=f(y^,y)
代价函数:衡量整个批次 (Batch) 样本的平均损失。
Cost=1N∑i=0Nf(y^i,yi)\text{Cost} = \frac{1}{N} \sum_{i=0}^{N} f(\hat{y}_i, y_i)Cost=N1i=0Nf(y^i,yi)
目标函数:最终优化的目标,通常是 Cost + 正则化项
Obj=Cost+Regularization\text{Obj} = \text{Cost} + \text{Regularization}Obj=Cost+Regularization
注:在 PyTorch 训练中,loss.backward() 通常是针对 Cost 求梯度的。

2.PyTorch 损失函数的通用参数

在 PyTorch 中,几乎所有 Loss 函数都有一个共同参数 reduction,用于控制 Batch 维度的行为,以后不再赘述:

  • reduction='mean' (默认):计算 Batch 内所有样本损失的平均值(最常用)。
  • reduction='sum':计算 Batch 内所有样本损失的总和。
  • reduction='none':不进行规约,保留每个样本的 Loss,返回形状为 (Batch_Size, ...) 的向量。常用于需要对不同样本加权的场景。

注:size_averagereduce 参数已弃用,请忽略。

二、常见损失函数

我们将常见的损失函数按照任务类型(应用场景)来进行划分。

Ⅰ.回归任务(Regression)

1.L1Loss(MAE)

功能:计算inputs与targets之差的绝对值。

class torch.nn.L1Loss(size_average=None, reduce=None, reduction='mean')

特点:对异常值不敏感,梯度恒定
公式:L=∣y−y^∣L = |y - \hat{y}|L=yy^

2.MSELoss

功能:计算inputs与targets之差的平方。

class torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean')

特点:对大误差惩罚更强;假设误差服从高斯分布
公式:L=(y−y^)2L = (y - \hat{y})^2L=(yy^)2

3.SmoothL1Loss

功能:在误差较小时表现为 MSE,在误差较大时表现为 L1,平滑过渡

class torch.nn.SmoothL1Loss(size_average=None, reduce=None, reduction='mean', beta=1.0)

适用场景:既想要 MSE 的平滑梯度,又想降低异常值影响;目标检测(如 Faster R-CNN, SSD 的边框回归)
公式:L={0.5(xn−yn)2β,∣xn−yn∣<β∣xn−yn∣−0.5β,otherwiseL = \begin{cases} 0.5 \dfrac{(x_n-y_n)^2}{\beta}, & |x_n-y_n| < \beta \\[6pt] |x_n-y_n| - 0.5\beta, & \text{otherwise} \end{cases}L=0.5β(xnyn)2,xnyn0.5β,xnyn<βotherwise
参数解析:beta是转折点,越小 → 越像 L1,越大 → 越像 MSE

回归损失函数直观理解
在这里插入图片描述

回归损失函数的梯度对比
在这里插入图片描述

Ⅱ.分类任务(Classification)

1.CrossEntropyLoss

功能:Softmax + NLLLoss 的组合,用于多分类任务。

class torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='mean', label_smoothing=0.0)

适用场景:NNN 分类任务(如 ImageNet, CIFAR-10)
公式:L=−log⁡exy∑jexjL = -\log \frac{e^{x_{y}}}{\sum_j e^{x_j}}L=logjexjexy
参数解析:
weight:类别不平衡时使用
ignore_index:忽略某些标签(如 padding)
label_smoothing:防止模型过度自信;常用于大规模分类

2.NLLLoss

功能:计算负对数似然损失。

class torch.nn.NLLLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='mean')

适用场景:多分类;
公式:L=−log⁡p(y)L = -\log p(y)L=logp(y)
参数解析:
与 CrossEntropyLoss 类似,但是CrossEntropyLoss内部已经做了LogSoftmax

3.BCELoss

功能:二分类交叉熵损失。

class torch.nn.BCELoss(weight=None, size_average=None, reduce=None, reduction='mean')

适用场景:二分类;

4.BCEWithLogitsLoss

功能:Sigmoid + BCELoss 的融合版本。

class torch.nn.BCEWithLogitsLoss(weight=None, size_average=None, reduce=None, reduction='mean', pos_weight=None)

适用场景:二分类或多标签分类(一张图既有猫又有狗);
参数解析:pos_weight:正样本权重(类别不平衡)

损失函数任务类型输入典型输入shape真实标签shape标签 Dtype标签语义
CrossEntropyLoss单标签多分类logits(N, C)(N)Long (int64)标签必须是类别索引 (0~C-1),不能是 One-Hot 编码!
NLLLoss单标签多分类log-probabilities
LogSoftmax后的值
(N, C)(log-prob)(N)Long (int64)同上
BCELoss二分类 / 多标签probabilities
p ∈ (0,1)
(N, *)(N, *)Float0/1 或独立概率
容易出现 log⁡(0)\log(0)log(0) 导致的 NaN 问题,不推荐直接使用
BCEWithLogitsLoss二分类 / 多标签logits(N, *)(N, *)Float0/1 或独立概率
标签必须和输出形状一致,且必须是浮点数
5.KLDivLoss

功能:计算两个分布之间的 KL 散度。

class torch.nn.KLDivLoss(size_average=None, reduce=None, reduction='mean', log_target=False)

适用场景:知识蒸馏,衡量两个概率分布的差异;变分自编码器(VAE);
公式:DKL(P∥Q)=∑Plog⁡PQD_{\mathrm{KL}}(P\|Q) = \sum P \log\frac{P}{Q}DKL(PQ)=PlogQP,input 必须是 log-probability

  • 输入:预测值需为 Log 概率,真实值需为普通概率。

Ⅲ.排序与嵌入任务

1.TripletMarginLoss

功能:让Anchor(基准)和正样本靠得近,和负样本离得远。

class torch.nn.TripletMarginLoss(margin=1.0, p=2.0, eps=1e-06, swap=False, size_average=None, reduce=None, reduction='mean')

适用场景:人脸识别;度量学习;表征学习
公式:L=max⁡(0,  d(a,p)−d(a,n)+margin)L = \max\big( 0,\; d(a,p) - d(a,n) + margin \big)L=max(0,d(a,p)d(a,n)+margin),其中其中d(⋅)d(\cdot)d()通常为 L2 距离。

2.MarginRankingLoss

功能:比较两个输入的相对大小关系

class torch.nn.MarginRankingLoss(margin=0.0, size_average=None, reduce=None, reduction='mean'

适用场景:排序任务;推荐系统;学习“谁更大”
公式:L=max⁡ ⁣(0,  −y(x1−x2)+margin)L = \max\!\bigl(0,\; -y(x_1 - x_2) + \mathrm{margin}\bigr)L=max(0,y(x1x2)+margin)
参数解析:margin:负样本的最小间隔

3.CosineEmbeddingLoss

功能:基于余弦相似度判断样本相似性。

class torch.nn.CosineEmbeddingLoss(margin=0.0, size_average=None, reduce=None, reduction='mean')

适用场景:NLP中的语义相似度;向量相似度学习;学习非线性嵌入或半监督学习
公式:
L={1−cos⁡(x1,x2),y=1max⁡(0,cos⁡(x1,x2)−margin),y=−1L = \begin{cases} 1 - \cos(x_1, x_2), & y = 1 \\ \max(0, \cos(x_1, x_2) - margin), & y = -1 \end{cases}L={1cos(x1,x2),max(0,cos(x1,x2)margin),y=1y=1
参数解析:margin:负样本允许的最大相似度

Ⅳ.其他冷门/特定领域损失

1.PoissonNLLLoss

功能:泊松分布的负对数似然损失函数。

class torch.nn.PoissonNLLLoss(log_input=True, full=False, eps=1e-08, reduction='mean')

适用场景:计数型回归;事件发生次数(如点击数、到达次数)
公式:L=y^−ylog⁡(y^)L = \hat{y} - y \log(\hat{y})L=y^ylog(y^)
参数解析:
log_input:True:输入是 log(λ);False:输入是 λ
full:是否计算完整损失,即添加斯特林近似项
eps:数值稳定,用于避免计算 log⁡(0)log⁡(0)log(0) 的小值

2.CTCLoss

功能:连接时序分类损失。

class torch.nn.CTCLoss(blank=0, reduction='mean', zero_infinity=False)

适用场景:语音识别;OCR;解决输入序列(语音帧)和输出序列(文本)长度不对齐的问题。

3.HingeEmbeddingLoss

功能:学习样本之间的相似性或举例。

class torch.nn.HingeEmbeddingLoss(margin=1.0, size_average=None, reduce=None, reduction='mean')

适用场景:相似 / 不相似样本对学习;度量学习、聚类前表征学习
公式:设输入为 xxx,标签 y∈y ∈y{1,-1}:
L={x,y=1max⁡(0,margin−x),y=−1L = \begin{cases} x, & y = 1 \\ \max(0, margin - x), & y = -1 \end{cases}L={x,max(0,marginx),y=1y=1

4.SoftMarginLoss

功能:Hinge Loss 的平滑版本。

class torch.nn.SoftMarginLoss(size_average=None, reduce=None, reduction='mean')

适用场景:二分类;替代 hinge loss,梯度更平滑
公式:y∈y ∈y{1,-1},x.nelement()x.nelement()x.nelement()xxx中元素的数量,用于对损失进行平均
loss(x,y)=∑ilog⁡(1+exp⁡(−y[i]⋅x[i]))x.nelement()\text{loss}(x, y) = \sum_i \frac{\log(1 + \exp(-y[i] \cdot x[i]))}{x.\text{nelement()}}loss(x,y)=ix.nelement()log(1+exp(y[i]x[i]))

5.MultiMarginLoss

功能:多分类的 margin-based 损失。

class torch.nn.MultiMarginLoss(p=1, margin=1.0, weight=None, size_average=None, reduce=None, reduction='mean')

适用场景:多分类;类似SVM的思想,强调类别间间隔
公式:设真实类别为yyyL=∑j≠ymax⁡(0,xj−xy+margin)L = \sum_{j \neq y} \max(0, x_j - x_y + margin)L=j=ymax(0,xjxy+margin)

6.MultiLabelMarginLoss

功能:多标签分类的 margin-based 损失。

class torch.nn.MultiLabelMarginLoss(size_average=None, reduce=None, reduction='mean')

适用场景:一个样本属于多个类别;标签以 索引形式 给出(不是 one-hot)
公式:
loss(x,y)=∑ijmax⁡(0,1−(x[y[j]]−x[i]))x.size(0)\text{loss}(x, y) = \sum_{ij} \frac{\max(0, 1 - (x[y[j]] - x[i]))}{x.\text{size}(0)}loss(x,y)=ijx.size(0)max(0,1(x[y[j]]x[i]))
x∈{0,⋯ ,x.size(0)−1}x \in \{0, \cdots, x.size(0) - 1\} \quadx{0,,x.size(0)1}表示输入样本的索引。
y∈{0,⋯ ,y.size(0)−1}y \in \{0, \cdots, y.size(0) - 1\}y{0,,y.size(0)1} 表示标签的索引。
0≤y[j]≤x.size(0)−10 \leq y[j] \leq x.size(0) - 10y[j]x.size(0)1i≠y[j]i \neq y[j]i=y[j]表示对于所有的 iiijjjy[j]y[j]y[j] 是一个有效的索引,且 iiiy[j]y[j]y[j] 不能相等。

7.MultiLabelSoftMarginLoss

功能:多标签分类的 SoftMargin 版本。

class torch.nn.MultiLabelSoftMarginLoss(weight=None, size_average=None, reduce=None, reduction='mean')

适用场景:多标签分类;输出为 logits;每个类别独立进行二分类判断
公式:L=−1C∑c=1C[yclog⁡σ(xc)+(1−yc)log⁡(1−σ(xc))]L = -\frac{1}{C}\sum_{c=1}^C \left[ y_c \log \sigma(x_c) + (1-y_c)\log(1-\sigma(x_c)) \right]L=C1c=1C[yclogσ(xc)+(1yc)log(1σ(xc))]

⚠️ 早期的多分类 Margin 损失,现在用的较少,通常被 CrossEntropy 或 BCE 取代。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值