ToB企服应用市场:ToB评测及商务社交产业平台

标题: Pytorch常用的函数(十)交织熵丧失函数nn.BCELoss()、nn.BCELossWithLogits( [打印本页]

作者: 愛在花開的季節    时间: 2024-9-5 09:38
标题: Pytorch常用的函数(十)交织熵丧失函数nn.BCELoss()、nn.BCELossWithLogits(
Pytorch常用的函数(九)交织熵丧失函数nn.BCELoss()、nn.BCELossWithLogits()、nn.CrossEntropyLoss()详解

关于交织熵公式推导以及明白,可以参考:
信息量、熵、KL散度、交织熵概念明白
通过上面链接中的推导,二分类交织熵丧失函数:
                                         l                            o                            s                            s                            =                            −                                       1                               n                                                 ∑                                           i                                  =                                  1                                          n                                      (                                       y                               i                                      l                            o                            g                                                   y                                  i                                          ^                                      +                            (                            1                            −                                       y                               i                                      )                            l                            o                            g                            (                            1                            −                                                   y                                  i                                          ^                                      )                            )                                     n                            为批量样本                                  loss=-\frac{1}{n}\sum\limits_{i=1}^n(y_{i}log\hat{y_{i}}+(1-y_{i})log(1-\hat{y_i}))\\ n为批量样本                     loss=−n1​i=1∑n​(yi​logyi​^​+(1−yi​)log(1−yi​^​))n为批量样本
多分类的交织熵丧失函数:
                                         l                            o                            s                            s                            =                            −                                       1                               n                                                 ∑                                           i                                  =                                  1                                          n                                                 ∑                                           c                                  =                                  1                                          m                                                 y                                           i                                  c                                                 l                            o                            g                                                   y                                  ^                                                      i                                  c                                                          n                            为批量样本,                            m                            为分类数                                  loss=-\frac{1}{n}\sum\limits_{i=1}^n\sum\limits_{c=1}^my_{ic}log\hat{y}_{ic} \\ n为批量样本,m为分类数                     loss=−n1​i=1∑n​c=1∑m​yic​logy^​ic​n为批量样本,m为分类数
我们上面公式继续化简:
                                         l                            o                            s                            s                            =                            −                                       1                               n                                                 ∑                                           i                                  =                                  1                                          n                                                 ∑                                           c                                  =                                  1                                          m                                                 y                                           i                                  c                                                 l                            o                            g                                                   y                                  ^                                                      i                                  c                                                          我们现在只看一个样本:                                     l                            o                            s                            s                            (                            x                            ,                            c                            l                            a                            s                            s                            )                            =                            −                                       ∑                                           c                                  =                                  1                                          m                                                 y                                           x                                  c                                                 l                            o                            g                                                   y                                  ^                                                      x                                  c                                                          =                            −                            [                                       y                                           x                                  1                                                 l                            o                            g                            (                                                   y                                  ^                                                      x                                  1                                                 )                            +                                       y                                           x                                  2                                                 l                            o                            g                            (                                                   y                                  ^                                                      x                                  2                                                 )                            +                            .                            .                            .                            +                                       y                                           x                                  m                                                 l                            o                            g                            (                                                   y                                  ^                                                      x                                  m                                                 )                            ]                                     这个样本,只有                            c                            l                            a                            s                            s                            处                                       y                                           x                                  [                                  c                                  l                                  a                                  s                                  s                                  ]                                                 =                            1                            ,其他地方都为                            0                            ,因此                                     l                            o                            s                            s                            (                            x                            ,                            c                            l                            a                            s                            s                            )                            =                            −                            l                            o                            g                            (                                                   y                                  ^                                                      x                                  [                                  c                                  l                                  a                                  s                                  s                                  ]                                                 )                                     需要注意的是,在                            p                            y                            t                            o                            r                            c                            h                            中                            x                            需要先进行                            s                            o                            f                            t                            m                            a                            x                            ,                            因此                                     l                            o                            s                            s                            (                            x                            ,                            c                            l                            a                            s                            s                            )                            =                            −                            l                            o                            g                            (                                                   y                                  ^                                                      x                                  [                                  c                                  l                                  a                                  s                                  s                                  ]                                                 )                                     =                            −                            l                            o                            g                            (                                                   e                                               x                                     [                                     c                                     l                                     a                                     s                                     s                                     ]                                                                               ∑                                     j                                                           e                                                   x                                        [                                        j                                        ]                                                                          )                                     =                            −                            x                            [                            c                            l                            a                            s                            s                            ]                            +                            l                            o                            g                            (                                       ∑                               j                                                 e                                           x                                  [                                  j                                  ]                                                 )                                     我们举个例子,假设预测三个类别的概率为                            [                            0.1                            ,                            0.2                            ,                            0.3                            ]                            ,标签                            c                            l                            a                            s                            s                            =                            1                                     l                            o                            s                            s                            (                            x                            ,                            c                            l                            a                            s                            s                            )                            =                            −                            x                            [                            c                            l                            a                            s                            s                            ]                            +                            l                            o                            g                            (                                       ∑                               j                                                 e                                           x                                  [                                  j                                  ]                                                 )                                     =                            −                            0.2                            +                            l                            o                            g                            (                                       e                                           x                                  [                                  0                                  ]                                                 +                                       e                                           x                                  [                                  1                                  ]                                                 +                                       e                                           x                                  [                                  2                                  ]                                                 )                                     =                            −                            0.2                            +                            l                            o                            g                            (                                       e                               0.1                                      +                                       e                               0.2                                      +                                       e                               0.3                                      )                                  loss=-\frac{1}{n}\sum\limits_{i=1}^n\sum\limits_{c=1}^my_{ic}log\hat{y}_{ic} \\ 我们现在只看一个样本:\\ loss(x,class)=-\sum\limits_{c=1}^my_{xc}log\hat{y}_{xc}\\ =-[y_{x1}log(\hat{y}_{x1})+ y_{x2}log(\hat{y}_{x2}) + ... + y_{xm}log(\hat{y}_{xm})] \\ 这个样本,只有class处y_{x[class]}=1,其他地方都为0,因此\\ loss(x,class)=-log(\hat{y}_{x[class]}) \\ 需要注意的是,在pytorch中x需要先进行softmax,因此\\ loss(x,class)=-log(\hat{y}_{x[class]})\\ =-log(\frac{e^{x[class]}}{\sum\limits_{j}e^{x[j]}}) \\ =-x[class]+log(\sum\limits_{j}e^{x[j]}) \\ 我们举个例子,假设预测三个类别的概率为[0.1, 0.2, 0.3],标签class=1\\ loss(x,class)=-x[class]+log(\sum\limits_{j}e^{x[j]})\\ =-0.2+log(e^{x[0]}+e^{x[1]}+e^{x[2]})\\ =-0.2 + log(e^{0.1}+e^{0.2}+e^{0.3})                     loss=−n1​i=1∑n​c=1∑m​yic​logy^​ic​我们现在只看一个样本:loss(x,class)=−c=1∑m​yxc​logy^​xc​=−[yx1​log(y^​x1​)+yx2​log(y^​x2​)+...+yxm​log(y^​xm​)]这个样本,只有class处yx[class]​=1,其他地方都为0,因此loss(x,class)=−log(y^​x[class]​)需要注意的是,在pytorch中x需要先进行softmax,因此loss(x,class)=−log(y^​x[class]​)=−log(j∑​ex[j]ex[class]​)=−x[class]+log(j∑​ex[j])我们举个例子,假设预测三个类别的概率为[0.1,0.2,0.3],标签class=1loss(x,class)=−x[class]+log(j∑​ex[j])=−0.2+log(ex[0]+ex[1]+ex[2])=−0.2+log(e0.1+e0.2+e0.3)
现在得到了化简后的多分类交织熵丧失函数:
                                         对于单个样本                            x                            :                                     l                            o                            s                            s                            (                            x                            ,                            c                            l                            a                            s                            s                            )                            =                            −                            l                            o                            g                            (                                                   e                                               x                                     [                                     c                                     l                                     a                                     s                                     s                                     ]                                                                               ∑                                     j                                                           e                                                   x                                        [                                        j                                        ]                                                                          )                            =                            −                            x                            [                            c                            l                            a                            s                            s                            ]                            +                            l                            o                            g                            (                                       ∑                               j                                                 e                                           x                                  [                                  j                                  ]                                                 )                                  对于单个样本x:\\ loss(x,class)=-log(\frac{e^{x[class]}}{\sum\limits_{j}e^{x[j]}}) =-x[class]+log(\sum\limits_{j}e^{x[j]})                     对于单个样本x:loss(x,class)=−log(j∑​ex[j]ex[class]​)=−x[class]+log(j∑​ex[j])
(1)二分类丧失函数nn.BCELoss()、nn.BCELossWithLogits()

                                         l                            o                            s                            s                            =                            −                                       1                               n                                                 ∑                                           i                                  =                                  1                                          n                                      (                                       y                               i                                      l                            o                            g                                                   y                                  i                                          ^                                      +                            (                            1                            −                                       y                               i                                      )                            l                            o                            g                            (                            1                            −                                                   y                                  i                                          ^                                      )                            )                                     n                            为批量样本                                  loss=-\frac{1}{n}\sum\limits_{i=1}^n(y_{i}log\hat{y_{i}}+(1-y_{i})log(1-\hat{y_i}))\\ n为批量样本                     loss=−n1​i=1∑n​(yi​logyi​^​+(1−yi​)log(1−yi​^​))n为批量样本
Pytorch链接:BCEWithLogitsLoss
  1. torch.nn.BCEWithLogitsLoss(
  2.     weight=None,
  3.     size_average=None,
  4.     reduce=None,
  5.     reduction='mean', # 默认计算的是批量样本损失的平均值,还可以为'sum'或者'none'
  6.     pos_weight=None
  7. )
复制代码
  1. # 可以输入参数的shape可以为任意维度,只不过Target要和Input一致
  2. Input: (*), where *∗ means any number of dimensions.
  3. Target: (*), same shape as the input.
  4. # 如果reduction='mean',输出标量,
  5. # reduction='none',输出Output的shape和input一致
  6. Output: scalar. If reduction is 'none', then (*), same shape as input.
复制代码
Pytorch链接:BCELoss
  1. torch.nn.BCELoss(
  2.     weight=None,
  3.     size_average=None,
  4.     reduce=None,
  5.     reduction='mean' # 默认计算的是批量样本损失的平均值,还可以为'sum'或者'none'
  6. )
复制代码
  1. # 可以输入参数的shape可以为任意维度,只不过Target要和Input一致
  2. Input: (*), where *∗ means any number of dimensions.
  3. Target: (*), same shape as the input.
  4. # 如果reduction='mean',输出标量,
  5. # reduction='none',输出Output的shape和input一致
  6. Output: scalar. If reduction is 'none', then (*), same shape as input.
复制代码

  1. import numpy as np
  2. import torch
  3. from torch import nn
  4. import torch.nn.functional as F
  5. y = torch.tensor([1, 0, 1], dtype=torch.float)
  6. y_hat = torch.tensor([0.8, 0.2, 0.4], dtype=torch.float)
  7. bce_loss = nn.BCELoss()
  8. # nn.BCELoss()需要先对输入数据进行sigmod
  9. print("官方BCELoss = ", bce_loss(torch.sigmoid(y_hat), y))
  10. # nn.BCEWithLogitsLoss()不需要自己sigmod
  11. bcelogits_loss = nn.BCEWithLogitsLoss()
  12. print("官方BCEWithLogitsLoss = ", bcelogits_loss(y_hat, y))
  13. # 我们根据二分类交叉熵损失函数实现:
  14. def loss(y_hat, y):
  15.     y_hat = torch.sigmoid(y_hat)
  16.     l = -(y * np.log(y_hat) + (1 - y) * np.log(1 - y_hat))
  17.     l = sum(l) / len(l)
  18.     return l
  19. print('自己实现Loss = ', loss(y_hat, y))
复制代码
  1. # 可以看到结果值相同
  2. 官方BCELoss           =  tensor(0.5608)
  3. 官方BCEWithLogitsLoss =  tensor(0.5608)
  4. 自己实现Loss           =  tensor(0.5608)
复制代码
(2) nn.CrossEntropyLoss()

化简后的多分类交织熵丧失函数:
                                         对于单个样本                            x                            :                                     l                            o                            s                            s                            (                            x                            ,                            c                            l                            a                            s                            s                            )                            =                            −                            l                            o                            g                            (                                                   e                                               x                                     [                                     c                                     l                                     a                                     s                                     s                                     ]                                                                               ∑                                     j                                                           e                                                   x                                        [                                        j                                        ]                                                                          )                            =                            −                            x                            [                            c                            l                            a                            s                            s                            ]                            +                            l                            o                            g                            (                                       ∑                               j                                                 e                                           x                                  [                                  j                                  ]                                                 )                                  对于单个样本x:\\ loss(x,class)=-log(\frac{e^{x[class]}}{\sum\limits_{j}e^{x[j]}}) =-x[class]+log(\sum\limits_{j}e^{x[j]})                     对于单个样本x:loss(x,class)=−log(j∑​ex[j]ex[class]​)=−x[class]+log(j∑​ex[j])
Pytorch链接:CrossEntropyLoss
  1. torch.nn.CrossEntropyLoss(
  2.     weight=None,
  3.     size_average=None,
  4.     ignore_index=-100,
  5.     reduce=None,
  6.     reduction='mean',
  7.     label_smoothing=0.0 # 同样,默认计算的是批量样本损失的平均值,还可以为'sum'或者'none'
  8. )
复制代码
shape如下所示:



  1. cross_loss = nn.CrossEntropyLoss(reduction="none") # 设置为none,这里输入每个样本的loss值,不计算平均值
  2. target = torch.tensor([0, 1, 2])
  3. predict = torch.tensor([[0.9, 0.2, 0.8],
  4.                         [0.5, 0.2, 0.4],
  5.                         [0.4, 0.2, 0.9]]) # 未经过softmax
  6. print('官方实现CrossEntropyLoss: ', cross_loss(predict, target))
  7. # 自己实现方便理解版本的CrossEntropyLoss
  8. def cross_loss(predict, target, reduction=None):
  9.     all_loss = []
  10.     for index, value in enumerate(target):
  11.         # 利用多分类简化后的公式,对每一个样本求loss值
  12.         loss = -predict[index][value] + torch.log(sum(torch.exp(predict[index])))
  13.         all_loss.append(loss)
  14.     all_loss = torch.stack(all_loss)
  15.     if reduction == 'none':
  16.         return all_loss
  17.     else:
  18.         return torch.mean(all_loss)
  19. print('实现方便理解的CrossEntropyLoss: ', cross_loss(predict, target, reduction='none'))
  20. # 利用F.nll_loss实现的CrossEntropyLoss
  21. def cross_loss2(predict, target, reduction=None):
  22.     # Softmax的缺点:
  23.     # 1、如果有得分值特别大的情况,会出现上溢情况;
  24.     # 2、如果很小的负值很多,会出现下溢情况(超出精度范围会向下取0),分母为0,导致计算错误。
  25.     # 引入log_softmax可以解决上溢和下溢问题
  26.     logsoftmax = F.log_softmax(predict)
  27.     print('target = ', target)
  28.     print('logsoftmax:\n', logsoftmax)
  29.     # nll_loss不是将标签值转换为one-hot编码,而是根据target的值,索引到对应元素,然后取相反数。
  30.     loss = F.nll_loss(logsoftmax, target, reduction=reduction)
  31.     return loss
  32. print('F.nll_loss实现的CrossEntropyLoss: ', cross_loss2(predict, target, reduction='none'))
复制代码
  1. 官方实现CrossEntropyLoss:          tensor([0.8761, 1.2729, 0.7434])
  2. 实现方便理解的CrossEntropyLoss:     tensor([0.8761, 1.2729, 0.7434])
  3. target =  tensor([0, 1, 2])
  4. logsoftmax:
  5. tensor([[-0.8761, -1.5761, -0.9761],
  6.         [-0.9729, -1.2729, -1.0729],
  7.         [-1.2434, -1.4434, -0.7434]])
  8. F.nll_loss实现的CrossEntropyLoss:  tensor([0.8761, 1.2729, 0.7434])
复制代码
末了提出一个题目,二分类题目,应该选择sigmoid照旧softmax?
可以参考: 二分类题目,应该选择sigmoid照旧softmax?

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4