深度学习之“向量范数和距离度量”

ops/2025/2/4 23:46:56/

深度学习中,范数和向量距离是两个不同的概念。向量范数是一种函数,用于将一个实数或复数向量映射为一个值。虽然范数通常用于度量向量之间的距离,但是同样也有其它的一些表示距离的方式。

范数距离

范数是具有“长度”概念的函数。在向量空间内,为所有的向量的赋予非零的增长度或者大小。不同的范数,所求的向量的长度或者大小是不同的。
L1范数是指向量中各个元素绝对值之和,L2范数定义为向量所有元素的平方和的开平方。
L1范数的定义:
在这里插入图片描述

L2范数的定义:
在这里插入图片描述

深度学习中,二范数可用于正则化的权值衰减法,从而避免模型的权重变得过大。
此外,在facenet人脸识别模型中,就是将将人脸图片表征为一个128维向量,通过计算两个人脸向量之间的二范数距离,来判断两张人脸图片是否属于同一个人。
下面的代码读取了两张人脸图片,分别获得了128维的输出向量并进行正则化,之后使用L2范数计算它们之间的距离。

python">    # Set inputs and inferenceimage_1 = Image.open("./dataset/facenet/1_001.jpg")image_1 = image_1.resize((160,160), Image.BICUBIC)img1 = np.asarray(image_1, np.uint8)outputs1 = np.array(rknn.inference(data_format='nhwc', inputs=[img1])[0])outputs1 = preprocessing.normalize(outputs1, norm='l2') image_2 = Image.open("./dataset/facenet/1_002.jpg")image_2 = image_2.resize((160,160), Image.BICUBIC)img2 = np.asarray(image_2, np.uint8)outputs2 = np.array(rknn.inference(data_format='nhwc', inputs=[img2])[0])outputs2 = preprocessing.normalize(outputs2, norm='l2') # Get distance distance = np.linalg.norm(outputs2 - outputs1, axis=1)print("distance:", distance)

马氏距离

当需要度量某个特征向量与多个特征向量之间的距离时,如果直接采用欧式距离,衡量的是两个特征向量之间的直接距离,而没有考虑数据的分布特性。而采用马氏距离,在计算中对协方差进行归一化,则可以规避欧式距离对于数据特征方差不同的风险,从而使所谓的“距离”更加符合数据分布特征以及实际意义。
在这里插入图片描述

其中Σ是多维随机变量的协方差矩阵,μ为样本均值向量。马氏距离刻画了x与以μ为均值的某个分布之间的距离。如果协方差矩阵是单位向量,即各维度独立同分布,此时马氏距离就变成了欧氏距离。
在这里插入图片描述

直观的解释如上图,虽然Point1和Point2距离样本中心点的距离相同,但是在右图中,可以明显看出来,Point2不属于该分布。
因此,我们可以使用马氏距离来构建一个简单的分类器。比如,给定数据集,判断输入样本与所有类别质心之间的马氏距离,并选择最小距离作为该输入的类别。
下面以sklearn中的乳腺癌数据集来构建基于马氏距离的最近质心分类器,从而进一步加深理解与认识。
代码实现如下:
导入需要的库

python">import numpy as np
from sklearn import datasets
from scipy.spatial.distance import mahalanobis

读取数据集并打乱,取前400个样本作为训练数据并将剩下的样本作为测试数据

python">bc = datasets.load_breast_cancer()
d = bc.data
l = bc.target
i = np.argsort(np.random.random(len(d)))
d = d[i]
l = l[i]
xtrn, ytrn = d[:400], l[:400]
xtst, ytst = d[400:], l[400:]

计算每个类别数据的均值以及训练数据集的协方差矩阵和协方差矩阵的逆

python">i = np.where(ytrn == 0)
m0 = xtrn[i].mean(axis=0)
i = np.where(ytrn == 1)
m1 = xtrn[i].mean(axis=0)
S = np.cov(xtrn, rowvar=False)
SI= np.linalg.inv(S)

定义函数,对测试数据集进行分类

python">def score(xtst, ytst, m, SI):nc = 0for i in range(len(ytst)):d = np.array([mahalanobis(xtst[i],m[0],SI),mahalanobis(xtst[i],m[1],SI)])c = np.argmin(d)if (c == ytst[i]):nc += 1return nc / len(ytst)

分别计算马氏距离和欧氏距离的结果得分

python">mscore = score(xtst, ytst, [m0,m1], SI)
escore = score(xtst, ytst, [m0,m1], np.identity(30))
print("Mahalanobis score = %0.4f" % mscore)
print("Euclidean   score = %0.4f" % escore)

运行结果如下:
在这里插入图片描述

可以看到,马氏距离分类的效果比欧氏距离的效果有所提升。

K-L散度

K-L散度又称相对熵,用于衡量两个概率分布的相似程度。若K-L散度越小,则说明两个概率分布越相似。
我们设定两个概率分布分别为P和Q,则连续和离散情况下的K-L散度计算公式分别为
在这里插入图片描述

在这里插入图片描述

其中log为以2为底的对数,在scipy.special中使用rel_entr函数来实现K-L散度的计算,但是它使用的是自然对数而不是以2为底的对数。此外,K-L散度不满足对称性,并非数学意义上的距离度量。下面我们通过一个实验来加深对于K-L散度的理解。
首先导入使用到的库

python">import numpy as np
from scipy.special import rel_entr
import matplotlib.pylab as plt

分别生成服从均匀分布和两组二项分布B(12,0.4)以及B(12,0.9)。

python">N = 1000000
p = np.random.randint(0,13,size=N)
p = np.bincount(p)
p = p / p.sum()
q = np.random.binomial(12,0.9,size=N)
q = np.bincount(q)
q = q / q.sum()
w = np.random.binomial(12,0.4,size=N)
w = np.bincount(w)
w = w / w.sum()

使用rel_entr函数计算两组二项分布与均匀分布的K-L散度,判断哪个二项分布更接近于均匀分布

python">print(rel_entr(q,p).sum())
print(rel_entr(w,p).sum())

输出结果如下:
在这里插入图片描述

可以看到,w与p的K-L散度更小,说明w与p的概率分布更为相似。事实是否如此呢?我们来看一下三个不同的离散概率分布的图像。

python">plt.bar(np.arange(13),p,0.333,hatch="///",edgecolor='k')
plt.bar(np.arange(13)+0.333,q,0.333,hatch="---",edgecolor='k')
plt.bar(np.arange(13)+0.666,w,0.333,hatch="\\\\",edgecolor='k')
plt.xlabel("Value")
plt.ylabel("Proportion")
plt.tight_layout(pad=0,h_pad=0,w_pad=0)
plt.savefig("kl_divergence.png", dpi=300)
plt.show()

在这里插入图片描述

其中蓝色为p,橙色为q,绿色为w。可以看到与q相比,p确实更像w,说明我们通过K-L散度的判断是正确的。

此外,既然前面提到了K-L散度是非对称的,那么我们在计算K-L散度时将输入变量换一下位置会产生什么样的后果呢?我们将计算w与p的散度时的输入换一下顺序

python">print(rel_entr(q,p).sum())
print(rel_entr(p,w).sum())

得到结果如下:
在这里插入图片描述

可以看到第二项反而比第一项更大了,这显然不是我们期望的结果。那么在实际使用中,应该如何确定输入变量的顺序呢?
为了解决这个问题,我们首先需要理解K-L散度的意义,KL(P||Q)衡量的是分布P相对于Q的信息损失,即当Q被用作P的近似时,描述P所需的额外信息量。如果将P设为目标分布、Q设为近似分布,则KL(P||Q)越小说明用Q描述P所需的额外信息量越小,即P和Q越接近。相反KL(Q||P)越小,则说明用P描述Q所需的额外信息量越小。因此,在上面比较q和w与p之间的距离时,我们需要固定输入中p的位置,这样得到的数值才具有可比性。
然而,若我们将p都作为第一个输入变量,下面又出现了新的问题

python">print(rel_entr(p,q).sum())
print(rel_entr(p,w).sum())

输出结果如下:
在这里插入图片描述

可以看到,结果中竟然出现了inf,但是inf在计算中会给我们带来极大的不便,如何避免这个问题呢?下面给出了解答。
[图片]


http://www.ppmy.cn/ops/155709.html

相关文章

k8s二进制集群之ETCD集群证书生成

安装cfssl工具配置CA证书请求文件创建CA证书创建CA证书策略配置etcd证书请求文件生成etcd证书 继续上一篇文章《负载均衡器高可用部署》下面介绍一下etcd证书生成配置。其中涉及到的ip地址和证书基本信息请替换成你自己的信息。 安装cfssl工具 下载cfssl安装包 https://github…

Python中的函数(下)

函数返回值 返回单个值 函数可以通过 return 语句返回一个值。一旦执行到 return 语句,函数就会停止执行,并将指定的值返回给调用者。例如: 返回多个值 实际上,Python函数只能返回一个值,但可以通过返回一个元组来模…

系统思考—结构影响行为

“系统的行为是它结构的产物。要改变系统的行为,必须改变它的结构。”——德内拉梅多斯 很多企业在遇到问题时,习惯性的做法是换管理层、加大考核、调整激励机制,甚至开更多的会,但问题真的能解决吗?如果系统的底层逻…

AMD模块

AMD 与 CommonJS 在介绍 AMD 之前,我们需要了解 CommonJS 规范。CommonJS 是服务器端 JavaScript(如Node.js)的模块化标准,它使用同步方式加载模块。然而,这种方式并不适用于浏览器环境,因为 JavaScript 文…

解锁豆瓣高清海报(一) 深度爬虫与requests进阶之路

前瞻 PosterBandit 这个脚本能够根据用户指定的日期,爬取你看过的影视最高清的海报,然后使用 PixelWeaver.py 自动拼接成指定大小的长图。 你是否发现直接从豆瓣爬取下来的海报清晰度很低? 使用 .pic .nbg img CSS 选择器,在 我…

国产之DeepSeek认识、使用及影响

一、前言 2025年乙巳蛇年,DeekSeek彻底网络爆火,为更多国人熟知,在国外更是早先几月就引起Ai界轩然大波,对Ai界硬件显卡厂商英伟达和一众外国Ai资本和科技公司造成很大冲击。Deepseek公司同产品名,早在2023年7月已成立,由知名私募巨头幻方量化孕育而生 ,专注于开发先进的…

【AI编程助手系列】国产AI编程工具 DeepSeek+Cline+VSCode 快速集成

文章目录 前言一、deepseek 介绍二、deepseek 优势三、什么是 Cline?3.1 安装与配置3.1.1 安装 Cline 插件3.1.2 获取 DeepSeek API Key3.1.3 配置 Cline 四、总结 前言 🤖 DeepSeek 是一个强大的 API 平台,提供了丰富的功能和数据&#xff…

【Deep Seek本地化部署】修改模型保存位置

目录 前言 一、官方文档说明 二、操作流程 参考链接 前言 win10系统中,使用ollama进行Deep Seek本地化部署,模型文件默认保存在C:\Users\用户名\.ollama\models文件夹中,很占C盘空间,于是想要更换位置,查阅文档后…