熵,交叉熵,KL散度公式与计算实例 (转载学习)

交叉熵(Cross Entropy)和KL散度(Kullback–Leibler Divergence)是机器学习中极其常用的两个指标,用来衡量两个概率分布的相似度,常被作为Loss Function。本文给出熵、相对熵、交叉熵的定义,用python实现算法并与pytorch中对应的函数结果对比验证。

熵(Entropy)

此处为方便讨论及与后续实例呼应,所有随机变量均为离散随机变量。

定义随机变量x在概率分布p的熵:
在这里插入图片描述

import torch
import numpy as np
from torch.distributions import Categorical, kl

# Entropy
p = [0.1, 0.2, 0.3, 0.4]

Hp = -sum([p[i] * np.log(p[i]) for i in range(len(p))])
print (f"H(p) = {Hp}")
dist_p = Categorical(torch.tensor(p))
print (f"Torch H(p) = {dist_p.entropy().item()}")

结果

H(p) = 1.2798542258336676
Torch H(p) = 1.2798542976379395

相对熵(Relative Entropy)

相对熵(Relative Entropy),也称KL散度 (Kullback–Leibler divergence)。

p(x),q(x)为随机变量x的两个概率分布,定义p对q的相对熵(KL散度)为:
在这里插入图片描述
KL散度在p(x)和q(x)相同时取到最小值0,两个概率分布越相似,则KL散度越小。

假设p(x)是随机变量的真实分布,q(x)是模型预测的分布,则可以用KL散度作为分类问题的Loss Function,通过训练使预测分布接近于真实分布。

import torch
import numpy as np
from torch.distributions import Categorical, kl

# KL divergence
p = [0.1, 0.2, 0.3, 0.4]
q = [0.1, 0.1, 0.7, 0.1]

Dpq = sum([p[i] * np.log(p[i] / q[i]) for i in range(len(p))])
print (f"D(p, q) = {Dpq}")
dist_p = Categorical(torch.tensor(p))
dist_q = Categorical(torch.tensor(q))
print (f"Torch D(p, q) = {kl.kl_divergence(dist_p, dist_q)}")

结果:

D(p, q) = 0.43895782244378423
Torch D(p, q) = 0.4389578104019165

交叉熵(Cross Entropy)

在这里插入图片描述

import torch
import numpy as np
from torch.distributions import Categorical, kl

# Cross entropy
p = [0.1, 0.2, 0.3, 0.4]
q = [0.1, 0.1, 0.7, 0.1]

Hpq = -sum([p[i] * np.log(q[i]) for i in range(len(p))])
print (f"H(p, q) = {Hpq}")

结果

H(p, q) = 1.7188120482774516

交叉熵损失函数

具体地来看下交叉熵作为分类问题的损失函数是如何工作的。 参考pytorch的文档:https://pytorch.org/docs/master/generated/torch.nn.CrossEntropyLoss.html

torch.nn.CrossEntropyLoss(weight: Optional[torch.Tensor] = None, size_average=None, ignore_index: int = -100, reduce=None, reduction: str = 'mean')

输入为两部分Input和Target,其中Input的Shape是(batch_size, C),CrossEntropyLoss是softmax和NLLLoss的结合体,Matrix每行的值是模型输出的各分类的概率值,无须经过softmax;Target的Shape是(batch_size),取值是true label对应的类的index。 输出是一个tensor。

听起来复杂,举个例子: 一个4分类问题,假设模型输出的结果是p = [1,2,3,4],true label是1,即第二类:

import torch
import numpy as np
from torch.distributions import Categorical, kl
from torch.nn import CrossEntropyLoss

# Cross entropy loss
p = [1, 2, 3, 4]
q = [1] # [0, 1, 0, 0] = torch.nn.functional.one_hot(torch.tensor(q), len(p))

celoss = -p[q[0]] + np.log(sum([np.exp(i) for i in p]))
print (f"Cross Entropy Loss: {celoss}")

loss = CrossEntropyLoss()
tensor_p = torch.FloatTensor(p).unsqueeze(0)
tensor_q = torch.tensor(q)
output = loss(tensor_p, tensor_q)
print (f"Torch Cross Entropy Loss: {output.item()}")

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(jexp(x[j]))

结果:

Cross Entropy Loss: 2.4401896985611957
Torch Cross Entropy Loss: 2.4401895999908447

在这里插入图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值