Pytorch中的分类损失函数比较NLLLoss与CrossEntropyLoss

本文介绍了二分类及多分类任务中的损失函数计算方法,包括二分类交叉熵损失及多分类交叉熵损失,并通过实例详细解释了PyTorch中损失函数的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考来源,仅作为学习笔记


二分类

对于一个二分类问题,比如我们有一个样本,有两个不同的模型对他进行分类,那么它们的输出都应该是一个二维向量,比如:

模型一的输出为:pred_y1=[0.8,0.2]
模型二的输出为:pred_y2=[0.6,0.4]

需要注意的是,这里的数值已经经过了sigmoid激活函数,所以0.8+0.2=1,比如样本的真实标签是:true_y=[1,0]

现在我们来求这两个模型对于这一个类别的分类损失,怎么求?先给出二分类损失函数,表达式如下:
L = − y l o g ( y ′ ) + ( 1 − y ) l o g ( 1 − y ′ ) L = -ylog(y')+(1-y)log(1-y') L=ylog(y)+(1y)log(1y)
这里的y表示的是真实地标签,y’表示模型的输出标签,我们带入进去计算得到:

cost1 = -[1log0.8+(1-1)log0.2] = 0.22314
cost2 = -[1log0.6+(1-1)log0.4] = 0.51083

可以看出,第一个模型的损失更小,即模型更好,而且直观来看,第一个模型觉得正确的概率是0.8,自然比0.6要好。


多分类

交叉熵是一个信息论中的概念,它原来是用来估算平均编码长度的。给定两个概率分布p和q,通过q来表示p的交叉熵为上式,交叉熵刻画的是两个概率分布之间的距离,或可以说它刻画的是通过概率分布q来表达概率分布p的困难程度,p代表正确答案,q代表的是预测值,交叉熵越小,两个概率的分布约接近。
H ( p , q ) = − ∑ x ( p ( x ) ∗ l o g ( q ( x ) ) ) H(p,q) = -\sum_x(p(x) * log(q(x))) H(p,q)=x(p(x)log(q(x)))


过程总结

不管是二分类,还是多分类问题,其实在计算损失函数的过程都经历了三个步骤:

(1) 激活函数。通过激活函数sigmoid或者是softmax将输出值缩放到[0,1]之间,

(2) 求对数。计算缩放之后的向量的对数值,即所谓的logy的值,求对数之后的值在[-infinite,0]之间

(3) 累加求和。根据损失函数的定义,将标签和输出值逐元素相乘再求和,最后再添加一个负号求相反数,得到一个正数损失。


Pytorch中损失函数的实现

求多分类交叉熵损失有三种途径可以实现,分别是:

(1) 三步实现:softmax+log+nll_loss
(2) 两步实现:log_softmax+nll_loss
(3) 一步实现:crossEntropyLoss

代码实现

import numpy as np
import torch
import torch.nn.functional as F

# 比如这是一个模型的输出,本案例为一个三类别的分类,共有四组样本,如下:
pred_y = np.array([[0.30722019, -0.8358033, -1.24752918],
                   [0.72186664, 0.58657704, -0.25026393],
                   [0.16449865, -0.44255082, 0.68046693],
                   [-0.52082402, 1.71407838, -1.36618063]])
pred_y = torch.from_numpy(pred_y)

# 真实的标签如下所示
true_y = np.array([[1, 0, 0],
                   [0, 1, 0],
                   [0, 1, 0],
                   [0, 0, 1]])
true_y = torch.from_numpy(true_y)
target = np.argmax(true_y, axis=1)  # (4,) #其实就是获得每一给类别的整数值,这个和tensorflow里面不一样哦 内部会自动转换为one-hot形式
target = torch.LongTensor(target)  # (4,)

print(target)  # tensor([0,1,1,2])
print("-----------------------------------------------------------")


'''
三步实现:softmax + log + nll_loss如下:
'''
# 第一步:使用激活函数softmax进行缩放
pred_y = F.softmax(pred_y, dim=1)
print(pred_y)
print('-----------------------------------------------------------')

# 第二步:对每一个缩放之后的值求对数log
pred_y = torch.log(pred_y)
print(pred_y)
print('-----------------------------------------------------------')

# 第三步:求交叉熵损失
loss = F.nll_loss(pred_y, target)
print(loss)  # 最终的损失为:tensor(1.5929, dtype=torch.float64)


'''
两步实现:log_softmax+nll_loss
'''


# 第一步:直接使用log_softmax,相当于softmax+log
pred_y=F.log_softmax(pred_y,dim=1)
print(pred_y)
print('-----------------------------------------------------------')

# 第二步:求交叉熵损失
loss=F.nll_loss(pred_y,target)
print(loss) # tensor(1.5929, dtype=torch.float64)


'''
一步实现
'''
loss=F.cross_entropy(pred_y,target)
print(loss) # tensor(1.5929, dtype=torch.float64)

注意

在求交叉熵损失的时候,需要注意的是,不管是使用 nll_loss函数,还是直接使用cross_entropy函数,都需要传递一个target参数,这个参数表示的是真实的类别,对应于一个列表的形式而不是一个二维数组,这个和tensorflow是不一样的哦!(Pytorch分类损失函数内部会自动把列表形式(一维数组形式)的整数索引转换为one-hot表示)

nn.NLLLoss()和nn.CrossEntropyLoss()是用于多分类任务的损失函数,在PyTorch中它们实际上是相同的。唯一的区别在于它们接收的输入不同: - nn.NLLLoss()的输入是一个对数概率向量和一个目标标签,它不会为我们计算对数概率。适合网络的最后一层是log_softmax损失函数的情况。 - nn.CrossEntropyLoss()的输入是一个预测值和一个目标标签,它会为我们自动计算预测值的对数概率,即先做softmax,再做log处理。在实际使用中,两者可以互换使用,效果是一样的。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [paddle中nll_loss()CrossEntropyLoss()损失函数区别](https://blog.csdn.net/weixin_43848436/article/details/115448659)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Pytorch损失函数 NLLLOSSCROSSENTROPYLOSS 的区别](https://blog.csdn.net/cnhwl/article/details/125518586)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jeremy_lf

你的鼓励是我的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值