nn.CrossEntropyLoss()这个损失函数用于多分类问题虽然说的是交叉熵,但是和我理解的交叉熵不一样。nn.CrossEntropyLoss()是nn.logSoftmax()和nn.NLLLoss()的整合,可以直接使用它来替换网络中的这两个操作。下面我们来看一下计算过程。
首先输入是size是(minibatch,C)。这里的C是类别数。损失函数的计算如下:
l o s s ( x , c l a s s ) = − l o g ( e x p ( x [ c l a s s ] ) ∑ j e x p ( x [ j ] ) ) = − x [ c l a s s ] + l o g ( ∑ j e x p ( x [ j ] ) ) loss(x,class)=-log(\frac{exp(x[class])}{\sum_jexp(x[j])})=-x[class]+log(\sum_jexp(x[j])) loss(x,class)=−log(∑jexp(x[j])exp(x[class]))=−x[class]+log(j∑exp(x[j]))
损失函数中也有权重weight参数设置,若设置权重,则公式为: l o s s ( x , c l a s s ) = w e i g h t [ c l a s s ] ( − x [ c l a s s ] + l o g ( ∑ j e x p ( x [ j ] ) ) ) loss(x,class)=weight[class](-x[class]+log(\sum_jexp(x[j]))) loss(x,class)=weight[class](−x[class]+log(j∑exp(x[j])))
其他参数不具体说,和nn.BCELoss()设置差不多,默认情况下,对minibatch的loss求均值。
注意这里的标签值class,并不参与直接计算,而是作为一个索引,索引对象为实际类别
举个栗子,我们一共有三种类别,批量大小为1(为了好计算),那么输入size为(1,3),具体值为torch.Tensor([[-0.7715, -0.6205,-0.2562]])。标签值为target = torch.tensor([0]),这里标签值为0,表示属于第0类。loss计算如下:
import torch
import torch.nn as nn
import math
entroy=nn.CrossEntropyLoss()
input=torch.Tensor([[-0.7715, -0.6205,-0.2562]])
target = torch.tensor([0])
output = entroy(input, target)
print(output)
#根据公式计算
输出:
tensor(1.3447)
动手自己算:
−
x
[
0
]
+
l
o
g
(
e
x
p
(
x
[
0
]
)
+
e
x
p
(
x
[
1
]
)
+
e
x
p
(
x
[
2
]
)
)
-x[0]+log(exp(x[0])+exp(x[1])+exp(x[2]))
−x[0]+log(exp(x[0])+exp(x[1])+exp(x[2]))
=
0.7715
+
l
o
g
(
e
x
p
(
−
0.7715
)
+
e
x
p
(
−
0.6205
)
+
e
x
p
(
−
0.2562
)
=
1.3447266007601868
=0.7715+log(exp(-0.7715)+exp(-0.6205)+exp(-0.2562)=1.3447266007601868
=0.7715+log(exp(−0.7715)+exp(−0.6205)+exp(−0.2562)=1.3447266007601868
。
我们在看看是否等价nn.logSoftmax()和nn.NLLLoss()的整合:
m = nn.LogSoftmax()
loss = nn.NLLLoss()
input=m(input)
output = loss(input, target)
print('output:',output)
输出:
input: tensor([[-1.3447, -1.1937, -0.8294]])
output: tensor(1.3447)