pytorch 实现二分类交叉熵逆样本频率权重

通常,由于类别不均衡,需要使用weighted cross entropy loss平衡。

def inverse_freq(label):
 """
 输入label [N,1,H,W],1是channel数目
 """
    den = label.sum() # 0
    _,_,h,w= label.shape
    num = h*w
    alpha = den/num # 0
    return torch.tensor([alpha, 1-alpha]).cuda()
# train
...
loss1 = F.cross_entropy(out1, label.squeeze(1).long(), weight=inverse_freq(label))

补充:Pytorch踩坑记之交叉熵(nn.CrossEntropy,nn.NLLLoss,nn.BCELoss的区别和使用)

在Pytorch中的交叉熵函数的血泪史要从nn.CrossEntropyLoss()这个损失函数开始讲起。

从表面意义上看,这个函数好像是普通的交叉熵函数,但是如果你看过一些Pytorch的资料,会告诉你这个函数其实是softmax()和交叉熵的结合体。

然而如果去官方看这个函数的定义你会发现是这样子的:

哇,竟然是nn.LogSoftmax()和nn.NLLLoss()的结合体,这俩都是什么玩意儿啊。再看看你会发现甚至还有一个损失叫nn.Softmax()以及一个叫nn.nn.BCELoss()。

我们来探究下这几个损失到底有何种关系。

nn.Softmax和nn.LogSoftmax

首先nn.Softmax()官网的定义是这样的:

嗯...就是我们认识的那个softmax。那nn.LogSoftmax()的定义也很直观了:

果不其然就是Softmax取了个log。可以写个代码测试一下:

import torch
import torch.nn as nn

a = torch.Tensor([1,2,3])
#定义Softmax
softmax = nn.Softmax()
sm_a = softmax=nn.Softmax()
print(sm)
#输出:tensor([0.0900, 0.2447, 0.6652])

#定义LogSoftmax
logsoftmax = nn.LogSoftmax()
lsm_a = logsoftmax(a)
print(lsm_a)
#输出tensor([-2.4076, -1.4076, -0.4076]),其中ln(0.0900)=-2.4076

nn.NLLLoss

上面说过nn.CrossEntropy()是nn.LogSoftmax()和nn.NLLLoss的结合,nn.NLLLoss官网给的定义是这样的:

The negative log likelihood loss. It is useful to train a classification problem with C classes

负对数似然损失 ,看起来好像有点晦涩难懂,写个代码测试一下:

import torch
import torch.nn

a = torch.Tensor([[1,2,3]])
nll = nn.NLLLoss()
target1 = torch.Tensor([0]).long()
target2 = torch.Tensor([1]).long()
target3 = torch.Tensor([2]).long()

#测试
n1 = nll(a,target1)
#输出:tensor(-1.)
n2 = nll(a,target2)
#输出:tensor(-2.)
n3 = nll(a,target3)
#输出:tensor(-3.)

看起来nn.NLLLoss做的事情是取出a中对应target位置的值并取负号,比如target1=0,就取a中index=0位置上的值再取负号为-1,那这样做有什么意义呢,要结合nn.CrossEntropy往下看。

nn.CrossEntropy

看下官网给的nn.CrossEntropy()的表达式:

看起来应该是softmax之后取了个对数,写个简单代码测试一下:

import torch
import torch.nn as nn

a = torch.Tensor([[1,2,3]])
target = torch.Tensor([2]).long()
logsoftmax = nn.LogSoftmax()
ce = nn.CrossEntropyLoss()
nll = nn.NLLLoss()

#测试CrossEntropyLoss
cel = ce(a,target)
print(cel)
#输出:tensor(0.4076)

#测试LogSoftmax+NLLLoss
lsm_a = logsoftmax(a)
nll_lsm_a = nll(lsm_a,target)
#输出tensor(0.4076)

看来直接用nn.CrossEntropy和nn.LogSoftmax+nn.NLLLoss是一样的结果。为什么这样呢,回想下交叉熵的表达式:

其中y是label,x是prediction的结果,所以其实交叉熵损失就是负的target对应位置的输出结果x再取-log。这个计算过程刚好就是先LogSoftmax()再NLLLoss()。

所以我认为nn.CrossEntropyLoss其实应该叫做softmaxloss更为合理一些,这样就不会误解了。

nn.BCELoss

你以为这就完了吗,其实并没有。还有一类损失叫做BCELoss,写全了的话就是Binary Cross Entropy Loss,就是交叉熵应用于二分类时候的特殊形式,一般都和sigmoid一起用,表达式就是二分类交叉熵:

直觉上和多酚类交叉熵的区别在于,不仅考虑了的样本,也考虑了的样本的损失。

总结

nn.LogSoftmax是在softmax的基础上取自然对数nn.NLLLoss是负的似然对数损失,但Pytorch的实现就是把对应target上的数取出来再加个负号,要在CrossEntropy中结合LogSoftmax来用BCELoss是二分类的交叉熵损失,Pytorch实现中和多分类有区别

Pytorch是个深坑,让我们一起扎根使用手册,结合实践踏平这些坑吧暴风哭泣。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • PyTorch的SoftMax交叉熵损失和梯度用法

    在PyTorch中可以方便的验证SoftMax交叉熵损失和对输入梯度的计算 关于softmax_cross_entropy求导的过程,可以参考HERE 示例: # -*- coding: utf-8 -*- import torch import torch.autograd as autograd from torch.autograd import Variable import torch.nn.functional as F import torch.nn as nn import nu

  • pytorch中交叉熵损失(nn.CrossEntropyLoss())的计算过程详解

    公式 首先需要了解CrossEntropyLoss的计算过程,交叉熵的函数是这样的: 其中,其中yi表示真实的分类结果.这里只给出公式,关于CrossEntropyLoss的其他详细细节请参照其他博文. 测试代码(一维) import torch import torch.nn as nn import math criterion = nn.CrossEntropyLoss() output = torch.randn(1, 5, requires_grad=True) label = tor

  • 在Pytorch中使用样本权重(sample_weight)的正确方法

    step: 1.将标签转换为one-hot形式. 2.将每一个one-hot标签中的1改为预设样本权重的值 即可在Pytorch中使用样本权重. eg: 对于单个样本:loss = - Q * log(P),如下: P = [0.1,0.2,0.4,0.3] Q = [0,0,1,0] loss = -Q * np.log(P) 增加样本权重则为loss = - Q * log(P) *sample_weight P = [0.1,0.2,0.4,0.3] Q = [0,0,sample_wei

  • pytorch 实现二分类交叉熵逆样本频率权重

    通常,由于类别不均衡,需要使用weighted cross entropy loss平衡. def inverse_freq(label): """ 输入label [N,1,H,W],1是channel数目 """ den = label.sum() # 0 _,_,h,w= label.shape num = h*w alpha = den/num # 0 return torch.tensor([alpha, 1-alpha]).cuda(

  • Python机器学习pytorch交叉熵损失函数的深刻理解

    目录 1.交叉熵损失函数的推导 2. 交叉熵损失函数的直观理解 3. 交叉熵损失函数的其它形式 4.总结 说起交叉熵损失函数「Cross Entropy Loss」,脑海中立马浮现出它的公式: 我们已经对这个交叉熵函数非常熟悉,大多数情况下都是直接拿来使用就好.但是它是怎么来的?为什么它能表征真实样本标签和预测概率之间的差值?上面的交叉熵函数是否有其它变种? 1.交叉熵损失函数的推导 我们知道,在二分类问题模型:例如逻辑回归「Logistic Regression」.神经网络「Neural Ne

  • Pytorch 实现focal_loss 多类别和二分类示例

    我就废话不多说了,直接上代码吧! import numpy as np import torch import torch.nn as nn import torch.nn.functional as F # 支持多分类和二分类 class FocalLoss(nn.Module): """ This is a implementation of Focal Loss with smooth label cross entropy supported which is pro

  • 解决pytorch 交叉熵损失输出为负数的问题

    网络训练中,loss曲线非常奇怪 交叉熵怎么会有负数. 经过排查,交叉熵不是有个负对数吗,当网络输出的概率是0-1时,正数.可当网络输出大于1的数,就有可能变成负数. 所以加上一行就行了 out1 = F.softmax(out1, dim=1) 补充知识:在pytorch框架下,训练model过程中,loss=nan问题时该怎么解决? 当我在UCF-101数据集训练alexnet时,epoch设为100,跑到三十多个epoch时,出现了loss=nan问题,当时是一脸懵逼,在查阅资料后,我通过

  • pytorch交叉熵损失函数的weight参数的使用

    首先 必须将权重也转为Tensor的cuda格式: 然后 将该class_weight作为交叉熵函数对应参数的输入值. class_weight = torch.FloatTensor([0.13859937, 0.5821059, 0.63871904, 2.30220396, 7.1588294, 0]).cuda() 补充:关于pytorch的CrossEntropyLoss的weight参数 首先这个weight参数比想象中的要考虑的多 你可以试试下面代码 import torch im

  • 使用TensorFlow实现二分类的方法示例

    使用TensorFlow构建一个神经网络来实现二分类,主要包括输入数据格式.隐藏层数的定义.损失函数的选择.优化函数的选择.输出层.下面通过numpy来随机生成一组数据,通过定义一种正负样本的区别,通过TensorFlow来构造一个神经网络来实现二分类. 一.神经网络结构 输入数据:定义输入一个二维数组(x1,x2),数据通过numpy来随机产生,将输出定义为0或1,如果x1+x2<1,则y为1,否则y为0. 隐藏层:定义两层隐藏层,隐藏层的参数为(2,3),两行三列的矩阵,输入数据通过隐藏层之

  • 浅谈keras中自定义二分类任务评价指标metrics的方法以及代码

    对于二分类任务,keras现有的评价指标只有binary_accuracy,即二分类准确率,但是评估模型的性能有时需要一些其他的评价指标,例如精确率,召回率,F1-score等等,因此需要使用keras提供的自定义评价函数功能构建出针对二分类任务的各类评价指标. keras提供的自定义评价函数功能需要以如下两个张量作为输入,并返回一个张量作为输出. y_true:数据集真实值组成的一阶张量. y_pred:数据集输出值组成的一阶张量. tf.round()可对张量四舍五入,因此tf.round(

  • python实现二分类的卡方分箱示例

    解决的问题: 1.实现了二分类的卡方分箱: 2.实现了最大分组限定停止条件,和最小阈值限定停止条件: 问题,还不太清楚,后续补充. 1.自由度k,如何来确定,卡方阈值的自由度为 分箱数-1,显著性水平可以取10%,5%或1% 算法扩展: 1.卡方分箱除了用阈值来做约束条件,还可以进一步的加入分箱数约束,以及最小箱占比,坏人率约束等. 2.需要实现更多分类的卡方分箱算法: 具体代码如下: # -*- coding: utf-8 -*- """ Created on Wed No

随机推荐