深度学习之“向量范数和距离度量”
在深度学习中,范数和向量距离是两个不同的概念。向量范数是一种函数,用于将一个实数或复数向量映射为一个值。虽然范数通常用于度量向量之间的距离,但是同样也有其它的一些表示距离的方式。
范数距离
范数是具有“长度”概念的函数。在向量空间内,为所有的向量的赋予非零的增长度或者大小。不同的范数,所求的向量的长度或者大小是不同的。
L1范数是指向量中各个元素绝对值之和,L2范数定义为向量所有元素的平方和的开平方。
L1范数的定义:

L2范数的定义:

在深度学习中,二范数可用于正则化的权值衰减法,从而避免模型的权重变得过大。
此外,在facenet人脸识别模型中,就是将将人脸图片表征为一个128维向量,通过计算两个人脸向量之间的二范数距离,来判断两张人脸图片是否属于同一个人。
下面的代码读取了两张人脸图片,分别获得了128维的输出向量并进行正则化,之后使用L2范数计算它们之间的距离。
# 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中的乳腺癌数据集来构建基于马氏距离的最近质心分类器,从而进一步加深理解与认识。
代码实现如下:
导入需要的库
import numpy as np
from sklearn import datasets
from scipy.spatial.distance import mahalanobis
读取数据集并打乱,取前400个样本作为训练数据并将剩下的样本作为测试数据
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:]
计算每个类别数据的均值以及训练数据集的协方差矩阵和协方差矩阵的逆
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)
定义函数,对测试数据集进行分类
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)
分别计算马氏距离和欧氏距离的结果得分
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散度的理解。
首先导入使用到的库
import numpy as np
from scipy.special import rel_entr
import matplotlib.pylab as plt
分别生成服从均匀分布和两组二项分布B(12,0.4)以及B(12,0.9)。
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散度,判断哪个二项分布更接近于均匀分布
print(rel_entr(q,p).sum())
print(rel_entr(w,p).sum())
输出结果如下:

可以看到,w与p的K-L散度更小,说明w与p的概率分布更为相似。事实是否如此呢?我们来看一下三个不同的离散概率分布的图像。
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的散度时的输入换一下顺序
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都作为第一个输入变量,下面又出现了新的问题
print(rel_entr(p,q).sum())
print(rel_entr(p,w).sum())
输出结果如下:

可以看到,结果中竟然出现了inf,但是inf在计算中会给我们带来极大的不便,如何避免这个问题呢?下面给出了解答。
![[图片]](https://i-blog.csdnimg.cn/direct/904fc47db3f4499ca93e4ec9e11ef556.png#pic_center)
相关文章:
深度学习之“向量范数和距离度量”
在深度学习中,范数和向量距离是两个不同的概念。向量范数是一种函数,用于将一个实数或复数向量映射为一个值。虽然范数通常用于度量向量之间的距离,但是同样也有其它的一些表示距离的方式。 范数距离 范数是具有“长度”概念的函数。在向量…...
基于Python的简单企业维修管理系统的设计与实现
以下是一个基于Python的简单企业维修管理系统的设计与实现,这里我们会使用Flask作为Web框架,SQLite作为数据库来存储相关信息。 1. 需求分析 企业维修管理系统主要功能包括: 维修工单的创建、查询、更新和删除。设备信息的管理。维修人员…...
javascript常用函数大全
javascript函数一共可分为五类: •常规函数 •数组函数 •日期函数 •数学函数 •字符串函数 1.常规函数 javascript常规函数包括以下9个函数: (1)alert函数:显示一个警告对话框,包括一个OK按钮。 (2)confirm函数:显…...
【Leetcode 每日一题】81. 搜索旋转排序数组 II
问题背景 已知存在一个按非降序排列的整数数组 n u m s nums nums,数组中的值不必互不相同。 在传递给函数之前, n u m s nums nums 在预先未知的某个下标 k ( 0 < k < n u m s . l e n g t h ) k\ (0 < k < nums.length) k (0<k<…...
< OS 有关 > Android 手机 SSH 客户端 app: connectBot
connectBot 开源且功能齐全的SSH客户端,界面简洁,支持证书密钥。 下载量超 500万 方便在 Android 手机上,连接 SSH 服务器,去运行命令。 Fail2ban 12小时内抓获的 IP ~ ~ ~ ~ rootjpn:~# sudo fail2ban-client status sshd Status for the jail: sshd …...
【算法设计与分析】实验7:复杂装载及0/1背包问题的回溯法设计与求解
目录 一、实验目的 二、实验环境 三、实验内容 四、核心代码 五、记录与处理 六、思考与总结 七、完整报告和成果文件提取链接 一、实验目的 针对复杂装载问题、及0/1背包问题开展分析、建模、评价,算法设计与优化,并进行编码实践。 理解复杂装载…...
仿真设计|基于51单片机的温湿度、一氧化碳、甲醛检测报警系统
目录 具体实现功能 设计介绍 51单片机简介 资料内容 仿真实现(protues8.7) 程序(Keil5) 全部内容 资料获取 具体实现功能 (1)温湿度传感器、CO传感器、甲醛传感器实时检测温湿度值、CO值和甲醛值进…...
使用vhd虚拟磁盘安装两个win10系统
使用vhd虚拟磁盘安装两个win10系统 前言vhd虚拟磁盘技术简介准备工具开始动手实践1.winX选择磁盘管理2.选择“操作”--“创建VHD”3.自定义一个位置,输入虚拟磁盘大小4.右键初始化磁盘5.选择GPT分区表格式6.右键新建简单卷7.给卷起个名字,用于区分8.打开…...
Python学习——函数参数详解
Python中的函数参数传递机制允许多种灵活的参数类型,可以根据需求灵活配置参数,这使得函数具有更强大的扩展性和适应性。以下是对各类参数类型的详细说明: 1. 定义函数的不同参数类型 1.1 位置参数 定义方式:def func(a, b2) 特…...
深入理解Spring事务管理
一、事务基础概念 1.1 什么是事务? 事务(Transaction)是数据库操作的最小工作单元,具有ACID四大特性: 原子性(Atomicity):事务中的操作要么全部成功,要么全部失败 一致…...
自制虚拟机(C/C++)(二、分析引导扇区,虚拟机读二进制文件img软盘)
先修复上一次的bug,添加新指令,并增加图形界面 #include <graphics.h> #include <conio.h> #include <windows.h> #include <commdlg.h> #include <iostream> #include <fstream> #include <sstream> #inclu…...
基于最近邻数据进行分类
人工智能例子汇总:AI常见的算法和例子-CSDN博客 完整代码: import torch import numpy as np from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import accuracy_score import matplotlib.pyplot as plt# 生成一个简单的数据集 (2个特征和2个分类…...
ASP.NET Core 启动并提供静态文件
ASP.NET Core 启动并提供静态文件 即是单个可执行文件,它既运行 API 项目,也托管 前端项目(通常是前端的发布文件)。 这种方式一般是通过将 前端项目 的发布文件(例如 HTML、CSS、JavaScript)放入 Web AP…...
【异步编程】CompletableFuture:异步任务的选择(执行最快的)执行
文章目录 一. applyToEither : 拿到第一个任务结束的结果二. runAfterEither :第一个任务完成后执行副作用三. acceptEither:消费第一个任务的结果四. 三种接口总结 对于两个异步任务,我们有时希望在其中一个任务完成时立即执行某些操作&…...
4 [危机13小时追踪一场GitHub投毒事件]
事件概要 自北京时间 2024.12.4 晚间6点起, GitHub 上不断出现“幽灵仓库”,仓库中没有任何代码,只有诱导性的病毒文件。当天,他们成为了 GitHub 上 star 增速最快的仓库。超过 180 个虚假僵尸账户正在传播病毒,等待不…...
变量和常量
一.变量 1.标准声明 var 变量名 变量类型 变量声明行末不需要分号 2..批量声明 package main import "fmt" func main(){var(a string b int c boold float32)}3.变量的初始化 var a int 10 var b float321.1 4.类型推导 var name"tom" var age18 fmt.Pr…...
大模型概述(方便不懂技术的人入门)
1 大模型的价值 LLM模型对人类的作用,就是一个百科全书级的助手。有多么地百科全书,则用参数的量来描述, 一般地,大模型的参数越多,则该模型越好。例如,GPT-3有1750亿个参数,GPT-4可能有超过1万…...
流浪 Linux: 外置 USB SSD 安装 ArchLinux
注: ArchLinux 系统为滚动更新, 变化很快, 所以本文中的安装方法可能很快就过时了, 仅供参考. 实际安装时建议去阅读官方文档. 最近, 突然 (也没有那么突然) 有了一大堆 PC: 4 个笔记本, 2 个台式主机 (M-ATX 主板), 1 个小主机 (迷你主机). 嗯, 多到用不过来. 但是, 窝又不能…...
Hot100之子串
560和为K的子数组 题目 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列 思路解析 ps:我们的presum【0】就是0,如果没有这个0的话我们的第一个元素就无法减去上…...
网络工程师 (11)软件生命周期与开发模型
一、软件生命周期 前言 软件生命周期,也称为软件开发周期或软件开发生命周期,是指从软件项目的启动到软件不再被使用为止的整个期间。这个过程可以细分为多个阶段,每个阶段都有其特定的目标、任务和产出物。 1. 问题定义与需求分析 问题定义…...
(三)QT——信号与槽机制——计数器程序
目录 前言 信号(Signal)与槽(Slot)的定义 一、系统自带的信号和槽 二、自定义信号和槽 三、信号和槽的扩展 四、Lambda 表达式 总结 前言 信号与槽机制是 Qt 中的一种重要的通信机制,用于不同对象之间的事件响…...
从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(基础图形库实现)
目录 基础图形库的抽象 抽象图形 抽象点 设计我们的抽象 实现我们的抽象 测试 抽象线 设计我们的抽象 实现我们的抽象 绘制垂直的和水平的线 使用Bresenham算法完成任意斜率的绘制 绘制三角形和矩形 矩形 三角形 实现 绘制圆,圆弧和椭圆 继续我们的…...
hot100_21. 合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1: 输入:l1 [1,2,4], l2 [1,3,4] 输出:[1,1,2,3,4,4] 示例 2: 输入:l1 [], l2 [] 输出:[…...
安全防护前置
就业概述 网络安全工程师/安全运维工程师/安全工程师 安全架构师/安全专员/研究院(数学要好) 厂商工程师(售前/售后) 系统集成工程师(所有计算机知识都要会一点) 学习目标 前言 网络安全事件 蠕虫病毒--&…...
01-六自由度串联机械臂(ABB)位置分析
ABB工业机器人(IRB2600)如下图所示(d1444.8mm,a1150mm,a2700mm,a3115mm,d4795mm,d685mm),利用改进DH法建模,坐标系如下所示: 利用改进…...
JVM运行时数据区域-附面试题
Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域 有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而一直存在,有些区域则是 依赖用户线程的启动和结束而建立和销毁。 1. 程序计…...
Java线程池与Future_优化并发任务执行
1. 引言 1.1 并发编程的重要性 并发编程是现代软件开发中的关键部分,特别是在处理高并发、大数据和分布式系统时。通过并发编程,可以充分利用多核处理器的计算能力,提高系统的吞吐量和响应速度。 1.2 线程池与Future的作用 线程池:提供了对线程资源的有效管理和复用,减…...
HTML(快速入门)
欢迎大家来到我的博客~欢迎大家对我的博客提出指导,有错误的地方会改进的哦~点击这里了解更多内容 目录 一、前言二、HTML基础2.1 什么是HTML?2.2 认识HTML标签2.2.1 HTML标签当中的基本结构2.2.2 标签层次结构 2.3 HTML常见标签2.3.1 标题标签2.3.2 段落标签2.3.3…...
《苍穹外卖》项目学习记录-Day10订单状态定时处理
利用Cron表达式生成器生成Cron表达式 1.处理超时订单 查询订单表把超时的订单查询出来,也就是订单的状态为待付款,下单的时间已经超过了15分钟。 //select * from orders where status ? and order_time < (当前时间 - 15分钟) 遍历集合把数据库…...
WebForms SortedList 深度解析
WebForms SortedList 深度解析 引言 在Web开发领域,对于数据结构的理解与应用至关重要。其中,SortedList类在WebForms中是一个常用的数据结构,它能够帮助开发者高效地管理有序数据集合。本文将深入解析SortedList类在WebForms中的应用,包括其基本概念、常用方法、性能特点…...
