目录
PyTorch 的⼗七个损失函数
我们所说的优化,即优化网络权值使得损失函数值变小。但是,损失函数值变小是否能代表模型的分类/回归精度变高呢?那么多种损失函数,应该如何选择呢?请来了解PyTorch 中给出的十七种损失函数吧。
1. L1loss
class torch.nn.L1Loss(size_average=None, reduce=None)
官方文档中仍有 reduction='elementwise_mean'参数,但代码实现中已经删除该参数
功能:
计算 output 和 target 之差的绝对值,可选返回同维度的 tensor 或者是一个标量。
计算公式:
reduce(bool)- 返回值是否为标量,默认为 True
size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和
2. MSELoss
class torch.nn.MSELoss(size_average=None, reduce=None, reduction='elementwise_mean')
官方文档中仍有 reduction='elementwise_mean'参数,但代码实现中已经删除该参数
功能:
计算 output 和 target 之差的平方,可选返回同维度的 tensor 或者是一个标量。
计算公式:
参数:
reduce(bool)- 返回值是否为标量,默认为 True
size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和
3. CrossEntropyLoss
class torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='elementwise_mean')
功能:
将输入经过 softmax **函数之后,再计算其与 target 的交叉熵损失。即该方法将nn.LogSoftmax()和 nn.NLLLoss()进行了结合。严格意义上的交叉熵损失函数应该是nn.NLLLoss()
补充:小谈交叉熵损失函数交叉熵损失(cross-entropy Loss) 又称为对数似然损失(Log-likelihood Loss)、对数损失;二分类时还可称之为逻辑斯谛回归损失(Logistic Loss)。交叉熵损失函数表达式为 L =- sigama(y_i * log(x_i))。pytroch 这里不是严格意义上的交叉熵损失函数,而是先将 input 经过 softmax **函数,将向量“归一化”成概率形式,然后再与 target 计算严格意义上交叉熵损失。在多分类任务中,经常采用 softmax **函数+交叉熵损失函数,因为交叉熵描述了两个概率分布的差异,然而神经网络输出的是向量,并不是概率分布的形式。所以需要 softmax**函数将一个向量进行“归一化”成概率分布的形式,再采用交叉熵损失函数计算 loss。再回顾 PyTorch 的 CrossEntropyLoss(),官方文档中将 nn.LogSoftmax()和 nn.NLLLoss()进行了结合,nn.LogSoftmax() 相当于**函数 , nn.NLLLoss()是损失函数,将其结合,完整的是否可以叫做 softmax+交叉熵损失函数呢?
计算公式:
参数:
weight(Tensor)- 为每个类别的 loss 设置权值,常用于类别不均衡问题。weight 必须是 float类型的 tensor,其长度要于类别 C 一致,即每一个类别都要设置有 weight。带 weight 的计算公式:
size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。
reduce(bool)- 返回值是否为标量,默认为 True
ignore_index(int)- 忽略某一类别,不计算其 loss,其 loss 会为 0,并且,在采用size_average 时,不会计算那一类的 loss,除的时候的分母也不会统计那一类的样本。
补充:
output 不仅可以是向量,还可以是图片,即对图像进行像素点的分类,这个例子可以从 NLLLoss()中看到,这在图像分割当中很有用。
4. NLLLoss
class torch.nn.NLLLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='elementwise_mean')
功能:
计算公式:loss(input, class) = -input[class]。举个例,三分类任务,input=[-1.233, 2.657, 0.534], 真实标签为 2(class=2),则 loss 为-0.534。就是对应类别上的输出,取一个负号!感觉被 NLLLoss 的名字欺骗了。
实际应用:
常用于多分类任务,但是 input 在输入 NLLLoss()之前,需要对 input 进行 log_softmax 函数**,即将 input 转换成概率分布的形式,并且取对数。其实这些步骤在 CrossEntropyLoss中就有,如果不想让网络的最后一层是 log_softmax 层的话,就可以采用CrossEntropyLoss
完全代替此函数
参数:
weight(Tensor)- 为每个类别的 loss 设置权值,常用于类别不均衡问题。weight 必须是 float类型的 tensor,其长度要于类别 C 一致,即每一个类别都要设置有 weight。
size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为除以权重之和的平均值;为 False 时,返回的各样本的 loss 之和。
reduce(bool)- 返回值是否为标量,默认为 True。
ignore_index(int)- 忽略某一类别,不计算其 loss,其 loss 会为 0,并且,在采用size_average 时,不会计算那一类的 loss,除的时候的分母也不会统计那一类的样本。
5. PoissonNLLLoss
class torch.nn.PoissonNLLLoss(log_input=True, full=False, size_average=None, eps=1e-08, reduce=None, reduction='elementwise_mean')
功能:
用于 target 服从泊松分布的分类任务。
计算公式:
参数:
log_input(bool)- 为 True 时,计算公式为:loss(input,target)=exp(input) - target * input;
为 False 时,loss(input,target)=input - target * log(input+eps)
full(bool)- 是否计算全部的 loss。例如,当采用斯特林公式近似阶乘项时,此为target*log(target) - target+0.5∗log(2πtarget)
eps(float)- 当 log_input = False 时,用来防止计算 log(0),而增加的一个修正项。即loss(input,target)=input - target * log(input+eps)
size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。
reduce(bool)- 返回值是否为标量,默认为 True
6. KLDivLoss
class torch.nn.KLDivLoss(size_average=None, reduce=None, reduction='elementwise_mean')
功能:
计算 input 和 target 之间的 KL 散度( Kullback–Leibler divergence) 。
计算公式:
补充:KL 散度
KL 散度( Kullback–Leibler divergence) 又称为相对熵(Relative Entropy),用于描述两个概率分布之间的差异。计算公式(离散时):
其中 p 表示真实分布,q 表示 p 的拟合分布, D(P||Q)表示当用概率分布 q 来拟合真实分布 p 时,产生的信息损耗。这里的信息损耗,可以理解为损失,损失越低,拟合分布 q越接近真实分布 p。同时也可以从另外一个角度上观察这个公式,即计算的是 p 与 q 之间的对数差在 p 上的期望值。
特别注意,D(p||q) ≠ D(q||p), 其不具有对称性,因此不能称为 K-L 距离。
信息熵 = 交叉熵 - 相对熵
从信息论角度观察三者,其关系为信息熵 = 交叉熵 - 相对熵。在机器学习中,当训练数据固定,最小化相对熵 D(p||q) 等价于最小化交叉熵 H(p,q) 。
参数:
size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值,平均值为
element-wise 的,而不是针对样本的平均;为 False 时,返回是各样本各维度的 loss 之和。
reduce(bool)- 返回值是否为标量,默认为 True。
使用注意事项:
要想获得真正的 KL 散度,需要如下操作:
1. reduce = True ;size_average=False
2. 计算得到的 loss 要对 batch 进行求平均
7. BCELoss
class torch.nn.BCELoss(weight=None, size_average=None, reduce=None, reduction='elementwise_mean')
功能:
二分类任务时的交叉熵计算函数。此函数可以认为是 nn.CrossEntropyLoss 函数的特例。其分类限定为二分类,y 必须是{0,1}。还需要注意的是,input 应该为概率分布的形式,这样才符合交叉熵的应用。所以在 BCELoss 之前,input 一般为 sigmoid **层的输出,官方例子也是这样给的。该损失函数在自编码器中常用。
计算公式:
参数:
weight(Tensor)- 为每个类别的 loss 设置权值,常用于类别不均衡问题。
size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。
reduce(bool)- 返回值是否为标量,默认为 True
8. BCEWithLogitsLoss
class torch.nn.BCEWithLogitsLoss(weight=None, size_average=None, reduce=None, reduction='elementwise_mean', pos_weight=None)
功能:
将 Sigmoid 与 BCELoss 结合,类似于 CrossEntropyLoss(将 nn.LogSoftmax()和 nn.NLLLoss()进行结合)。即 input 会经过 Sigmoid **函数,将 input 变成概率分布的形式。
计算公式:
参数:
weight(Tensor)- : 为 batch 中单个样本设置权值,If given, has to be a Tensor of size “nbatch”.
pos_weight-: 正样本的权重, 当 p>1,提高召回率,当 P<1,提高精确度。可达到权衡召回率(Recall)和精确度(Precision)的作用。 Must be a vector with length equal to the number of classes.
size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。
reduce(bool)- 返回值是否为标量,默认为 True
9. MarginRankingLoss
class torch.nn.MarginRankingLoss(margin=0, size_average=None, reduce=None, reduction='elementwise_mean')
功能:
计算两个向量之间的相似度,当两个向量之间的距离大于 margin,则 loss 为正,小于margin,loss 为 0。
计算公式:
参数:
margin(float)- x1 和 x2 之间的差异。
size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。
reduce(bool)- 返回值是否为标量,默认为 True。
10. HingeEmbeddingLoss
class torch.nn.HingeEmbeddingLoss(margin=1.0, size_average=None, reduce=None, reduction='elementwise_mean')
功能:
未知。为折页损失的拓展,主要用于衡量两个输入是否相似。 used for learning nonlinear embeddings or semi-supervised 。
计算公式:
参数:
margin(float)- 默认值为 1,容忍的差距。
size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False
时,返回的各样本的 loss 之和。
reduce(bool)- 返回值是否为标量,默认为 True。
11. MultiLabelMarginLoss
class torch.nn.MultiLabelMarginLoss(size_average=None, reduce=None, reduction='elementwise_mean')
功能:
用于一个样本属于多个类别时的分类任务。例如一个四分类任务,样本 x 属于第 0类,第 1 类,不属于第 2 类,第 3 类。
计算公式:
x[y[j]] 表示 样本 x 所属类的输出值,x[i]表示不等于该类的输出值。
参数:
size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。
reduce(bool)- 返回值是否为标量,默认为 True。
Input: (C) or (N,C) where N is the batch size and C is the number of classes.
Target: (C) or (N,C), same shape as the input.
12. SmoothL1Loss
class torch.nn.SmoothL1Loss(size_average=None, reduce=None, reduction='elementwise_mean')
功能:
计算平滑 L1 损失,属于 Huber Loss 中的一种(因为参数 δ 固定为 1 了)。
补充:
Huber Loss 常用于回归问题,其最大的特点是对离群点(outliers)、噪声不敏感,具有较强的鲁棒性。
公式为:
理解为,当误差绝对值小于 δ,采用 L2 损失;若大于 δ,采用 L1 损失。
回到 SmoothL1Loss,这是 δ=1 时的 Huber Loss。
计算公式为:
对应红色线:
参数:
size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。
reduce(bool)- 返回值是否为标量,默认为 True。
13. SoftMarginLoss
class torch.nn.SoftMarginLoss(size_average=None, reduce=None, reduction='elementwise_mean')
功能:
Creates a criterion that optimizes a two-class classification logistic loss between input tensor x and target tensor y (containing 1 or -1). (暂时看不懂怎么用,有了解的朋友欢迎补充!)
计算公式:
参数:
size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。
reduce(bool)- 返回值是否为标量,默认为 True。
14. MultiLabelSoftMarginLoss
class torch.nn.MultiLabelSoftMarginLoss(weight=None, size_average=None, reduce=None, reduction='elementwise_mean')
功能:
SoftMarginLoss 多标签版本,a multi-label one-versus-all loss based on max-entropy,
计算公式:
参数:
weight(Tensor)- 为每个类别的 loss 设置权值。weight 必须是 float 类型的 tensor,其长度要于类别 C 一致,即每一个类别都要设置有 weight。
15. CosineEmbeddingLoss
class torch.nn.CosineEmbeddingLoss(margin=0, size_average=None, reduce=None, reduction='elementwise_mean')
功能:
用 Cosine 函数来衡量两个输入是否相似。 used for learning nonlinear embeddings or semi-supervised 。
计算公式:
参数:
margin(float)- : 取值范围[-1,1], 推荐设置范围 [0, 0.5]
size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。
reduce(bool)- 返回值是否为标量,默认为 True。
16. MultiMarginLoss
class torch.nn.MultiMarginLoss(p=1, margin=1, weight=None, size_average=None, reduce=None, reduction='elementwise_mean')
功能:
计算多分类的折页损失。
计算公式:
参数:
p(int)- 默认值为 1,仅可选 1 或者 2。
margin(float)- 默认值为 1
weight(Tensor)- 为每个类别的 loss 设置权值。weight 必须是 float 类型的 tensor,其长度要于类别 C 一致,即每一个类别都要设置有 weight。
size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。
reduce(bool)- 返回值是否为标量,默认为 True。
17. TripletMarginLoss
class torch.nn.TripletMarginLoss(margin=1.0, p=2, eps=1e-06, swap=False, size_average=None, reduce=None, reduction='elementwise_mean')
功能:
计算三元组损失,人脸验证中常用。
如下图 Anchor、Negative、Positive,目标是让 Positive 元和 Anchor 元之间的距离尽可能的小,Positive 元和 Negative 元之间的距离尽可能的大。
从公式上看,Anchor 元和 Positive 元之间的距离加上一个 threshold 之后,要小于Anchor 元与 Negative 元之间的距离。
计算公式:
参数:
margin(float)- 默认值为 1
p(int)- The norm degree ,默认值为 2
swap(float)– The distance swap is described in detail in the paper Learning shallow convolutional feature descriptors with triplet losses by V. Balntas, E. Riba et al. Default: False
size_average(bool)- 当 reduce=True 时有效。为 True 时,返回的 loss 为平均值;为 False时,返回的各样本的 loss 之和。
reduce(bool)- 返回值是否为标量,默认为 True。