• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    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是个深坑,让我们一起扎根使用手册,结合实践踏平这些坑吧暴风哭泣

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

    您可能感兴趣的文章:
    • 在Pytorch中使用样本权重(sample_weight)的正确方法
    • pytorch中交叉熵损失(nn.CrossEntropyLoss())的计算过程详解
    • PyTorch的SoftMax交叉熵损失和梯度用法
    上一篇:pytorch交叉熵损失函数的weight参数的使用
    下一篇:Python Pycharm虚拟下百度飞浆PaddleX安装报错问题及处理方法(亲测100%有效)
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

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