Measurement

测度

Euclidian Distance(欧几理得距离)

\(\large \begin{array}{rl} \\
EuDistance(Point_1, Point_2) &= \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2} \\
where: & \\
Point_1 &= (x_1, y_1), \\
Point_2 &= (x_2, y_2), \\
\end{array}\)

Manhattan Distance(出租车站点距离)

\(\large \begin{array}{rl} \\
MhtDistance(Point_1, Point_2) &= |x_1 - x_2| + |y_1 - y_2| \\
where: & \\
Point_1 &= (x_1, y_1), \\
Point_2 &= (x_2, y_2), \\
\end{array}\)

KLD(Kullback-Leibler Divergence,KL散度):

测度比较两Distribution的Similarity

  • AI领域最重要的 Measure Method of Distributions(分布度量方法)
  • 简写和全称: KLD(Kullback-Leibler Divergence, KL散度)
  • 用途: 测度比较两Distribution的Similarity(
    • 统计应用上, 我们经常需要用一个常用、组件模块化、简单近似的 \(\large Distribution\) $\large f^* $,

      去描述另一个复杂的, \(\large Distribution\) $\large f $ 或 \(\large Observations(观察数据)\) \(\large D\);
    • 这时,我们需要一个度量来衡量选择的 \(\large \bm{ Approximated\ Distribution}\) $\large f^* $

      对比原 \(\large Distribution\) \(\large f\) 总共 \(\large Loss\) 多少\(\large \bm{ Information(信息量)}\)。

      这就是KLD(散度)起作用的地方。

\(\large Information\ Entropy\)(信息熵)

KL(Kullback-Leibler Divergence, 散度)起源于 IT(Information Theory, 信息理论)。

I.T.的主要目标量化数据信息量

I.T. 最重要的度量标准称为 \(\large Entropy\)(熵), 常用 \(\large H\) 表示。

\(large \text{for a Distribution} \large p(X)\), \(\large \text{ the } Definition \text{ of } Entropy\) 的定义是:

\(\large \begin{array}{rl} \\
H &= \overset{N}{\underset{i=1}{\sum}}{p(x_{i}) \cdot log_{k}{p(x_{i})}} \\
if\ k = 2, then: \\
\end{array}\)

如果计算时使用\(\large log_{2}\), 我们可以将Entropy(熵)解释为

"Encoding(编码)我们的Information(信息)所需的$ Minimum\ Number \text{ of } bits$(最小比特数)。

举几个例子,有一门语言是由 ABCD 四个字母组成的,整个语料库为 8192个字母。

  • Example 1, A、B、C、D 四个字母分别占 1/2(4096个), 1/4(2048个), 1/8(1024个), 1/8(1024个)。

    那么最有效的一种编码方式为 A(0), B(10), C(110), D(111)。

    整个语料库的长度 4096 x 1 + 2048 x 2 + 1024 x 3 x 2=14336,平均长度为 14336/8192=1.75。

    和下面代码的【结果1】一致。

  • Example 2, ABCD 等概率, 最有效的一种编码方式为 A(00), B(01), C(10), D(11), 计算平均长度为2,

    和代码中的【结果2】一致。

  • Example 3: ABCD 四个字母占比变成1/8(1024个), 1/8(1024个), 1/2(4096个), 1/4(2048个),

    最有效的一种编码方式为 A(110), B(111), C(0), D(10), 计算平均长度为1.75,

    和代码中的【结果3】一致。

我们用\(\large Entropy\)(熵)的方式计算:

  • 代码示例1:
import math

def cal_entropy_log2(prob_distribution):
return -sum(p * math.log2(p) for p in prob_distribution) p = [0.5, 0.25, 0.125, 0.125]
entropy = cal_entropy_log2(p)
print(f"熵: {entropy}")
#【结果1】输出为:熵: 1.75 q = [0.25, 0.25, 0.25, 0.25]
entropy = cal_entropy_log2(q)
print(f"熵: {entropy}")
#【结果2】输出为:熵: 2.0 q2 = [0.125, 0.125, 0.5, 0.25]
entropy = cal_entropy_log2(q2)
print(f"熵: {entropy}")
#【结果3】输出为:熵: 1.75 import numpy as np
def kl_divergence_log2(a, b):
return sum(a[i] * np.log2(a[i]/b[i]) for i in range(len(a))) print('KL-divergence_log2(例1 || 例2): %.6f ' % kl_divergence_log2(p, q))
# 输出:KL-divergence_log2(例1 || 例2): 0.250000 print('KL-divergence_log2(例1 || 例3): %.6f ' % kl_divergence_log2(p, q2))
# 输出:KL-divergence_log2(例1 || 例3):

\(\large KL\)(Kullback-Leibler) 散度的计算公式

\(\large KL\text{ is a kind of }Method \text{ for } measuring \text{ the } difference \text{ between } two\ Distributions\)

散度, 是一种衡量两个概率分布之间差异性的度量方法。

\(\large KL\)是对熵公式的轻微修改。

\(\large \begin{array}{ll} \\
Hypothesis, \\
\text{ there is a }Distribution\ p(X), \text{ usually means } Observations,\ Samples,\\
\text{ and } Approximated\ Distribution\ q, \text{ usually means the }output \text{ of } Predicative\ Model,\\
then, \text{ the } difference \text{ between these } two\ Distribution \text{ is as follow }:\\
\end{array}\)

离散性的公式如下:

\(\large \begin{array}{rl} \\
D_{KL}(p || q) &= \overset{N}{\underset{i=1}{\sum}}{[ p(x_{i}) \cdot ( log_{k}{p(x_{i})} - log_{k}{q(x_{i})} ) ]} \\
& = \overset{N}{\underset{i=1}{\sum}}{( p(x_{i}) \cdot log_{k}{ \dfrac{p(x_{i})}{q(x_{i})} } )} \\
\end{array}\)

连续性的公式如下:

\(\large \begin{array}{rl} \\
D_{KL}(p || q) &= \int_{-\infty}^{\infty} { p(x) \cdot [ log_{k}{p(x)} - log_{k}{q(x)} ] } \text{ d}x \\
&= \int_{-\infty}^{\infty} { p(x) \cdot log_{k}{ \dfrac{p(x)}{q(x)} } \text{ d}x } \\
\end{array}\)

二进制编码角度的解释

假如用二进制编码长度来解释 \(\large KL\) , 其衡量的是当使用基于\(\large q(x)\) 的编码而非基于\(\large p(x)\) 的编码对来自\(\large p(x)\)的\(\large Samples\)进行编码时, 所需的额外比特数的\(\large Expectation\), 结果大于等于 0(两个\(\large Distribution\)完全一样时为 0)。

还以【例1】计算 \(\large KL\) 散度(注意:对数的底还是取 2,而不是概率学用到的自然底数 e)。

当我们使用【例2】的 ABCD 编码方式对【例1】的数据编码时,

平均长度显然就是 2,

所以 \(\large KL(例1||例2) =2-1.75=0.25\)。

当我们使用【例3】的 ABCD 编码方式对【例1】的数据编码时,

长度变成 (4096 * 3 + 2048 * 3 + 1024 * 1 + 1024 * 2 )/8192 = 2.625,

所以 \(\large KL(例1||例3) = 2.625-1.75 =0.875\),

和代码一致, 即相对于自身分布的最优编码,用另一个分布的最优编码来编码时,平均额外需要0.875个比特。

KL 散度的分步计算

KL 散度的中间步骤的计算结果, 可能为正, 也可能为负数。

以下为 p 和 q1 的 \(\large KL\) 散度的分步计算结果,可对照上面的数据示例和程序输出看。

p[i] q[i] p[i]/q[i] log(p[i]/q[i]) p[i]*log(p[i]/q[i])
0.15 0.14 1.071429 0.068993 0.010349
0.13 0.14 0.928571 -0.074108 -0.009634
0.23 0.25 0.920000 -0.083382 -0.019178
0.09 0.08 1.125000 0.117783 0.010600
0.2 0.21 0.952381 -0.048790 -0.009758
0.05 0.06 0.833333 -0.182322 -0.009116
0.15 0.12 1.250000 0.223144 0.033472
求和: 0.006735

分步计算的结果和后面代码的一致。

如下面代码所示。

import numpy as np
from kl_div_data import box_p, box_q1, box_q2 def kl_divergence_step(a, b):
return np.array([a[i] * np.log(a[i]/b[i]) for i in range(len(a))]) np.set_printoptions(precision=6) print(kl_divergence_step(box_p, box_q1))
# 输出:
# [ 0.010349 -0.009634 -0.019178 0.0106 -0.009758 -0.009116 0.033472] print(kl_divergence_step(box_p, box_q2))
# 输出:
# [ 0.046523 0.021717 0.010224 -0.051783 0.057536 -0.058158 0.076624]

\(\large KL\) 散度的特点及代码示例

\(\large KL\)散度具有以下显著特点:

  • 非对称性: \(\large KL\)散度是非对称的,

    即从 P分布到 Q分布 的 \(\large KL\)散度, 与从 Q分布 到 P分布 的 \(\large KL\)散度可能不同。

    如代码中示例, \(\large KL(p || q1)\) 和 $\large KL(q1 || p) $ 不同。
  • 非负性: \(\large KL\)散度的值始终为非负数。

    当且仅当两个概率分布完全一致时, \(\large KL\)散度的值才为零。

    \(\large KL\)散度值越大,表示两个概率分布越不相似。

    如代码示例,相对 p, q2 的 \(\large KL\) 散度比 q1大, 这和图上的直观显示一致。
  • 非度量性: \(\large KL\)散度并不满足度量空间的性质,特别是三角不等式

    由于非对称性和非度量性, \(\large KL\) 散度不能用于计算两个分布之间的“距离”或“相似度”。
  • 直观性: \(\large KL\)散度的值越大, 表示用一个分布近似另一个分布时引入的信息损失或误差越大。

    这使得KL散度在度量模型的误差或信息损失方面非常直观。

以下代码列出 \(\large KL\) 散度的三种实现方式:

  • 简单函数
  • 使用 Scipy rel_entr 函数
  • 使用 Pytorch KLDivLoss

简单函数

import numpy as np
from scipy.special import rel_entr
from kl_div_data import box_p, box_q1, box_q2 def kl_divergence(a, b):
return sum(a[i] * np.log(a[i]/b[i]) for i in range(len(a))) print('KL-divergence(p || q1): %.6f ' % kl_divergence(box_p, box_q1)) # KL 散度没有对称性
print('KL-divergence(q1 || p): %.6f ' % kl_divergence(box_q1, box_p))
# 从计算结果可以看出,概率分布 q2 和 p 的差异明显更大
print('KL-divergence(p || q2): %.6f ' % kl_divergence(box_p, box_q2))

使用 Scipy rel_entr 函数

# 使用 Scipy rel_entr 函数
p = np.array(box_p)
q1 = np.array(box_q1)
q2 = np.array(box_q2) # 和上面函数的计算结果一致
print('rel_entr KL-divergence(p || q1): %.6f ' % sum(rel_entr(p, q1)))
print('rel_entr KL-divergence(p || q2): %.6f ' % sum(rel_entr(p, q2)))
print('rel_entr KL-divergence(q1 || p): %.6f ' % sum(rel_entr(q1, p)))
# 自身的 KL 散度是0
print('rel_entr KL-divergence(p || p): %.6f ' % sum(rel_entr(p, p))) # ------- 输出如下 -------
# KL-divergence(p || q1): 0.006735
# KL-divergence(q1 || p): 0.006547
# KL-divergence(p || q2): 0.102684
# rel_entr KL-divergence(p || q1): 0.006735
# rel_entr KL-divergence(p || q2): 0.102684
# rel_entr KL-divergence(q1 || p): 0.006547
# rel_entr KL-divergence(p || p): 0.000000

使用 Pytorch KLDivLoss

# torch 的写法,参考:https://pytorch.org/docs/stable/generated/torch.nn.KLDivLoss.html
import torch
kl_loss = torch.nn.KLDivLoss(reduction="sum",log_target=False) # 第 1 个参数为模型的输出,上面直接指定了概率,故增加一次 log
# 第 2 个参数为真实概率
output = kl_loss(torch.log(torch.tensor(q1)), torch.tensor(p))
print(output)
# 输出:
# tensor(0.0067, dtype=torch.float64)

作为Loss Function(损失函数)

使用 \(\large KL\) 作为Loss Function(损失函数)的算法在机器学习和深度学习中非常常见,尤其在处理涉及概率分布的问题时。例如

  • VAE(变分自编码器): VAE是一种生成模型,它结合了自编码器的结构和概率图模型。

    在 VAE 中, \(\large KL\) 被用作Loss Function的一部分, 用于衡量Encoder生成的潜在空间分布先验分布之间的差异

SciTech-BigDataAIML-Measurement: Euclidian Distance + Manhattan Distance + Area面积 + Density密度 + KLD(KL散度):测度比较"两Distribution(概率分布)"的Similarity(接近度)的更多相关文章

  1. Manhattan distance(for lab)

    Input four integer x1, y1, x2, y2, which is mean that the coordinates of two points A(x1, y1), B(x2, ...

  2. poj 1265 Area 面积+多边形内点数

    Area Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5861   Accepted: 2612 Description ...

  3. 【TOJ 1449】Area of Circles II(求不同位置的两圆面积之和)

    描述 There are two circles on the plane. Now you must to calculate the area which they cover the plane ...

  4. Annoy 近邻算法

    Annoy 随机选择两个点,以这两个节点为初始中心节点,执行聚类数为2的kmeans过程,最终产生收敛后两个聚类中心点 二叉树底层是叶子节点记录原始数据节点,其他中间节点记录的是分割超平面的信息 但是 ...

  5. 概率分布之间的距离度量以及python实现

    1. 欧氏距离(Euclidean Distance)       欧氏距离是最易于理解的一种距离计算方法,源自欧氏空间中两点间的距离公式.(1)二维平面上两点a(x1,y1)与b(x2,y2)间的欧 ...

  6. Approximate Nearest Neighbors.接近最近邻搜索

    (一):次优最近邻:http://en.wikipedia.org/wiki/Nearest_neighbor_search 有少量修改:如有疑问,请看链接原文.....1.Survey:Neares ...

  7. 从线性模型(linear model)衍生出的机器学习分类器(classifier)

    1. 线性模型简介 0x1:线性模型的现实意义 在一个理想的连续世界中,任何非线性的东西都可以被线性的东西来拟合(参考Taylor Expansion公式),所以理论上线性模型可以模拟物理世界中的绝大 ...

  8. PyTorch 实战:计算 Wasserstein 距离

    PyTorch 实战:计算 Wasserstein 距离 2019-09-23 18:42:56 This blog is copied from: https://mp.weixin.qq.com/ ...

  9. GAN实战笔记——第五章训练与普遍挑战:为成功而GAN

    训练与普遍挑战:为成功而GAN 一.评估 回顾一下第1章中伪造达・芬奇画作的类比.假设一个伪造者(生成器)正在试图模仿达・芬奇,想使这幅伪造的画被展览接收.伪造者要与艺术评论家(判别器)竞争,后者试图 ...

  10. C博客作业01--分支,顺序结构

    本章学习总结(2分) 1.1思维导图 1.2本章学习体会及代码量学习体会 1.2.1学习体会 本周初次接触C语言,一开始难度较大,很多代码都看不懂,书里面的章节要看很多遍.开始编写代码时也遇到很多困难 ...

随机推荐

  1. linux 安装jdk8

    参考:https://www.cnblogs.com/raoyulu/p/13265419.html 一.卸载现用的JDK 1.查看Linux自带的JDK是否已安装 查看是否安装openjdk jav ...

  2. 联邦学习图像分类实战:基于FATE与PyTorch的隐私保护机器学习系统构建指南

    引言 在数据孤岛与隐私保护需求并存的今天,联邦学习(Federated Learning)作为分布式机器学习范式,为医疗影像分析.金融风控.智能交通等领域提供了创新解决方案.本文将基于FATE框架与P ...

  3. RabbitMQ的连接方式

    一.帐号密码连接 直接设置各个属性值,其中许多属性有其默认值,例如 connection = pika.BlockingConnection(pika.ConnectionParameters(vir ...

  4. 已经在为VKProxy写UI配置站点和文档了

    VKProxy 是使用c#开发的基于 Kestrel 实现 L4/L7的代理 有兴趣的同学点个赞呗 目前已经在写文档了, 文档在 https://fs7744.github.io/VKProxy.Do ...

  5. 聊聊常见的几款Agent平台:字节Coze、腾讯元器、文心智能体

    你好,小钗在医疗AI.教育AI.管理AI有丰富的经验 关注公众号,回复1,与我交个朋友吧 之前我们探讨过公司AI能力的评判方式: 这里主要涉及两个方面:工程能力以及行业KnowHow. 对于一般公司, ...

  6. 【中文】【吴恩达课后编程作业】Course 2 - 改善深层神经网络 - 第三周作业

    [中文][吴恩达课后编程作业]Course 2 - 改善深层神经网络 - 第三周作业 - TensorFlow入门 上一篇:[课程2 - 第三周测验]※※※※※ [回到目录]※※※※※下一篇:[课程3 ...

  7. 图解JavaScript原型:原型链及其分析 | JavaScript图解

    忽略该图的细节(如内存地址值没有用二进制) 以下是对该图进一步的理解和总结 1. JS对象概念的辨析 对象是什么:保存在堆中一块区域,同时在栈中有一块区域保存其在堆中的地址(也就是我们通常说的该变量指 ...

  8. FlashAttention安装失败的一种可能的原因,nvcc -V与nvidia-smi显示的CUDA版本号不一样

    $ pip install flash-attn --no-build-isolation 报错 RuntimeError: FlashAttention is only supported on C ...

  9. 解析依赖注入(DI)的本质

    本文由 ChatMoney团队出品 在软件开发中,依赖注入是一种常用的设计模式,它允许我们将类的依赖关系通过构造器或其他方式自动注入.这种模式在控制器架构中尤为常见,它使得类的依赖关系更加灵活和可管理 ...

  10. 数据湖选型指南|Hudi vs Iceberg 数据更新能力深度对比

    数据湖作为新一代大数据基础设施,近年来持续火热,许多前线的同学都在讨论数据湖应该怎么建,许多企业也都在构建或者计划构建自己的数据湖.基于此,自然引发了许多关于数据湖选型的讨论和探究.但是经过搜索之后我 ...