对于pytorch的内置交叉熵损失函数torch.nn.CrossEntropyLoss(),其中的具体运算公式如下图所示:
乍一看,看不懂,继续看,还是不理解?!别怕,具体带入数值进行流程解析!
输出(经过softmax概率化)为x=[0.2, 0.7, 0.1],假设是一个三分类问题三个输出,输入图像的标签为"1"--也就是公式中的”class“。
带入到损失函数进行计算:
接下来,我们到pycharm里验证以下:
import torch
from torch import nn
input = torch.tensor([[0.2, 0.7, 0.1]])
#注意输入要是二维的矩阵--1*3,而不是一维的向量,具体可以看最左边方括号,有几个方括号就是几维
target = torch.tensor([1]) #target也必须是tensor类型的,不然会报错
print(target)
print(input)
loss = nn.CrossEntropyLoss()
output = loss(input, target)
print(output)
输出结果:
tensor([1])
tensor([[0.2000, 0.7000, 0.1000]])
tensor(0.7679)
咦,可以发现,代码运行的结果与我们公式计算的结果不同?为啥?
其实,是因为log是自然对数,即--ln
真实的计算过程如下:
这样,就对了吧!!!
另外,我想说一下,众所周知,交叉熵损失函数是利用神经网络输出的概率化和输入图像的标签作为输入,那如果没有将神经网络的输出概率化,直接输入到交叉熵损失函数会怎么样??
try一下吧!
import torch
from torch import nn
input = torch.tensor([[1.2, 2.4, 3.6]])
#注意输入要是二维的矩阵--1*3,而不是一维的向量,具体可以看最左边方括号,有几个方括号就是几维
target = torch.tensor([1]) #target也必须是tensor类型的,不然会报错
print(target)
print(input)
loss = nn.CrossEntropyLoss()
output = loss(input, target)
print(output)
输出结果:
tensor([1])
tensor([[1.2000, 2.4000, 3.6000]])
tensor(1.5307)
可以看到,我的输入改成了大于1的数,概率总和为1,已经超过了!
但是pycharm并没有报错!
可能依然会有很高的正确率,因为nn.CrossEntropyLoss()函数已经将softmax包含进去了,是将softmax-log-NLLLoss合并到一块得到的结果,这就是加载pytorch编辑好的神经网络,而最后一层通常没有softmax函数原因。
让我们看看具体的运算:
nn.CrossEntropyLoss()=nn.LogSoftmax()+nn.NLLLoss()
就是先执行nn.LogSoftmax(),再执行nn.NLLLoss()的结果。
看代码:
import torch
from torch import nn
input1 = torch.tensor([[1.2, 2.4, 3.6]])
target = torch.tensor([1])
print(target)
print(input1)
loss1 = nn.LogSoftmax()
loss2 = nn.NLLLoss()
input2 = loss1(input1)
output = loss2(input2, target)
print(output)
输出结果:
tensor([1])
D:UserWarning: Implicit dimension choice for log_softmax has been deprecated. Change the call to include dim=X as an argument.
input2 = loss1(input1)
tensor([[1.2000, 2.4000, 3.6000]])
tensor(1.5307)
为啥会警告嘞???Let us see see!
log_softmax的隐式维度选择已经被弃用。更改调用包含dim = X作为参数】
log_softmax已经被抛弃了,不是亲儿子了!!需要自己加上维度dim即可!
代码更新:
import torch
from torch import nn
input1 = torch.tensor([[1.2, 2.4, 3.6]])
target = torch.tensor([1])
print(target)
print(input1)
loss1 = nn.LogSoftmax(dim=1) #dim=1好像是按行进行计算,注意是好像,别骂!!!
loss2 = nn.NLLLoss()
input2 = loss1(input1)
output = loss2(input2, target)
print(output)
结果如下:
tensor([1])
tensor([[1.2000, 2.4000, 3.6000]])
tensor(1.5307)
这样就没有警告了!!!终于结束了,码字真累啊!!!赶紧溜!!!Bye!!!