CrossEntropyLoss(交叉熵损失函数)和LabelSmoothing(标签平滑)推导和代码

CrossEntropyLoss

公式

J l o s s = − ∑ i = 1 N ∑ k = 1 K y i k ∗ l o g ( h θ ( x i ) k ) J_{loss} = -\sum_{i = 1}^{N} \sum_{k = 1}^{K} y_{ik}*log(h_{\theta}(x_{i})_{k}) Jloss=i=1Nk=1Kyiklog(hθ(xi)k)

h θ ( x i ) j = e x p ( x i ) j ∑ k = 1 K e x p ( x i ) k h_{\theta}(x_{i})_{j} = \frac{exp(x_{i})_{j}}{\sum_{k = 1}^{K}exp(x_{i})_{k}} hθ(xi)j=k=1Kexp(xi)kexp(xi)j

其中

  • N N N : 样本点的数量
  • K K K : 类别的数量
  • y i c y_{ic} yic : 样本目标的 o n e − h o t one-hot onehot 编码。如果样本 x i x_{i} xi 的真实类别等于 k k k 取1,否则取0。
  • h θ ( x i ) k h_{\theta}(x_{i})_{k} hθ(xi)k : 观测样本 x i x_{i} xi 属于类别 k k k 的预测概率。

样例

下面以一个图片分类问题为例,理解上面的公式。这个例子,根据图片中动物的轮廓、颜色等特征,来预测动物的类别(猫、狗、马)。

类别名称 类别编号 one-hot
0 [1, 0, 0]
1 [0, 1, 0]
2 [0, 0, 1]

有一张马的图片,它的真实类别编号为 2, one-hot 编码为 [ 0 , 0 , 1 ] [0, 0, 1] [0,0,1] 。假定模型的预测概率为 [ 0.1 , 0.12 , 0.78 ] [0.1, 0.12, 0.78] [0.1,0.12,0.78],如下为计算交叉熵的过程。

类别名称 预测概率 类别的one-hot 符号函数值 yicyic​ 单项交叉熵计算过程 单项交叉熵结果
0.1 [1, 0, 0] 0 -0 * log(0.1) 0
0.12 [0, 1, 0] 0 -0 * log(0.12) 0
0.78 [0, 0, 1] 1 -1 * log(0.78) 0.2485

总的交叉熵为0.2485。

Pytorch 中的CrossEntropy的形式

pytorch中torch.nn模块和torch.nn.functional中均有对应的交叉熵的模块,但是两者是相通的。不过torch.nn.functional中可以理解为是一个接口,而torch.nn是具体类的定义。

  1. torch.nn.functional.cross_entropy
def cross_entropy(input, target, weight=None, size_average=None, ignore_index=-100,
                  reduce=None, reduction='mean'):
    # type: (Tensor, Tensor, Optional[Tensor], Optional[bool], int, Optional[bool], str) -> Tensor

    if size_average is not None or reduce is not None:
        reduction = _Reduction.legacy_get_string(size_average, reduce)
    return nll_loss(log_softmax(input, 1), target, weight, None, ignore_index, None, reduction)

看上面代码也能知道input和target是必选项,并且是Tensor类型的。最后一行说明functional.cross_entropy实际计算过程就是先计算Tensor的log_softmax,然后再计算nll_loss。

那么问题来了,log_softmax是怎么计算的,干了些什么,用上面表格的数据来举例来说:

Tensor的log_softmax函数和functional的函数作用一样,都是先对数据进行softmax,然后进行log函数,这里的log以e为底,即ln。log_softmax和softmax中的数字表示按照什么维度计算。0代表按列计算,softmax函数计算后的数据按列加起来为1;1代表按行计算,softmax函数计算后的数据按行加起来为1。

import torch.nn.functional as F
import torch
truth = torch.tensor([[1, 0, 0]], dtype=torch.float)
predicted1 = torch.tensor([[0.5, 0.4, 0.1]], dtype=torch.float)
print(truth.softmax(0))
print(truth.softmax(1))
print(F.log_softmax(predicted1, 1))
print(truth.log_softmax(-1))

上面代码的输出结果为:

tensor([[1., 1., 1.]])
tensor([[0.5017, 0.2491, 0.2491]])
tensor([[-0.9459, -1.0459, -1.3459]])
tensor([[-0.6897, -1.3897, -1.3897]])

第一行的输出结果可以理解,按照列计算只有一个数据,所以计算后每列的只有1个1。
第二行的输出结果可以通过计算得到:

e 1 e 1 + e 0 + e 0 = e e + 2 ​ = 0.5017 \frac{e^{1}}{e^{1}+e^{0}+e^{0}}=\frac{e}{e+2}​=0.5017 e1+e0+e

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我是路人贾啊

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值