BCELoss

二分类交叉熵损失

单标签二分类

一个输入样本对应于一个分类输出,例如,情感分类中的正向和负向

对于包含 N N N个样本的batch数据, l o s s loss loss计算如下:

l o s s = 1 N ∑ n = 1 N l n loss=\frac{1}{N} \sum_{n=1}^{N} l_{n} loss=N1​∑n=1N​ln​

其中, l n = − w [ y n ⋅ log ⁡ x n + ( 1 − y n ) ⋅ log ⁡ ( 1 − x n ) ] l_{n}=-w\left[y_{n} \cdot \log x_{n}+\left(1-y_{n}\right) \cdot \log \left(1-x_{n}\right)\right] ln​=−w[yn​⋅logxn​+(1−yn​)⋅log(1−xn​)] 为第 n n n个样本对应的 l o s s loss loss。

x n x_{n} xn​代表第n个样本的对应的模型输出,经过sigmoid激活函数处理

y n y_{n} yn​代表第n个样本的对应的类别

w w w是超参数,对于单标签二分类,设不设置 w w w, 没有影响

一般情况下, y y y中各个元素的取值为0或1,代表真实类别

class BCELoss(_WeightedLoss):__constants__ = ['reduction', 'weight']def __init__(self, weight=None, size_average=None, reduce=None, reduction='mean'):super(BCELoss, self).__init__(weight, size_average, reduce, reduction)def forward(self, input, target):return F.binary_cross_entropy(input, target, weight=self.weight, reduction=self.reduction)

pytorch中通过torch.nn.BCELoss类实现,也可以直接调用F.binary_cross_entropy 函数,代码中的weight即是 w w w。size_averagereduce已经弃用。reduction有三种取值mean, sum, none,对应不同的返回 ℓ ( x , y ) \ell(x, y) ℓ(x,y). 默认为mean,对应于上述 l o s s loss loss的计算。

L = { l 1 , … , l N } L=\left\{l_{1}, \ldots, l_{N}\right\} L={l1​,…,lN​}

ℓ ( x , y ) = { L ⁡ , if reduction  = ’none’  mean ⁡ ( L ) , if reduction  = ’mean’  sum ⁡ ( L ) , if reduction  = ’sum’  \ell(x, y)=\left\{\begin{array}{ll}\operatorname L, & \text { if reduction }=\text { 'none' } \\ \operatorname{mean}(L), & \text { if reduction }=\text { 'mean' } \\ \operatorname{sum}(L), & \text { if reduction }=\text { 'sum' }\end{array} \right. ℓ(x,y)=⎩⎨⎧​L,mean(L),sum(L),​ if reduction = ’none’  if reduction = ’mean’  if reduction = ’sum’ ​

验证函数:证明loss函数的输出和我们理解的输出一致

def validate_loss(output, target, weight=None, pos_weight=None):# 处理正负样本不均衡问题if pos_weight is None:label_size = output.size()[1]pos_weight = torch.ones(label_size)# 处理多标签不平衡问题if weight is None:label_size = output.size()[1]weight = torch.ones(label_size)val = 0for li_x, li_y in zip(output, target):for i, xy in enumerate(zip(li_x, li_y)):x, y = xyloss_val = pos_weight[i] * y * math.log(x, math.e) + (1 - y) * math.log(1 - x, math.e)val += weight[i] * loss_valreturn -val / (output.size()[0] * output.size(1))

使用torch.nn.BCELoss类实现loss计算

import torch
import torch.nn.functional as F
import torch.nn as nn
import math# 单标签二分类
m = nn.Sigmoid()
weight = torch.tensor([0.8])
loss_fct = nn.BCELoss(reduction="mean", weight=weight)
input_src = torch.Tensor([[0.8], [0.9], [0.3]])
target = torch.Tensor([[1], [1], [0]])
print(input_src.size())
print(target.size())
output = m(input_src)
loss = loss_fct(output, target)
print(loss.item())# 验证计算
validate = validate_loss(output, target, weight)
print(validate.item())
# 输出
torch.Size([3, 1])
torch.Size([3, 1])
0.4177626073360443
0.4177626371383667

使用binary_cross_entropy函数实现loss计算

# 单标签二分类
weight = torch.tensor([0.8])
input_src = torch.Tensor([[0.8], [0.9], [0.3]])
target = torch.Tensor([[1], [1], [0]])
print(input_src.size())
print(target.size())
output = torch.sigmoid(input_src)
loss = F.binary_cross_entropy(output, target, weight=weight, reduction='mean')
print(loss.item())# 验证计算
validate = validate_loss(output, target, weight)
print(validate.item())
torch.Size([3, 1])
torch.Size([3, 1])
0.4177626073360443
0.4177626371383667

多标签二分类

什么是多标签分类?

比如说给一篇文章分配话题,它既可以是科技类又可以是教育类,科技和教育就是这篇文章的两个标签。又比如判断一幅图中包含什么,它可能既包含房子又包含马路。房子和马路就是这幅图对应的两个标签。将每一种标签,看作是二分类。一个输入样本对应于多个标签,每个标签对应一个二分类(是或不是)。

l o s s loss loss 的计算方式和上面一致,对于包含 N N N个样本的batch数据 ,每个样本可能有 M M M个标签, l o s s loss loss计算如下:
l o s s = 1 N ∑ n = 1 N l n loss=\frac{1}{N} \sum_{n=1}^{N} l_{n} loss=N1​n=1∑N​ln​

其中, l n = 1 M ∑ i = 1 M l n i l_{n}= \frac{1}{M} \sum_{i=1}^{M}l_{n}^{i} ln​=M1​∑i=1M​lni​ 为第 n n n个样本对应的 l o s s loss loss

l n i = − w i [ y n i ⋅ log ⁡ x n i + ( 1 − y n i ) ⋅ log ⁡ ( 1 − x n i ) ] l_{n}^{i}= - w_{i}\left[y_{n}^{i} \cdot \log x_{n}^{i}+\left(1-y_{n}^{i}\right) \cdot \log \left(1-x_{n}^{i}\right)\right] lni​=−wi​[yni​⋅logxni​+(1−yni​)⋅log(1−xni​)]

x n i x_{n}^i xni​代表第n个样本的第i个标签对应的模型输出,经过sigmoid激活函数处理

y n i y_{n}^i yni​代表第n个样本的的第i个标签对应的类别

w i w_{i} wi​是超参数, 用于处理标签间的样本不均衡问题。对于一批训练集,若其中某个标签的出现次数较少,计算 l o s s loss loss时应该给予更高的权重。

L = ( l 1 1 , l 1 2 , . . . , l 1 M l 2 1 , l 2 2 , . . . , l 2 M ⋮ l N 1 , l N 2 , . . . , l N M ) L=\left(\begin{array}{c}l_{1}^{1},l_{1}^{2},...,l_{1}^{M} \\ l_{2}^{1},l_{2}^{2},...,l_{2}^{M} \\ \vdots \\ l_{N}^{1},l_{N}^{2},...,l_{N}^{M} \end{array}\right) L=⎝⎜⎜⎜⎛​l11​,l12​,...,l1M​l21​,l22​,...,l2M​⋮lN1​,lN2​,...,lNM​​⎠⎟⎟⎟⎞​

ℓ ( x , y ) = { L ⁡ , if reduction  = ’none’  mean ⁡ ( L ) , if reduction  = ’mean’  sum ⁡ ( L ) , if reduction  = ’sum’  \ell(x, y)=\left\{\begin{array}{ll}\operatorname L, & \text { if reduction }=\text { 'none' } \\ \operatorname{mean}(L), & \text { if reduction }=\text { 'mean' } \\ \operatorname{sum}(L), & \text { if reduction }=\text { 'sum' }\end{array} \right. ℓ(x,y)=⎩⎨⎧​L,mean(L),sum(L),​ if reduction = ’none’  if reduction = ’mean’  if reduction = ’sum’ ​

多标签二分类例子:

import torch
import torch.nn.functional as F
import torch.nn as nn
import math
weight = torch.Tensor([0.8, 1, 0.8])
input = torch.Tensor([[0.8, 0.9, 0.3], [0.8, 0.9, 0.3], [0.8, 0.9, 0.3], [0.8, 0.9, 0.3]])
target = torch.Tensor([[1, 1, 0], [1, 1, 0], [1, 1, 0], [1, 1, 0]])
print(input.size())
print(target.size())
output = torch.sigmoid(input)
loss = F.binary_cross_entropy(output, target, reduction='none', weight=weight)
print(loss)  # noneloss = F.binary_cross_entropy(output, target, reduction='mean', weight=weight)
print(loss.item())
# 验证计算
validate = validate_loss(output, target, weight)
print(validate.item())
torch.Size([4, 3])
torch.Size([4, 3])
tensor([[0.2969, 0.3412, 0.6835],[0.2969, 0.3412, 0.6835],[0.2969, 0.3412, 0.6835],[0.2969, 0.3412, 0.6835]])
0.4405061900615692
0.4405062198638916

BCEWithLogitsLoss

将Sigmoid层和BCELoss类合并在一个类中.

BCEWithLogitsLoss = Sigmoid + BCELoss 例子:

m = nn.Sigmoid()
weight = torch.tensor([0.8])
loss_fct = nn.BCELoss(reduction="mean", weight=weight)
loss_fct_logit = nn.BCEWithLogitsLoss(reduction="mean", weight=weight)
input_src = torch.Tensor([0.8, 0.9, 0.3])
target = torch.Tensor([1, 1, 0])
print(input_src)
print(target)
output = m(input_src)
loss = loss_fct(output, target)
loss_logit = loss_fct_logit(input_src, target)
print(loss.item())
print(loss_logit.item())
# 结果一致
tensor([0.8000, 0.9000, 0.3000])
tensor([1., 1., 0.])
0.4177626371383667
0.4177626371383667

值得注意的是,BCEWithLogitsLoss类比BCELoss类,还多了一个pos_weight参数,pos_weight用于处理每种标签中正负样本不均衡问题,作为正类的权重。具体的,若正类样本较多,设置pos_weight<1,若负类样本较多,设置pos_weight>1

input = torch.Tensor([[0.8, 0.9, 0.3], [0.8, 0.9, 0.3], [0.8, 0.9, 0.3], [0.8, 0.9, 0.3]])
target = torch.Tensor([[1, 1, 0], [1, 1, 0], [1, 1, 0], [1, 1, 0]])
print(input.size())
print(target.size())
output = torch.sigmoid(input)
weight = torch.tensor([0.8, 1, 0.8])
loss = F.binary_cross_entropy_with_logits(input, target, reduction='mean', pos_weight=weight)
print(loss.item())
# 验证计算
validate = validate_loss(output, target, pos_weight=weight)
print(validate.item())
torch.Size([4, 3])
torch.Size([4, 3])
0.49746325612068176
0.49746325612068176

loss函数之BCELoss, BCEWithLogitsLoss相关推荐

  1. 一起学习ML和DL中常用的几种loss函数

    摘要:本篇内容和大家一起学习下机器学习和深度学习中常用到的几种loss函数. 本文分享自华为云社区<[MindSpore易点通]网络实战之交叉熵类Loss函数>,作者:Skytier . ...

  2. 《深度学习笔记》——loss函数的学习笔记

    1 loss的作用 在南溪看来,loss函数是对目标target和预测prediction之间的一种距离度量的公式: 2 loss函数的设计原则 此设计原则参考了距离的定义,(注意:距离跟范数是两个概 ...

  3. 【Dual-Path-RNN-Pytorch源码分析】loss函数:SI-SNR

    DPRNN使用的loss函数是 SI-SNR SI-SNR 是scale-invariant source-to-noise ratio的缩写,中文翻译为尺度不变的信噪比,意思是不受信号变化影响的信噪 ...

  4. tensorflow学习(4.loss函数以及正则化的使用 )

    本文还是以MNIST的CNN分析为例 loss函数一般有MSE均方差函数.交叉熵损失函数,说明见 https://blog.csdn.net/John_xyz/article/details/6121 ...

  5. 多分类loss函数本质理解

    一.面对一个多分类问题,如何设计合理的损失函数呢? 1.损失函数的本质在数学上称为目标函数:这个目标函数的目标值符合最完美的需求:损失函数的目标值肯定是0,完美分类的损失必然为0 : 2.损失函数分为 ...

  6. 深度学习基础(三)loss函数

    loss函数,即损失函数,是决定网络学习质量的关键.若网络结构不变的前提下,损失函数选择不当会导致模型精度差等后果.若有错误,敬请指正,Thank you! 目录 一.loss函数定义 二.常见的lo ...

  7. Keras自定义Loss函数

    Keras作为一个深度学习库,非常适合新手.在做神经网络时,它自带了许多常用的目标函数,优化方法等等,基本能满足新手学习时的一些需求.具体包含目标函数和优化方法.但它也支持用户自定义目标函数,下边介绍 ...

  8. 商汤使用AutoML设计Loss函数,全面超越人工设计

    点击我爱计算机视觉标星,更快获取CVML新技术 深度学习领域,神经架构搜索得到的算法如雨后春笋般出现. 今天一篇arXiv论文<AM-LFS: AutoML for Loss Function ...

  9. 深度学习中的损失函数总结以及Center Loss函数笔记

    北京 上海巡回站 | NVIDIA DLI深度学习培训 2018年1月26/1月12日 NVIDIA 深度学习学院 带你快速进入火热的DL领域 阅读全文                        ...

最新文章

  1. 完成动态根据类别动态填充区域颜色
  2. C++编译器与链接器工作原理
  3. springboot-mybatis-多数据源
  4. 《JQuery 能干点啥~》第四讲 html() 与 text()的赋值比较
  5. python标准库——time模块
  6. Java SE Java EE和Java ME的区别
  7. CRNN——文本识别算法
  8. SIM800(GPRS)拨号上网失败未能连接服务器
  9. IDEA开发工具当前窗口导入多个项目
  10. 科学表明世界上最令人感觉舒服的10种颜色(色码及RGB)
  11. github 使用笔记之高级搜索、项目跳转到在线 IDE -- 网页版 VS code
  12. REST Assured 系列汇总
  13. 如何用html制作彩虹,javascript – 如何使用HTML5画布生成彩虹圈?
  14. 用java敲出三角_手敲Java:打印菱形!
  15. SpringMvc思维导图
  16. 服务注册与发现-全搞懂
  17. HTML5实现大文件上传
  18. 男朋友在武汉当程序员,月薪到手15k左右
  19. AndroidStudio制作欢迎界面与应用图标,使用Android Studio 3.0.1作为开发工具
  20. 网站导航:如何在线生成自定义的二维码?(要美观不要俗气)

热门文章

  1. Microsoft Access database engine 2010 (Chinese (Simplif... 您不能安装64位版本的Microsoft Access 2010 数据库引擎
  2. 如何修改Linux的远程端口
  3. 港科夜闻丨香港科大AEM:碳表面特性对锂沉积行为的影响
  4. 女子取超长名字 由007片子14个女主角名字组成
  5. 同一纬度,为什么大兴安岭是森林,呼伦贝尔是草原?
  6. ubuntu20.04安装pip2
  7. PostgreSQL实现oracle中rowid
  8. MATLAB函数参数的传递
  9. strerror()
  10. 万卷书 - 向阳而生 [The Optimistic Child]