求两个矩阵的余弦距离
余弦距离可适应用于人脸识别,将待识别人脸的图像提取特征,与人脸注册库的所有图像的特征矩阵求距离,然后找到最相似的。
本文提供两种思路三种编程方法
导入必要的库
import numpy as np
from numpy.linalg import norm
from sklearn.preprocessing import normalize
随机产生两个矩阵,可以这样理解,待识别人脸有10张,每张特征值128个点;同理人脸库100张图
features1 = np.random.rand(10,128).astype(np.float32)
features2 = np.random.rand(100,128).astype(np.float32)
第一种思路
c o s ( A , B ) = A m ∗ p ⃗ ⋅ B n ∗ p T ⃗ ∣ A ⃗ ∣ ⋅ ∣ B ⃗ ∣ cos(A,B)=\frac{\vec{A_{m*p}}\cdot{\vec{B_{n*p}^T}}}{|\vec{A}|\cdot|{\vec{B}}|} cos(A,B)=∣A∣⋅∣B∣Am∗p⋅Bn∗pT
求两个矩阵的点积,然后再除以模代码如下
norm1 = norm(features1,axis=-1).reshape(features1.shape[0],1)
norm2 = norm(features2,axis=-1).reshape(1,features2.shape[0])
end_norm = np.dot(norm1,norm2)
cos = np.dot(features1, features2.T)/end_norm
print(cos.shape)
(10, 100)
第二种思路
c o s ( A , B ) = A m ∗ p ⃗ ∣ A ⃗ ∣ ⋅ ( B n ∗ p ⃗ ∣ B ⃗ ∣ ) T cos(A,B)=\frac{\vec{A_{m*p}}}{|\vec{A}|}\cdot{(\frac{{\vec{B_{n*p}}}}{|{\vec{B}}|})}^T cos(A,B)=∣A∣Am∗p⋅(∣B∣Bn∗p)T
分别求两个向量的单位向量,然后再求点积
x1 = features1/norm(features1,axis=-1,keepdims=True)
x2 = features2/norm(features2,axis=-1,keepdims=True)
cos1 = np.dot(x1,x2.T)
x11 = normalize(features1)
x22 = normalize(features2)
cos2 = np.dot(x11,x22.T)
np.testing.assert_allclose(cos1,cos2,rtol=1e-6)
np.testing.assert_allclose(cos,cos2,rtol=1e-6)
余弦值的值域是-1到1,值越大,两都越相似,转换一下
similarity= 0.5*cos+0.5
这样将余弦距离转换成相似度,0到1之间,越大越相似