当前位置:   article > 正文

多标签分类、BCELoss和BCEWithLogitsLoss用法

多标签分类、BCELoss和BCEWithLogitsLoss用法

他们都用于多类别多分类

BCELoss

在图片多标签分类时,如果3张图片分3类,会输出一个3*3的矩阵。

在这里插入图片描述

先用Sigmoid给这些值都搞到0~1之间:

在这里插入图片描述

假设Target是:

在这里插入图片描述


下面用BCELoss来验证一下Loss是不是0.7194!

在这里插入图片描述

应该是上面每次都保留4位小数,算到最后误差越来越大差了0.0001。

BCEWithLogitsLoss

BCEWithLogitsLoss就是把Sigmoid-BCELoss合成一步。直接用刚刚的input验证一下是不是0.7193:

在这里插入图片描述

什么是多标签分类

学习过机器学习的你,也许对分类问题很熟悉。比如下图:

图片中是否包含房子?你的回答就是有或者没有,这就是一个典型的二分类问题。

同样,是这幅照片,问题变成了,这幅照片是谁拍摄的?备选答案你,你的父亲,你的母亲?这就变成了一个多分类问题。

但今天谈论的多标签是什么呢?
如果我问你上面图包含一座房子吗?选项会是YES或NO。

你会发现图中所示的答案有多个yes,而不同于之前的多分类只有一个yes。

这里思考一下:
一首歌:如果你有四个类别的音乐,分别为:古典音乐、乡村音乐、摇滚乐和爵士乐,那么这些类别之间是互斥的。这首歌属于哪个类别?这是一个什么问题?

一首歌:如果你有四个类别的音乐,分别为:人声音乐、舞曲、影视原声、流行歌曲,那么这些类别之间并不是互斥的。这首歌属于哪个类别?这是一个什么问题?

多标签的问题的损失函数是什么

这里需要先了解一下softmax 与 sigmoid函数:

这两个函数最重要的区别,我们观察一下:

区别还是很明显的。

综上,我们可以得出以下结论:

pytorch中的实现

PyTorch提供了两个类来计算二分类交叉熵(Binary Cross Entropy),分别是BCELoss() 和BCEWithLogitsLoss()

看一下源码,参考帮助,我们来玩一下:

 

  1. from torch import autograd
  2. input = autograd.Variable(torch.randn(3,3), requires_grad=True)
  3. print(input)

输出:

  1. tensor([[ 1.9072, 1.1079, 1.4906],
  2. [-0.6584, -0.0512, 0.7608],
  3. [-0.0614, 0.6583, 0.1095]], requires_grad=True)

因为Note that the targets t[i] should be numbers between 0 and 1.
所以需要先sigmoid:

  1. from torch import nn
  2. m = nn.Sigmoid()
  3. print(m(input))

输出:

  1. tensor([[0.8707, 0.7517, 0.8162],
  2. [0.3411, 0.4872, 0.6815],
  3. [0.4847, 0.6589, 0.5273]], grad_fn=<SigmoidBackward>)

假设你的target如下:

  1. target = torch.FloatTensor([[0, 1, 1], [1, 1, 1], [0, 0, 0]])
  2. print(target)

输出:

  1. tensor([[0., 1., 1.],
  2. [1., 1., 1.],
  3. [0., 0., 0.]])

我们先根据源码中公式,

自己计算一下:

  1. import math
  2. r11 = 0 * math.log(0.8707) + (1-0) * math.log((1 - 0.8707))
  3. r12 = 1 * math.log(0.7517) + (1-1) * math.log((1 - 0.7517))
  4. r13 = 1 * math.log(0.8162) + (1-1) * math.log((1 - 0.8162))
  5. r21 = 1 * math.log(0.3411) + (1-1) * math.log((1 - 0.3411))
  6. r22 = 1 * math.log(0.4872) + (1-1) * math.log((1 - 0.4872))
  7. r23 = 1 * math.log(0.6815) + (1-1) * math.log((1 - 0.6815))
  8. r31 = 0 * math.log(0.4847) + (1-0) * math.log((1 - 0.4847))
  9. r32 = 0 * math.log(0.6589) + (1-0) * math.log((1 - 0.6589))
  10. r33 = 0 * math.log(0.5273) + (1-0) * math.log((1 - 0.5273))
  11. r1 = -(r11 + r12 + r13) / 3
  12. #0.8447112733378236
  13. r2 = -(r21 + r22 + r23) / 3
  14. #0.7260397266631787
  15. r3 = -(r31 + r32 + r33) / 3
  16. #0.8292933181294807
  17. bceloss = (r1 + r2 + r3) / 3
  18. print(bceloss)

输出:

0.8000147727101611

核心解读
就是把每一个标签的预测值(sigmoid计算之后)交给cross_entropy函数来进行分类计算。比如样本1是一张图片(r1),r11代表某一个标签(有房子),r12代表某一个标签(有树), r13代表某一个标签(有小狗),最后r1就是样本1的预测值与真实值之间的loss。

我们再对比一下使用torch内置的loss函数:

  1. loss = nn.BCELoss()
  2. print(loss(m(input), target))

输出:

tensor(0.8000, grad_fn=<BinaryCrossEntropyBackward>)

和我们自己算的误差非常小,可以忽略。

我们可以把sigmoid和bce的过程放到一起,使用内建的BCEWithLogitsLoss函数:

  1. loss = nn.BCEWithLogitsLoss()
  2. print(loss(input, target))

输出:

tensor(0.8000, grad_fn=<BinaryCrossEntropyWithLogitsBackward>)

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/391953
推荐阅读
相关标签
  

闽ICP备14008679号