- pytorch中的损失函数
- 0.前言
- 1.Loss Function
- 1.1 _Loss基类
- 1.2 nn.CrossEntropyLoss
- 1.3 nn.NLLLoss
- 1.4 nn.BCELoss
- 1.5 nn.BCEWithLogitsLoss
- 1.6 nn.L1Loss(数据回归)
- 1.7 nn.MSELoss(数据回归)
- 1.8 nn.SmoothL1Loss(数据回归)
- 1.9 nn.PoissonNLLLoss
- 1.10 nn.KLDivLoss
- 1.11 nn.MarginRankingLoss
- 1.12 nn.MultiLabelMarginLoss(多标签分类)
- 1.13 nn.SoftMarginLoss(二分类)
- 1.14 MultiLabelSoftMarginLoss
- 1.15 nn.MultiMarginLoss(多分类)
- 1.16 TripletMarginLoss(三元组损失)
- 1.17 TripletMarginLoss(非线性embedding和半监督学习)
- 1.18 CosineEmbeddingLoss(embedding和半监督学习)
- 1.19 nn.CTCLoss
pytorch中的损失函数
0.前言
深度学习中优化方法直接作用的对象是损失函数。损失函数表示了预测值与真实值之间的差距程度,一个最优化问题的目标是将损失函数最小化,针对分类问题,直观的表现就是.分类的正确样本越多越好;回归问题中,直观的表现就是预测值与实际值的误差越小越好。
- 损失函数(Loss Function):
L o s s = f ( y , , y ) Loss=f(y^,,y) Loss=f(y,,y) - 代价函数(Cost Fuction):
C o s t = 1 N ∑ i = 0 N f ( y i , y i ) Cost=\frac{1}{N}\sum_{i=0}^{N}f(y_{i}^, y_{i}) Cost=N1i=0∑Nf(yi,yi)
Pytorch中nn模块下提供了多种可以直接使用的损失函数,如交叉熵、均方误差等,针对不同的问题,可以直接调用现有的损失函数,常用的损失函数以及适合的问题如下表。
类 | 损失函数名称 | 适应问题 |
---|---|---|
torch.nn.L1Loss() | 平均绝对值损失 | 回归 |
torch.nn.MSELoss() | 均方误差损失 | 回归 |
torch.nn.CrossEntropyLoss() | 交叉熵损失 | 多分类 |
torch.nn.CTCLoss() | ||
torch.nn.NLLLoss() | 负数对数似然函数损失 | 多分类 |
torch.nn.KLDivLoss() | KL散度损失 | 回归 |
torch.nn.BCELoss() | 二分类交叉熵损失 | 二分类 |
torch.nn.MarginRankingLoss | 评价相似度损失 | |
torch.nn.MultiLabelMarginLoss | 多标签分类损失 | 多标签分类 |
torch.nn.SmoothL1Loss | 平滑L1损失 | 回归 |
torch.nn.SoftMarginLoss | 多标签二分类损失 | 多标签二分类 |
接下来对部分损失函数,以及pytorch框架下的api进行整理说明。
1.Loss Function
1.1 _Loss基类
在pytorch中nn模块下定义的loss的源码类,分别定义LOSS的类以及的带有权重系数的类。
from .module import Module
from .. import functional as F
from .. import _reduction as _Reduction
from torch import Tensor
from typing import Optional
class _Loss(Module):
reduction: str
def __init__(self, size_average=None, reduce=None, reduction: str = 'mean') -> None:
super(_Loss, self).__init__()
if size_average is not None or reduce is not None:
self.reduction = _Reduction.legacy_get_string(size_average, reduce)
else:
self.reduction = reduction
class _WeightedLoss(_Loss):
def __init__(self, weight: Optional[Tensor] = None, size_average=None, reduce=None, reduction: str = 'mean') -> None:
super(_WeightedLoss, self).__init__(size_average, reduce, reduction)
self.register_buffer('weight', weight)
1.2 nn.CrossEntropyLoss
1.2.1 有关交叉熵、信息熵、相对熵的基本概念:
使用交叉熵是为衡量两个数据概率分布差异,所以交叉熵制越低两个值相差越相似。
交叉熵 = 信息熵 + 相对熵 \text{交叉熵 = 信息熵 + 相对熵} 交叉熵 = 信息熵 + 相对熵
1.交叉熵
H ( P , Q ) = − ∑ i = 1 N P ( x i ) l o g Q ( x i ) H(P,Q) = -\sum_{i=1}^NP(x_{i})logQ(x_{i}) H(P,Q)=−i=1∑NP(xi)logQ(xi)
2.自信息,衡量单个事件的不确定性
l ( x ) = − l o g [ p ( x ) ] l(x) = -log[p(x)] l(x)=−log[p(x)]
3.熵(信息熵),简答讲事件的越不确定性越大,熵的值越大,自信的期望
H ( P ) = E x p [ I ( x ) ] = − ∑ i N P ( x i ) l o g P ( x i ) H(P) = E_{x~p}[I(x)] = -\sum_{i}^NP(x_{i})logP(x_{i}) H(P)=Ex p[I(x)]=−i∑NP(xi)logP(xi)
4.相对熵(KL散度),衡量两个分布之间的差异,不具备对称性。
D K L ( P , Q ) = E x p [ l o g P ( x ) Q ( x ) ] = E x − p [ l o g P ( x ) − l o g Q ( x ) ] = ∑ i = 1 N P ( x i ) [ l o g P ( x i ) − l o g Q ( x i ) ] = ∑ i = 1 N P ( x i ) l o g P ( x i ) − ∑ i = 1 N P ( x i ) l o g Q ( x i ) = H ( P , Q ) − H ( P ) D_{KL}(P,Q) = E_{x~p}[log\frac{P(x)}{Q(x)}]\\=E_{x-p}[logP(x)-logQ(x)]\\=\sum_{i=1}^NP(x_{i})[logP(x_{i})-logQ(x_{i})]\\=\sum_{i=1}^NP(x_{i})logP(x_{i})-\sum_{i=1}^NP(x_{i})logQ(x_{i})\\=H(P,Q)-H(P) DKL(P,Q)=Ex p[logQ(x)P(x)]=Ex−p[logP(x)−logQ(x)]=i=1∑NP(xi)[logP(xi)−logQ(xi)]=i=1∑NP(xi)logP(xi)−i=1∑NP(xi)logQ(xi)=H(P,Q)−H(P)
结合上面的公式可以得出结论: 交叉熵: H ( P , Q ) = D K L ( P , Q ) + H ( P ) \text{交叉熵:}H(P, Q) = D_{KL}(P,Q)+H(P) 交叉熵:H(P,Q)=DKL(P,Q)+H(P),其中P代表实际样本的数据分布,Q代表预测结果的分布。
1.2.2 pytorch中的交叉熵
功能:nn.LogSoftmax()与nn.NLLLoss()结合,进行交叉熵计算。本该损失函数与公式中的交叉熵损失存在区别,采用了nn.LogSoftmax对数据进行归一化处理,即[0,1]的区间。
在官网的计算公式如下:
- 无权重
l o s s ( x , c l a s s ) = − l o g ( e x p (