#|理解「交叉熵」损失函数(包含自信息、信息熵、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^data?∣∣Pmodel?)=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~P?logQ(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^data??logPmodel?(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?(θ)=N1?n=1∑N?L(y(n),f(x(n); θ))=N1?n=1∑N?(?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 K≥1,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 0≤targets[i]≤C?1
  • 输出Output:标量,形状为(N),或(N, d_1, d_2, ..., d_K), K ≥ 1 K \geq 1 K≥1
    如果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 nncriterion = 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. 【#|理解「交叉熵」损失函数(包含自信息、信息熵、KL散度、交叉熵概念整理)】https://pytorch.org/docs/stable/generated/torch.nn.NLLLoss.html#torch.nn.NLLLoss ??

    推荐阅读