- 文章来源:CSDN_LawsonAbs
- 持续更新~
- 切记:在使用这个函数之前,不要对logits取softmax,否则无法训练收敛
1
CrossEntropyLoss()
函数解析
1.1 适用情况
单一标签的分类问题,即所谓的 one-hot
情形
1.2 数学基础
见文章
2 使用方法先看一下这个函数的文档,里面有这么一个公式:
那么这个公式是怎么来的呢?
- x是一个向量
x
=
(
x
1
,
x
2
,
.
.
.
,
x
n
)
x=(x_1,x_2,...,x_n)
x=(x1,x2,...,xn),其中的每个值
x
i
x_i
xi都代表对每类的预测值,即每个标签的值,在作为参数传入
CrossEntropy
的之前,这个值是尚未经过softmax
函数处理 - class是一个值,表示这个样本本身的类别
由交叉熵的公式可知
L
o
s
s
=
−
∑
i
=
1
n
y
i
l
o
g
(
y
^
i
)
Loss = - \sum_{i=1}^{n}y_i log(\hat y_i)
Loss=−i=1∑nyilog(y^i)
但是由于是 one-hot型,所以上式就等于:
L
o
s
s
=
−
l
o
g
y
t
^
Loss = -log \hat{y_t}
Loss=−logyt^ 其中
y
t
^
\hat{y_t}
yt^表示真实标签概率不为0的那个标签对应的预测值。
所以就得出下面这个公式:
loss
(
x
,
c
l
a
s
s
)
=
−
log
(
exp
(
x
[
c
l
a
s
s
]
)
∑
j
exp
(
x
[
j
]
)
)
=
−
x
[
c
l
a
s
s
]
+
log
(
∑
j
exp
(
x
[
j
]
)
)
\text{loss}(x, class) = -\log\left(\frac{\exp(x[class])}{\sum_j \exp(x[j])}\right) = -x[class] + \log\left(\sum_j \exp(x[j])\right)
loss(x,class)=−log(∑jexp(x[j])exp(x[class]))=−x[class]+log(j∑exp(x[j]))
中的 − l o g ( e x p ( x [ c l a s s ] ) ∑ j e x p ( x [ j ] ) ) -log(\frac{exp(x[class])}{\sum_j exp(x[j])}) −log(∑jexp(x[j])exp(x[class])) 就是通过softmax求概率的过程。
3 避坑 3.1 计算的维度上面这个三个红框中的类别是下面的2【按照列的角度出发,而不是行的角度】
上面这句话的说法是存在问题的,代码中,你既可以按照行,也可以按照列。官方的说明文档中给出的代码示例就是从行维度计算的。
import torch
import torch.nn as nn
# 如果在构造器中添加了 reduction = "none" 参数,则不再返回一个 scalar,也无法反向更新
loss = nn.CrossEntropyLoss()
input = torch.randn(3,5, requires_grad=True)
# 取3个数
# 需要注意,因为 input 的shape 是(3,5),就表明只有5类,所以下面的类别只能是5,否则会报 “IndexError: Target 5 is out of bounds.” 错
# random_() 中的数的含义应该是指定一个到其范围内的数,这里就是生成大小为[0,5) 的整数
target = torch.empty(3, dtype=torch.long).random_(5)
print(input)
print(target)
output = loss(input, target)
print(output.size())
output.backward()
print(output)