信息量、熵、交叉熵、KL散度、JS散度杂谈及代码实现

信息量、熵、交叉熵、KL散度、JS散度杂谈及代码实现

信息量

任何事件都会承载着一定的信息量,包括已经发生的事件和未发生的事件,只是它们承载的信息量会有所不同。如昨天下雨这个已知事件,因为已经发生,既定事实,那么它的信息量就为 0。如明天会下雨这个事件,因为未有发生,那么这个事件的信息量就大。

从上面例子可以看出信息量是一个与事件发生概率相关的概念,而且可以得出,事件发生的概率越小,其信息量越大。这也很好理解,比如某明星被爆出轨、逃税等,这种事件信息量就很大,我们在口语中也会称这种新闻 “信息量很大” ,因为是小概率事件,然而近几年看起来好像已经不是小概率事件了。而对于我是我妈生的,这种事件,信息量就几乎为零,因为这是确定事件。

另外,独立时间的信息量是可叠加的,比如 ”a. 张三喝了阿萨姆红茶,b. 李四喝了英式红茶“ 的信息量就应该是a和b的信息量之和,如果张三李四喝什么茶是两个独立事件。

我们已知某个事件的信息量是与它发生的概率有关,那我们可以通过如下公式计算信息量:假设 XXX 是一个离散型随机变量,其取值集合为 xxx ,概率分布函数 P(x)=Pr(X=x),x∈XP(x)=Pr(X=x),x\in XP(x)=Pr(X=x),xX ,则定义事件 x=x0x=x_0x=x0 的信息量为:
I(x0)=−logP(x0)I(x_0)=-logP(x_0) I(x0)=logP(x0)
我们可以看到,当某个时间的概率为1时,即其一定会发生,则此时它的信息量为0:I=−log1=0I=-log1=0I=log1=0

熵就是信息量的期望,即:
S(x)=−∑iP(xi)logP(xi)S(x)=-\sum_iP(x_i)logP(x_i) S(x)=iP(xi)logP(xi)

可以认为,熵表征的是随机事件的不确定性的大小,即事件可能性越多、越不确定,熵越大。这从公式中也可以看出来:

  • P(xi)P(x_i)P(xi) 作为事件的概率肯定小于 1,取对数肯定小于 0,再取负号肯定大于 0。也就是说,熵累加的每一项都是正数,因此:可能性越多,熵越大。
  • 再看每一项的确定性,当 P(xi)=1P(x_i)=1P(xi)=1000 ,分别代表必定发生或必定不发生,这两种情况事件的确定性最小,从式子中也可以看出 P(xi)=1P(x_i)=1P(xi)=1000 ,该项都为 0。而当 P(xi)P(x_i)P(xi) 的值在 0-1 中间某点时,事件非常不确定,此时该项值较大。因此说,越不确定,熵越大。

KL散度

以上说的都是某一个事件的信息量,如果我们另有一个独立的随机事件,我们该怎么计算事件A和事件B的差别?我们先介绍默认的计算方法:KL散度,有时又称相对熵、KL距离,实际上,虽然可以叫做KL距离,但它绝不是严格意义上的距离,因为KL散度不具有对称性,即A对B的KL散度 和 B对A的KL散度是不一样的。

KL散度的数学定义:对于离散事件
DKL=(A∣∣B)=∑iPA(xi)log(PA(xi)PB(xi))=∑iPA(xi)logPA(xi)−PA(xi)logPB(xi)D_{KL}=(A||B)=\sum_iP_A(x_i)log(\frac{P_A(x_i)}{P_B(x_i)})=\sum_iP_A(x_i)logP_A(x_i)-P_A(x_i)logP_B(x_i) DKL=(A∣∣B)=iPA(xi)log(PB(xi)PA(xi))=iPA(xi)logPA(xi)PA(xi)logPB(xi)
而对于连续事件,我们把求和改成积分即可。

可以看到,KL散度有这么几个特点:

  • 当两个事件完全相同时,即 PA=PBP_A=P_BPA=PB 时,DKL=0D_{KL}=0DKL=0
  • 如果把 A、BA、BAB 的位置互换,则上式右边的值也会不同,KL散度不具有对称性,即 DKL(A∣∣B)≠DKL(B∣∣A)D_{KL}(A||B) \ne D_{KL}(B||A)DKL(A∣∣B)=DKL(B∣∣A)
  • 可以发现,上式右边的左半部分 ∑iPA(xi)logPA(xi)\sum_i P_A(x_i)logP_A(x_i)iPA(xi)logPA(xi) 其实就是事件 A 的熵,这点也是非常重要发现。

有这样的结论: A对B的KL散度由A自己的熵值和B在A上的期望共同决定,当使用A对B的KL散度来衡量两个分布的差异时,就是求A、B的对数差在A上的期望值。

交叉熵

终于来到了我们最熟悉的交叉熵,它是分类任务的最常用的损失函数,每个炼丹师在最开始拿MNIST手写数字分类做Hello World时,应该都使用的交叉熵损失函数。

可是我们上面已经介绍了:KL散度可以用来衡量两个分布的差异,那为什么不直接拿KL散度来做损失函数呢?我们先来对比一下A的熵、A对B的KL散度和A对B的交叉熵三者的公式:

  • A的熵:S(A)=−∑iPA(xi)logPA(xi)S(A)=-\sum_iP_A(x_i)logP_A(x_i)S(A)=iPA(xi)logPA(xi)
  • A对B的KL散度:DKL(A∣∣B)=∑iPA(xi)logPA(xi)−PA(xi)logPB(xi)D_{KL}(A||B)=\sum_iP_A(x_i)logP_A(x_i)-P_A(x_i)logP_B(x_i)DKL(A∣∣B)=iPA(xi)logPA(xi)PA(xi)logPB(xi)
  • A对B的交叉熵:H(A,B)=−∑iPA(xi)logPB(xi)H(A,B)=-\sum_iP_A(x_i)logP_B(x_i)H(A,B)=iPA(xi)logPB(xi)

是不是越看越感觉这哥仨的某一部分有些像,它们之间应该是存在某种关系的。的确是这样的,有:
DKL(A∣∣B)=H(A,B)−I(A)D_{KL}(A||B)=H(A,B)-I(A) DKL(A∣∣B)=H(A,B)I(A)
KL散度=交叉熵-熵

也就是说,KL散度与交叉熵的不同就体现在A本身的熵值上,如果A本身的熵值是一个常量,那么优化KL散度和优化交叉熵实质上就是等价的了

再补充两个交叉熵的性质:

  • 自己与自己的交叉熵即自己的熵值,即 H(A,A)=S(A)H(A,A)=S(A)H(A,A)=S(A)
  • 与KL散度类似,交叉熵也不具有对称性,即 H(A,B)≠H(B,A)H(A,B)\ne H(B,A)H(A,B)=H(B,A)

将交叉熵作为损失函数

在我们训练优化机器学习模型时,我们希望学到的是真实数据的分布 PReal(x)P_{Real}(x)PReal(x),但这只是理想情况,我们不可能得到理想的真实分布。我们实际中一般都是通过在大规模的有标注训练数据分布 PLabel(x)P_{Label}(x)PLabel(x) 上来近似 PReal(x)P_{Real}(x)PReal(x)

在训练中,如果我们用 KL 散度来表示分布之间的差异,那么我们希望的就是模型学习到的分布 PModel(x)P_{Model}(x)PModel(x) 能够与标注训练数据的分布差异越小越好,也就是说我们要最小化这样的KL散度:DKL(Label∣∣Model)D_{KL}(Label||Model)DKL(Label∣∣Model)

可以看到,这里的 PLabelP_{Label}PLabel 就相当于上面的 PAP_APA ,而 PModelP_{Model}PModel 就相当于 PBP_BPB。而我们的标签的分布 PLabelP_{Label}PLabel 的熵值还真就是个常量,更准确地说:标签的分布对于待更新的模型参数来说,是常量。因为标签值不对模型参数进行求导,它的分布是固定的,是不受模型参数变化的影响的。那么我们要最小化 DKL(Label∣∣Model)D_{KL}(Label||Model)DKL(Label∣∣Model) 也就等价与计算交叉熵 $H(Label,Model) $了。而交叉熵算起来又更为方便,因此我们一般就将交叉熵作为损失函数了。

JS散度

JS散度又是怎么回事呢?我们看到,上面的KL散度和交叉熵都是不对称的形式,这在很多问题中是不合适的。因此JS散度的提出,解决了KL散度的不对称性的问题。

JS散度的公式如下:
JS(A∣∣B)=12KL(A∣∣A+B2)+12KL(B∣∣A+B2)JS(A||B)=\frac{1}{2}KL(A||\frac{A+B}{2})+\frac{1}{2}KL(B||\frac{A+B}{2}) JS(A∣∣B)=21KL(A∣∣2A+B)+21KL(B∣∣2A+B)
JS散度有这样的性质:

  • 值域范围[0,1][0,1][0,1]
  • 具有对称性,即 JS(A∣∣B)=JS(B∣∣A))JS(A||B)=JS(B||A))JS(A∣∣B)=JS(B∣∣A)),这从公式里也能看出来,A、BA、BAB 互换还是一样的。

代码实现及测试

以下根据公式手动实现了熵、KL 散度、JS 散度的计算,并与 scipy 库中的实现进行了对比。

import numpy as np
from scipy.stats import entropy
from scipy.spatial.distance import jensenshannondef calc_entropy(probs):# probs.shape: [n, ]log_probs = np.log2(probs)ent = -1 * np.sum(probs * log_probs)return entdef calc_KL_divergence(pa, pb):log_pa = np.log2(pa)log_pb = np.log2(pb)kl = np.sum(pa * log_pa - pa * log_pb)return kldef calc_JS_divergence(pa, pb):pc = 0.5 * (pa + pb)js = 0.5 * calc_KL_divergence(pa, pc) + 0.5 * calc_KL_divergence(pb, pc)return jsif __name__ == '__main__':a = np.array( [0.1, 0.2, 0.7] )b = np.array( [0.2, 0.3, 0.5] )sa = calc_entropy(a)sa_ = entropy(a, base=2)sb = calc_entropy(b)sb_ = entropy(b, base=2)print(f"entropy of a: {sa}, {sa_}")print(f"entropy of b: {sb}, {sb_}")kl_ab = calc_KL_divergence(a, b)kl_ab_ = entropy(a, b, base=2)kl_ba = calc_KL_divergence(b, a)kl_ba_ = entropy(b, a, base=2)print(f"kl of a->b: {kl_ab}, {kl_ab_}")print(f"kl of b->a: {kl_ba}, {kl_ba_}")js_ab = calc_JS_divergence(a, b)js_ab_ = jensenshannon(a, b, base=2)print(f"js of a, b: {js_ab}, {js_ab}")

Ref

https://blog.csdn.net/qq_36552489/article/details/103793667

https://www.zhihu.com/question/65288314

https://blog.csdn.net/FrankieHello/article/details/80614422

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/532609.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CTFHUB《Web-信息泄露-备份文件下载》网站源码,

1.网站源码 三种方法: 方法一:dirsearch扫描git泄露 有文件下载 拿到flag 方法二:御剑(超时10s) 御剑其实也可以扫出来,但是一般我们扫域名超时时间都是三秒,本环境中需要超时10秒才能得到…

Linux下C/C++程序编译链接加载过程中的常见问题及解决方法

Linux下C/C程序编译链接加载过程中的常见问题及解决方法 1 头文件包含的问题 报错信息 该错误通常发生在编译时&#xff0c;常见报错信息如下&#xff1a; run.cpp:2:10: fatal error: dlpack/dlpack.h: No such file or directory#include <dlpack/dlpack.h>^~~~~~~…

DVWA Command Injection 练习总结

low: 首先查看源码没有对字符进行任何过滤 target参数为将要ping的ip地址&#xff0c;比如在输入框输入127.0.0.1后&#xff0c;对于windows系统&#xff0c;会发出ping 127.0.0.1操作。 这里可以引入命令行的几种操作方式&#xff1a; A && B&#xff1a; 先执行A…

在vimrc中设置record

在vimrc中设置record Vim的record功能在大量重复操作的场景下非常实用&#xff0c;但是&#xff0c;一般我们都要每次进入Vim时重新录制record。而对于一些非常常用的record&#xff0c;我们想让它永久地保持&#xff0c;我们知道这种需求需要借助Vim的配置文件vimrc。但是具体…

DVWA sql注入 WP

sql注入基本思路&#xff1a; 1.源码 2.判断数字型和字符型 3.猜测字段数 4.查询数据库中的字段 5.查询表中的字段 6.查询user表中的字段 7.拿字段中数据 low: 1.源码&#xff1a; <?phpif( isset( $_REQUEST[ Submit ] ) ) {// Get input$id $_REQUEST[ id ];// Check…

cmake find_package路径详解

cmake find_package路径详解 转自&#xff1a;https://zhuanlan.zhihu.com/p/50829542 经常在Linux下面写C程序&#xff0c;尤其是需要集成各种第三方库的工程&#xff0c;肯定对find_package指令不陌生。 这是条很强大的指令。可以直接帮我们解决整个工程的依赖问题&#x…

DVWA File Inclusion——Writeup

文件包含&#xff1a; 即File Inclusion&#xff0c;意思是文件包含&#xff08;漏洞&#xff09;&#xff0c;是指当服务器开启allow_url_include选项时&#xff0c;就可以通过php的某些特性函数&#xff08;include()&#xff0c;require()和include_once()&#xff0c;requi…

PyTorch JIT与TorchScript

PyTorch JIT与TorchScript 转自&#xff1a;https://zhuanlan.zhihu.com/p/370455320 如果搜索 PyTorch JIT&#xff0c;找到的将会是「TorchScript」的文档&#xff0c;那么什么是 JIT 呢&#xff1f;JIT 和 TorchScript 又有什么联系&#xff1f; 文章只会关注概念的部分&a…

DVWA Cross Site Request Forgery (CSRF) -------WP

CSRF: 介绍 CSRF跨站点请求伪造(Cross—Site Request Forgery)&#xff0c;跟XSS攻击一样&#xff0c;存在巨大的危害性&#xff0c;你可以这样来理解&#xff1a; 攻击者盗用了你的身份&#xff0c;以你的名义发送恶意请求&#xff0c;对服务器来说这个请求是完全合法的&…

PyTorch C++ API libtorch 简介

PyTorch C API libtorch 简介 翻译自 PyTorch 官方文档&#xff1a;https://pytorch.org/cppdocs/index.html#acknowledgements 整体划分 根据 PyTorch 官方文档 的介绍&#xff0c;PyTorch的C API可以粗略分为以下五个部分&#xff1a; ATen&#xff1a;基础的张量和数学计…

DVWA upload

LOW medium high impossible

安装 PyTorch C++ API libtorch 及一个最小例子

安装 PyTorch C API libtorch 及一个最小例子 翻译自&#xff1a;https://pytorch.org/cppdocs/installing.html 我们提供依赖 PyTorch 所需的所有头文件、库和 CMake 配置文件的二进制分发版。我们将此发行版称为 LibTorch&#xff0c;您可以在我们的网站上下载包含最新 Lib…

ImageNet 1K 类别名与索引的对应关系

ImageNet 1K 类别名与索引的对应关系 转自&#xff1a;http://befree2008.github.io/2018/10/05/20181005_ImageNet1000%E5%88%86%E7%B1%BB%E5%90%8D%E7%A7%B0%E5%92%8C%E7%BC%96%E5%8F%B7/ ImageNet 2012 1000个类名称和编号。ILSVRC2012_img_train.tar 这个文件解压出来都是…

sqlilab--writeup (5~6) 布尔盲注

1.# 和 – &#xff08;有个空格&#xff09;表示注释&#xff0c;可以使它们后面的语句不被执行。在url中&#xff0c;如果是get请求**(记住是get请求&#xff0c;也就是我们在浏览器中输入的url)** &#xff0c;解释执行的时候&#xff0c;url中#号是用来指导浏览器动作的&am…

PyTorch导出JIT模型并用C++ API libtorch调用

PyTorch导出JIT模型并用C API libtorch调用 本文将介绍如何将一个 PyTorch 模型导出为 JIT 模型并用 PyTorch 的 CAPI libtorch运行这个模型。 Step1&#xff1a;导出模型 首先我们进行第一步&#xff0c;用 Python API 来导出模型&#xff0c;由于本文的重点是在后面的部署…

sqli-lab--writeup(7~10)文件输出,时间布尔盲注

前置知识点&#xff1a; 1、outfile是将检索到的数据&#xff0c;保存到服务器的文件内&#xff1a; 格式&#xff1a;select * into outfile “文件地址” 示例&#xff1a; mysql> select * into outfile ‘f:/mysql/test/one’ from teacher_class; 2、文件是自动创建…

树莓派4B (aarch64) 安装PyTorch 1.8 的可行方案

树莓派4B (aarch64) 安装PyTorch 1.8 的可行方案 最终可行方案 试了一堆方案&#xff08;源码编译、Fast.ai的安装文件等&#xff09;之后&#xff0c;终于找到一个可行的方案。是在 PyTorch 官方讨论社区的一个帖子中找到的&#xff0c;在回复中一个大佬给出了自己在2021年1…

sqli-lab———writeup(11~17)

less11 用户名提交单引号显示sql语法错误&#xff0c;故存在sql注入 根据单引号报错&#xff0c;在用户名和密码任意行输入 万能密码&#xff1a;‘ or 11# 输入后username语句为&#xff1a;SELECT username, password FROM users WHERE username or 11; 双引号 password语…

深入理解Python中的全局解释锁GIL

深入理解Python中的全局解释锁GIL 转自&#xff1a;https://zhuanlan.zhihu.com/p/75780308 注&#xff1a;本文为蜗牛学院资深讲师卿淳俊老师原创&#xff0c;首发自公众号https://mp.weixin.qq.com/s/TBiqbSCsjIbNIk8ATky-tg&#xff0c;如需转载请私聊我处获得授权并注明出处…

sqli-lab————Writeup(18~20)各种头部注入

less18 基于错误的用户代理&#xff0c;头部POST注入 admin admin 登入成功&#xff08;进不去重置数据库&#xff09; 显示如下 有user agent参数&#xff0c;可能存在注入点 显示版本号&#xff1a; 爆库&#xff1a;User-Agent:and extractvalue(1,concat(0x7e,(select …