Pytorch中torch.nn的损失函数

目录

前言

一、torch.nn.BCELoss(weight=None, size_average=True)

二、nn.BCEWithLogitsLoss(weight=None, size_average=True)

三、torch.nn.MultiLabelSoftMarginLoss(weight=None, size_average=True)

四、总结


前言

最近使用Pytorch做多标签分类任务,遇到了一些损失函数的问题,因为经常会忘记(好记性不如烂笔头囧rz),都是现学现用,所以自己写了一些代码探究一下,并在此记录,如果以后还遇到其他损失函数,继续在此补充。

如果有兴趣,我建议大家阅读Pytorch的官方中文文档的loss function部分,讲得比较清晰。

注:官方文档中特别强调了计算出来的结果默认已经对mini-batch取了平均

一、torch.nn.BCELoss(weight=None, size_average=True)

注:以下公式都是针对一个element(即mini-batch=1)的情形,如果mini-batch=m,最后的输出结果默认会对m个loss取平均的。

(关于weight和size_average两个参数我就不介绍了,介绍起来显得太啰嗦,只需要注意如果使用weight参数,那么weight的shape需要和类别数保持一致)

\small loss(y,target)=-\frac{1}{C}\sum_i(target[i] *log(y[i])+(1-target[i]) *log(1-y[i]))

这个地方需要强调的两点:

1、此处的i是指第i个类别,C表示总共有C个类别。

2、 0<=y[i]<=1(官方写的0<=target[i]<=1应该是写错了!)

下面是我实现的代码:

# 自己写的BCELoss函数
def BCE(y, target):
    loss = -(target*torch.log(y) + (1-target)*torch.log(1-y))
    # 官方文档中特别强调了:计算出来的结果默认对mini-batch取平均
    return loss.mean()

if __name__ == '__main__':
    # mini-batch = 2 , data shape is [2, 4] 
    y = torch.FloatTensor([[0.5, 0.9, 0.1, 0.3],
                          [0.1, 0.2, 0.3, 0.9]])
    target = torch.FloatTensor([[0, 1, 0, 0],
                                [0, 0, 1, 1]])
    # 官方的BCELoss()
    criterion = nn.BCELoss()
    loss = criterion(y, target)
    # 自己的BCELoss()
    loss2 = BCE(y, target)
    print("官方实现的BCELoss:", loss)
    print("自己实现的BCELoss:", loss2)


可以看到输出结果和官方是一样的
输出结果:
官方实现的BCELoss: tensor(0.3623)
自己实现的BCELoss: tensor(0.3623)

二、nn.BCEWithLogitsLoss(weight=None, size_average=True)

官方文档中没有看到这个函数,不过还是讲一下。

\small loss(y,target)=-\frac{1}{C}\sum_itarget[i] *log(\sigma (y[i]))+(1-target[i]) *log(\sigma (1-y[i]))

就是相当于先使用\small \sigma (x) = \frac{1}{1+e^{-x}}函数处理y,然后再使用BCELoss()函数进行处理。

以下是我实现的代码:

# sigmoid函数
def Sigmoid(x):
    return 1 / (1 + torch.exp(-x))

# 自己写的BCELoss函数
def BCE(y, target):
    loss = -(target*torch.log(y) + (1-target)*torch.log(1-y))
    # 官方文档中特别强调了:计算出来的结果已经对mini-batch取了平均
    return loss.mean()

# 自己写的BCEWithLogitsLoss函数
def BCELogit(y, target):
    # 首先使用sigmoid函数处理y
    y = Sigmoid(y)
    # 然后再使用BCELoss()
    loss = BCE(y, target)
    return loss

f __name__ == '__main__':
    # mini-batch = 2 , data shape is [2, 4]
    y = torch.FloatTensor([[0.5, 0.9, 0.1, 0.3],
                          [0.1, 0.2, 0.3, 0.9]])
    # 这是一个多标签分类,可以看到每行中可以有多个1
    target = torch.FloatTensor([[0, 1, 0, 1],
                                [0, 0, 1, 1]])

    criterion = nn.BCEWithLogitsLoss()
    loss = criterion(y, target)
    loss2 = BCELogit(y, target)
    print("官方实现的BCEWithLogitsLoss:", loss)
    print("自己实现的BCEWithLogitsLoss:", loss2)

可以看到输出结果和官方是一样的
输出结果:
官方实现的BCEWithLogitsLoss: tensor(0.6315)
自己实现的BCEWithLogitsLoss: tensor(0.6315)

注:因为对y使用了sigmoid函数,所以0<=y[i]<=1这个条件就不需要了

个人认为,BCEWithLogitsLoss就是比BCELoss多了一个Sigmoid函数处理。

三、torch.nn.MultiLabelSoftMarginLoss(weight=None, size_average=True)

\small loss(y, target) = - \frac{1}{C} * \sum_i target[i] * \log((1 + \exp(-y[i]))^{-1}) + (1-target[i]) * \log\left(\frac{\exp(-y[i])}{(1 + \exp(-y[i]))}\right)

这不就是和BCEWithLogitsLoss的公式一模一样咩,无非就是把Sigmoid函数展开了(小朋友你是否有很多问号???)

于是我写代码验证了一下

if __name__ == '__main__':
    # mini-batch = 2 , data shape is [2, 4]
    y = torch.FloatTensor([[0.5, 0.9, 0.1, 0.3],
                          [0.1, 0.2, 0.3, 0.9]])

    # 这是一个多标签分类,可以看到一行中可以有多个1
    target = torch.FloatTensor([[0, 1, 0, 1],
                                [0, 0, 1, 1]])


    criterion = nn.BCEWithLogitsLoss()
    criterion2 = nn.MultiLabelSoftMarginLoss()
    loss = criterion(y, target)
    loss2 = criterion2(y, target)
    print("官方实现的BCEWithLogitsLoss:", loss)
    print("官方实现的MultiLabelSoftMarginLoss:", loss2)


可以看到官方实现的BCEWithLogitsLoss和MultiLabelSoftMarginLoss输出是一样的
输出结果:
官方实现的BCEWithLogitsLoss: tensor(0.6315)
官方实现的MultiLabelSoftMarginLoss: tensor(0.6315)

四、总结

总结一下:

1、BCELoss加上一个Sigmoid函数操作就得到BCEWithLogitsLoss。

2、MultiLabelSoftMarginLoss和BCEWithLogitsLoss从公式上来看是一样的。

我也是最近才看了一下nn.torch的损失函数的内容,如果我写得有错误,还请评论区拍砖、斧正!

参考:https://blog.csdn.net/qq_39507748/article/details/105356845

           Pytorch的官方中文文档

 

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值