0
点赞
收藏
分享

微信扫一扫

pytorch中的CrossEntropyLoss()函数解析


总结


切记:在使用这个函数之前,不要对logits取softmax,否则无法训练收敛

1 ​​CrossEntropyLoss()​​函数解析

1.1 适用情况

单一标签的分类问题,即所谓的 ​​one-hot​​ 情形

1.2 数学基础

见文章

2 使用方法

先看一下这个函数的文档,里面有这么一个公式:

pytorch中的CrossEntropyLoss()函数解析_人工智能

那么这个公式是怎么来的呢?


  • 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∑n​yi​log(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(∑j​exp(x[j])exp(x[class])​)=−x[class]+log(j∑​exp(x[j]))

中的 e x p ( x [ c l a s s ] ) ∑ j e x p ( x [ j ] ) \frac{exp(x[class])}{\sum_j exp(x[j])} ∑jexp(x[j])exp(x[class]) 就是通过softmax求概率的过程。

3 避坑

3.1 计算的维度

代码中,你既可以按照行,也可以按照列。官方的说明文档中给出的代码示例就是从行维度计算的。

3.2 具体案例

import torch
import torch.nn as nn
# 如果在构造器中添加了 reduction = "none" 参数,则不再返回一个 scalar,也无法反向更新
loss = nn.CrossEntropyLoss()
# 需要注意,因为 input 的shape 是(3,5),就表明有5类,所以下面的类别只能是5,
# 否则会报 “IndexError: Target 5 is out of bounds.” 错
input = torch.randn(3,5, requires_grad=True)

# 取3个数;类型设置为torch.long;random_() 中的数的含义应该是指定一个到其范围内的数,这里就是生成大小为[0,5) 的整数
target = torch.empty(3, dtype=torch.long).random_(5)
print(input)
print(target)
output = loss(input, target)
print(output)

pytorch中的CrossEntropyLoss()函数解析_代码示例_02

这里面有一点儿不合理的地方就是: ​​randn()​​ 得到的是随机值,随机值的取值竟然也有到负值的,这对于普通的预测结果是不合理的。



举报

相关推荐

0 条评论