图像识别中欧氏距离与余弦距离的介绍与代码

欧氏距离和余弦相似度:
为什么要引入这两个东西呢,打个比方当我们使用facenet或者其他模型提取一张人脸的1024个特征点后怎么才能知道它是属于谁的人脸呢。这时候这两种方法就起关键作用。
Sample(假如提取的一个人的人脸特征向量如下):
人脸特征
[0.79533959,0.31125495,0.33145159 … 0.21212415,0.7672149 ,0.68650482](1024列)
首先可以把它看成一个1024维度的向量,如果进行人脸匹配的话,就需要与数据库进行比对,假如数据库中已录入有一万张人脸的话,一张人脸对应1024个人脸特征,那么可以把数据库看成一个10000(行)X1024(列)矩阵。我们需要将我们测得的1024个特征与矩阵中的每一行里对应的1024个(列)元素进行比对。此时我们通过常用的欧氏距离或余弦相似度来比较两个向量之间的差距。简单的来说欧氏距离比较的是向量之间的实际距离。 由于1024维度太大不方便举例,我们先举一个三维向量对比差距的例子(假如一个人脸只对应三个维度的数据)。
举个栗子
我们首先使用欧氏距离来比较(1,2,3)和(2,4,6)两个向量之间的距离
根据参考公式如下:
在这里插入图片描述
欧氏距离=
在这里插入图片描述

而余弦相似度表示的是向量之间的夹角大小,比如(1,2,3),(2,4,6)
参考向量求余弦夹角公式:
在这里插入图片描述
在这里插入图片描述

在使用余弦相似度来判断时这就是同一个人,因为二者的夹角是0,二者为平行关系,cosx在定义域(0,π)之间的值域是(-1,1)所以当值越大代表角度越小,为1时方向相同,值越小代表角度越大,值为-1代表两个向量方向完全相反。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们求得图片的特征向量后可通过欧氏距离和余弦相似度来进行人脸匹配,欧氏距离越小代表两个人脸之间的特征值差值越小,人脸越相似,余弦值越大代表两个向量之间的角度越小,人脸越相似。
所以我们通过计算出当前检测到人脸的特征与数据库录入的一万行人脸特征进行比对找到欧氏距离最小或余弦相似度最大的那一行人脸ID,就可以确认当前检测到人脸的身份,如果是未录入的人脸,由于我们设置了阈值,当欧氏距离与余弦相似度未超过此阈值就会显示为unknown,说明此人信息未录入人脸库中,因此我们并不需要保存该人的照片在数据库中,仅仅需要录入其人脸特征向量(以数值矩阵形式保存人脸特征向量)在数据库中。
对比欧氏距离与余弦相似度的相关知识参考
https://blog.csdn.net/huangfei711/article/details/78469614

http://blog.sina.com.cn/s/blog_407e5c1c0102vxyb.html

https://blog.csdn.net/weixin_37589896/article/details/78011003
再举个非常形象简单的关于聚类的例子:

歌手大赛,三个评委给三个歌手打分,第一个评委的打分(10,8,9), 第二个评委的打分(4,2,3),第三个评委的打分(8,10,9),如果采用余弦相似度来看每个评委的差异,虽然每个评委对同一个选手的评分不一样,但第一、第二两个评委对这三位歌手实力的排序是一样的,只是第二个评委对满分有更高的评判标准,说明第一、第二个评委对音乐的品味上是一致的。

因此,用余弦相似度来看,第一、第二个评委为一类人,第三个评委为另外一类。
如果采用欧氏距离, 第一和第三个评委的欧氏距离更近,就分成一类人了,但其实不太合理,因为他们对于三位选手的排名都是完全颠倒的。
两者各自的适用模型:

欧氏距离能够体现个体数值特征的绝对差异,所以更多的用于需要从维度的数值大小中体现差异的分析,如使用用户行为指标分析用户价值的相似度或差异。

余弦距离更多的是从方向上区分差异,而对绝对的数值不敏感,更多的用于使用用户对内容评分来区分兴趣的相似度和差异,同时修正了用户间可能存在的度量标准不统一的问题(因为余弦距离对绝对数值不敏感)。

向量点乘(内积)和叉乘(外积、向量积)概念及几何意义解读
https://blog.csdn.net/allenjiao/article/details/83828021
矩阵的内积点积
https://blog.csdn.net/zkq_1986/article/details/78203972

https://blog.csdn.net/Mr_EvanChen/article/details/77511312
在这里插入图片描述
在这里插入图片描述
Python实现如下:
欧氏距离

import numpy as np
from numpy.random import random
def EuclideanDistances(A, B):
    BT = B.transpose()
    vecProd = np.dot(A,BT)
    SqA =  A**2
    sumSqA = np.matrix(np.sum(SqA, axis=1))
    sumSqAEx = np.tile(sumSqA.transpose(), (1, vecProd.shape[1]))

    SqB = B**2
    sumSqB = np.sum(SqB, axis=1)
    sumSqBEx = np.tile(sumSqB, (vecProd.shape[0], 1))
    SqED = sumSqBEx + sumSqAEx - 2*vecProd
    SqED[SqED<0]=0.0
    ED = np.sqrt(SqED)
    return ED
matrix1= random(size=(1,1024))#单个人脸的特征向量
matrix2= random(size=(10000,1024))#数据库中一万个人脸的特征向量
#matrix1=np.array([[1,1],[1,2]])
#matrix2=np.array([[2,1],[2,2],[2,3]])
Euclidean_dis=EuclideanDistances(matrix1,matrix2)
Euclidean_dis=np.array(Euclidean_dis)#转换成ndarray形式
print(Euclidean_dis[0])
print(type(Euclidean_dis))
print('计算出欧氏距离的个数:',Euclidean_dis.shape[1])
print('欧氏距离最小值是:',min(Euclidean_dis[0]))#最小欧氏距离的值
loc = np.argmin(Euclidean_dis[0])#最小欧氏距离对应的元素位置
print('欧氏距离最小值位于第%d个元素,它的值为%.15f'%(loc,(Euclidean_dis[0][loc])))

余弦距离

from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
from numpy.random import random
import time

def cosine_distance(matrix1, matrix2):
    matrix1_matrix2 = np.dot(matrix1, matrix2.transpose())#内积
    matrix1_norm = np.sqrt(np.multiply(matrix1, matrix1).sum(axis=1))#求模
    matrix1_norm = matrix1_norm[:, np.newaxis]
    matrix2_norm = np.sqrt(np.multiply(matrix2, matrix2).sum(axis=1))
    matrix2_norm = matrix2_norm[:, np.newaxis]
    cosine_distance = np.divide(matrix1_matrix2, np.dot(matrix1_norm, matrix2_norm.transpose()))
    return cosine_distance

matrix1= random(size=(1,1024))#单个人脸的特征向量
matrix2= random(size=(10000,1024))#数据库中一万个人脸的特征向量
#matrix1=np.array([[1,1],[1,2]])
#matrix2=np.array([[2,1],[2,2],[2,3]])
start = time.process_time()
cosine_dis=cosine_distance(matrix1,matrix2)
elapsed = (time.process_time() - start)
print('自己编写代码计算的cosine_dis:',cosine_dis)
print('计算用时:',elapsed)
#print((type(cosine_dis)))
print('数据库里有%d张人脸数据'%cosine_dis.shape[1])#1个人脸与一万个人脸之间的10000个余弦相似度
print('余弦最大值是:',max(cosine_dis[0]))#最大余弦相似度的值
loc = np.argmax(cosine_dis[0])#最大余弦相似度对应的元素位置
print('余弦最大值位于第%d个元素,它的值为%.16f'%(loc,(cosine_dis[0][loc])))
#print(cosine_dis[0][loc])#最大相似度对应的元素位置的元素值
start_2=time.process_time()
cosine_dis2 = cosine_similarity(matrix1,matrix2)
elapsed_2=(time.process_time()-start_2)
print('调库计算的cosine_dis2:',cosine_dis2)
print('调库计算用时:',elapsed_2)
  • 8
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
对于行人重识别可视化检索结果与输入照片差距很大的问题,可能会有多种原因导致。以下是一些常见的问题和可能的解决方案: 1. 特征提取器选择不当:行人重识别中常用的特征提取器包括ResNet、Inception等。确保你使用了适合该任务的特征提取器,并尽量选择在大规模数据集上预训练过的模型。 2. 数据集不平衡:如果训练集和测试集之间存在明显的分布差异,或者训练集中某些类别的样本数量较少,可能会导致检索结果的差异。尽量选择平衡的训练数据集,并确保测试数据集能够充分覆盖各个类别。 3. 图像预处理错误:在行人重识别任务中,图像预处理对结果具有重要影响。确保在输入图像进行预处理时,采用了正确的尺寸调整、归一化、裁剪等操作,并与训练时的预处理方式一致。 4. 距离度量选择不当:行人重识别通常使用特征向量之间的距离来进行相似度度量。常见的距离度量方法包括欧距离余弦相似度等。尝试不同的距离度量方法,选择适合你数据集和任务的度量方式。 5. 模型训练不充分:行人重识别需要大规模的训练数据和较长的训练时间。如果模型训练不充分,性能可能会受到限制。尝试增加训练数据量、调整训练参数或增加训练迭代次数,以获得更好的模型性能。 6. 模型过拟合:如果模型在训练集上表现很好,但在测试集上表现差,可能存在过拟合问题。可以尝试使用正则化方法如dropout、正则化项等来减轻过拟合。 以上是一些可能导致行人重识别可视化检索结果与输入照片差距大的问题和解决方案。具体情况还需要根据你的代码和数据进行进一步分析和调试。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值