PyTorch 模型训练实用教程(四):损失函数
目录PyTorch 的⼗七个损失函数1. L1loss2. MSELoss3. CrossEntropyLoss4. NLLLoss5. PoissonNLLLoss6. KLDivLoss7. BCELoss8. BCEWithLogitsLoss9. MarginRankingLoss10. HingeEmbeddingLoss11. MultiLabelMarginLoss12. Smoot
·
目录
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)- Th e 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 。
更多推荐
所有评论(0)