理解「交叉熵」损失函数(包含自信息、信息熵、KL散度、交叉熵概念整理)

文章目录

    • 引言
    • 自信息(self-information)
    • 信息熵/香农熵(Entropy)
    • KL散度(Kullback-Leibler(KL)divergence)
    • 交叉熵(cross-entropy)
    • 分类任务中的交叉熵损失
    • pytorch代码示例
    • 小结

引言

KL散度、交叉熵通常被用来衡量两个分布之间的差异程度,可以用于衡量模型的“损失”。

要深入理解KL散度和交叉熵,首先要从信息论中的基础概念入手。

自信息(self-information)

假如有两条消息,一条内容是“今天太阳从东边升起”,另一条内容是“今天有日食”。

显然后一条消息的发生概率低,消息内容也更有信息量。

信息论的目标之一就是用最少的编码来传递信息。概率越低的事件,对应更高的信息量,概率越高的事件,对应更低的信息量。

所以在信息论中,把发生随机事件 X = x X=x X=x时的信息量进行量化,定义为自信息1
I ( x ) = l o g ( 1 P ( x ) ) = − l o g ( P ( x ) ) I(x) = log(\frac{1}{P(x)})=-log(P(x)) I(x)=log(P(x)1)=log(P(x))

如果log的底数时e, I ( x ) I(x) I(x)单位是奈特(nats);
如果底数是2,则 I ( x ) I(x) I(x)的单位是比特(bit)或香农(shannons)。

信息熵/香农熵(Entropy)

自信息反映的是单个随机事件的信息量,如果要反映整个随机变量分布的信息量,可以用数学期望来衡量这个分布的信息总量,这就是香农熵,又称为信息熵:
H ( x ) = E x ~ P [ I ( x ) ) ] = − E x ~ P [ l o g P ( x ) ] H(x)=\mathbb{E}_{\bold{x} \text{\textasciitilde} P}[I(x))]=-\mathbb{E}_{\bold{x} \text{\textasciitilde} P}[logP(x)] H(x)=Ex~P[I(x))]=Ex~P[logP(x)]

信息熵给出了对分布为P的符号进行编码时的最优平均编码长度2。单位与自信息相同。

KL散度(Kullback-Leibler(KL)divergence)

KL散度也叫KL距离相对熵(Relative Entropy),用来表达以分布Q来近似分布P时的信息损失量。

D K L ( P , Q ) = E x ~ P ( l o g P ( x ) − l o g Q ( x ) ) D_{KL}(P,Q)=\mathbb{E}_{\bold{x} \text{\textasciitilde} P}{(log {P(x)}-log{Q(x)})} DKL(P,Q)=Ex~P(logP(x)logQ(x))
在机器学习中,通常用KL散度来衡量训练数据上的经验分布 P ^ d a t a \hat{P}_{data} P^data和模型分布 P m o d e l P_{model} Pmodel之间的差异1
D K L ( P ^ d a t a ∣ ∣ P m o d e l ) = E x ~ P ^ d a t a ( l o g P ^ d a t a ( x ) − l o g P m o d e l ( x ) ) D_{KL}(\hat{P}_{data}||P_{model})=\mathbb{E}_{\bold{x} \text{\textasciitilde} {\hat{P}_{data}}}{(log{\hat{P}_{data}{(\boldsymbol{x})}}-log{P_{model}{(\boldsymbol{x})}})} DKL(P^dataPmodel)=Ex~P^data(logP^data(x)logPmodel(x))

交叉熵(cross-entropy)

交叉熵 H ( P , Q ) H(P,Q) H(P,Q)与KL散度相比,少一项 H ( P ) H(P) H(P)

H ( P , Q ) = − E x ~ P l o g Q ( x ) H(P,Q)=-\mathbb{E}_{\bold{x} \text{\textasciitilde} P}{log{Q(x)}} H(P,Q)=Ex~PlogQ(x)
在给定分布P的情况下,如果分布Q和P越接近,交叉熵越小;如果分布Q和P越远,交叉熵就越大。

由于训练数据上的经验分布 P ^ d a t a \hat{P}_{data} P^data是不变的,所以最小化两个分布之间的差异性,就相当于最小化两个分布之间的交叉熵
H ( P ^ d a t a , P m o d e l ) = − E x ~ P ^ d a t a l o g P m o d e l ( x ) ) H(\hat{P}_{data},P_{model})=-\mathbb{E}_{\bold{x} \text{\textasciitilde} {\hat{P}_{data}}}{log{P_{model}{(\boldsymbol{x})}})} H(P^data,Pmodel)=Ex~P^datalogPmodel(x))

分类任务中的交叉熵损失

交叉熵可以衡量模型输出和标签之间的距离,所以机器学习、深度学习都常用交叉熵作为损失函数。

以分类任务为例,标签是 [ 0 , 0 , 1 ] T [0, 0, 1]^T [0,0,1]T,而模型的输出概率是 [ 0.3 , 0.3 , 0.4 ] T [0.3, 0.3, 0.4]^T [0.3,0.3,0.4]T,则交叉熵损失为 − ( 0 × l o g ( 0.3 ) + 0 × l o g ( 0.3 ) + 1 × l o g ( 0.4 ) ) = − l o g ( 0.4 ) -(0×log(0.3)+0×log(0.3)+1×log(0.4)) = -log(0.4) (0×log(0.3)+0×log(0.3)+1×log(0.4))=log(0.4)2

为了减少模型输出和标签之间的距离,模型学习的准则就是找到使经验风险最小化的参数。

经验风险用训练集 D D D上的平均损失来表示:
R D ( θ ) = 1 N ∑ n = 1 N L ( y ( n ) , f ( x ( n ) ; θ ) ) = 1 N ∑ n = 1 N ( − l o g f y ( n ) ( x ( n ) ; θ ) ) R_D(θ) = \frac{1}{N}\sum_{\mathclap{n=1}}^NL(y^{(n)},f(\boldsymbol{x}^{(n)};\theta))=\frac{1}{N}\sum_{\mathclap{n=1}}^N(-log{f_{y^{(n)}}}(\boldsymbol{x}^{(n)};\theta)) RD(θ)=N1n=1NL(y(n),f(x(n);θ))=N1n=1N(logfy(n)(x(n);θ))

pytorch代码示例

pytorch中交叉熵损失对应的实现是torch.nn.CrossEntropyLoss3

torch.nn.CrossEntropyLoss( weight=None , size_average=None , ignore_index=-100 , reduce=None , reduction=‘mean’ )

  • 参数weight:(可选)是为每个类分配权重的一维张量,如果给定,必须是大小为C的张量,C表示类别数量(num of classes)。

前向计算:

  • 输入参数Input:形状为 (N, C) ,或(N, C, d_1, d_2, ..., d_K) K ≥ 1 K \geq 1 K1,C表示类别数量(num of classes),N表示minibatch
  • 输入参数Target:形状为 (N)(N, d_1, d_2, ..., d_K) ,每个值满足: 0 ≤ targets [ i ] ≤ C − 1 0 \leq \text{targets}[i] \leq C-1 0targets[i]C1
  • 输出Output:标量,形状为(N),或(N, d_1, d_2, ..., d_K) K ≥ 1 K \geq 1 K1
    如果reduction'none',输出和target的形状相同。

CrossEntropyLoss结合了LogSoftmax4 + NLLLoss5,通过在网络的最后一层添加LogSoftmax层,可以轻松获得神经网络中的对数概率 。如果不想添加额外的层,可以直接用CrossEntropyLoss。

以上一节的分类任务为例,标签是 [ 0 , 0 , 1 ] T [0, 0, 1]^T [0,0,1]T,而模型输出是 [ 0.3 , 0.3 , 0.4 ] T [0.3, 0.3, 0.4]^T [0.3,0.3,0.4]T,计算一下nn.CrossEntropyLoss的损失是多少:

import torch.nn as nn

criterion = nn.CrossEntropyLoss()

# 获取数据,前向计算,此处略... outputs = net(inputs)
outputs = torch.tensor([[0.3,0.3,0.4]])#shape:(N, C),C是类别数
labels = torch.tensor([1])#shape:(N)
loss = criterion(outputs, labels)
print(loss) 

输出:0.9162907318741551,与前面计算的-log(0.4)的结果一致。

小结

简单总结一下本文涉及的基本概念:

  • 自信息:单个随机事件的信息量
  • 信息熵:整个随机分布的信息量
  • KL散度:训练数据上的分布和模型分布之间的差距
  • 交叉熵:两个分布之间差异性的变量部分,常用于损失函数

如果本文对你有帮助的话,欢迎一键三连支持下博主~


  1. 《深度学习》伊恩.古德费洛 ↩︎ ↩︎

  2. 《神经网络与深度学习》邱锡鹏 ↩︎ ↩︎

  3. https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html#torch.nn.CrossEntropyLoss ↩︎

  4. https://pytorch.org/docs/stable/generated/torch.nn.LogSoftmax.html#torch.nn.LogSoftmax ↩︎

  5. https://pytorch.org/docs/stable/generated/torch.nn.NLLLoss.html#torch.nn.NLLLoss ↩︎

你可能感兴趣的:(#,数学基础,概率论,机器学习,深度学习,pytorch,信息论)