常用的距离以及相似度的计算

曼哈顿距离(Manhattan Distance)

曼哈顿距离(Manhattan Distance)又称之为街道距离,是由十九世纪的赫尔曼·闵可夫斯基所创词汇,是种使用在几何度量空间的几何学用语,用以标明两个点在标准坐标系上的绝对轴距总和。

曼哈顿距离的计算公式为:
M a n h a t t a n   D i s t a n c e = ∑ i = 1 n ∣ x i − y i ∣ Manhattan \ Distance= \sum_{i=1}^{n}|x_i-y_i| Manhattan Distance=i=1nxiyi

#曼哈顿距离
x = [1,2,5,4,6]
y = [3,2,5,5,6]

def MHT_Distance(v1,v2):
    sumxy = 0.0
    for i in range(len(x)):
        sumxy += abs(v1[i]-v2[i])
    return sumxy

print(MHT_Distance(x,y))

#方法二:根据scipy库求解
from scipy.spatial.distance import pdist
X=np.vstack([x,y])
d2=pdist(X,'cityblock')
# 结果为3
欧氏距离(Euclidean Distance)

在数学中,欧几里得距离或欧几里得度量是欧几里得空间中两点间“普通”(即直线)距离。

欧几里得距离的计算公式为:

E u c l i d e a n   d i s t a n c e ( x , y ) = ∑ i = 1 n ∣ x i − y i ∣ 2 2 Euclidean \ distance(x,y) = \sqrt[2]{\sum_{i=1}^{n}|x_i-y_i|^2} Euclidean distance(x,y)=2i=1nxiyi2

#欧式距离
from math import sqrt
x = [1,2,5,4,6]
y = [3,2,5,5,6]

def Ecld_Distance(v1,v2):
    sumxy = 0.0
    for i in range(len(x)):
        sumxy += (v1[i]-v2[i])**2
    return sqrt(sumxy)

print(Ecld_Distance(x,y))
#结果为2.23606797749979

#方法二:根据scipy库求解
from scipy.spatial.distance import pdist
X=np.vstack([x,y])
d2=pdist(X)
切比雪夫距离(Chebyshev Distance)

在数学中,切比雪夫距离(Chebyshev distance)或是L∞度量,是向量空间中的一种度量,二个点之间的距离定义是其各坐标数值差绝对值的最大值。以数学的观点来看,切比雪夫距离是由一致范数(uniform norm)(或称为上确界范数)所衍生的度量,也是超凸度量(injective metric space)的一种。

C h e b y s h e v   d i s t a n c e ( x , y ) = max ⁡ i = 1 n ( ∣ x i − y i ∣ ) Chebyshev \ distance(x,y) =\max_{i=1}^{n}(|x_i-y_i|) Chebyshev distance(x,y)=i=1maxn(xiyi)

#切比雪夫距离
x = [1,2,5,4,6]
y = [3,2,5,5,6]

def Cbsv_Distance(v1,v2):
    max_num = 0.0
    for i in range(len(x)):
        max_num = max(abs(v1[i]-v2[i]),max_num)
    return max_num

print(Cbsv_Distance(x,y))
# 结果为2

#方法二:根据scipy库求解
from scipy.spatial.distance import pdist
X=np.vstack([x,y])
d2=pdist(X,'chebyshev')
闵氏距离(Minkowski Distance)

闵式距离是闵可夫斯基在假定存在n维空间下
n维空间中有两点坐标x,yp为常数,闵式距离定义为
M i n k o w s k i   d i s t a n c e ( x , y ) = ∑ i = 1 n ∣ x i − y i ∣ p p Minkowski \ distance(x,y) = \sqrt[p]{\sum_{i=1}^{n}|x_i-y_i|^p} Minkowski distance(x,y)=pi=1nxiyip

  • p=1时,闵式距离就变成了曼哈顿距离
  • p=2时,闵式距离就变成了欧氏距离
  • p=∞时,闵式距离就变成了切比雪夫距离
# 闵氏距离
x = [1,2,5,4,6]
y = [3,2,5,5,6]

def Mksk_Distance(v1,v2,p):
    sumxy = 0.0
    for i in range(len(x)):
        sumxy += pow(abs(v1[i]-v2[i]),p)
    return pow(sumxy,1/p)

print(Mksk_Distance(x,y,3))
#结果为2.080083823051904

#方法二:根据scipy库求解
from scipy.spatial.distance import pdist
X=np.vstack([x,y])
d2=pdist(X,'minkowski',p=3)
标准化欧氏距离 (Standardized Euclidean Distance)

标准化欧氏距离是针对简单欧氏距离的缺点而作的一种改进方案。标准欧氏距离的思路:既然数据各维分量的分布不一样,好吧!那我先将各个分量都“标准化”到均值、方差相等。
假设样本集X的均值(mean)为m,标准差(standard deviation)为s,那么X的“标准化变量”表示为:
X ∗ = X − m s X^* = \frac{X-m}{s} X=sXm
标 准 化 后 的 值 = 标 准 化 前 的 值 - 分 量 的 均 值 分 量 的 标 准 差 标准化后的值 = \frac{标准化前的值 - 分量的均值 }{分量的标准差} =
经过简单的推导就可以得到两个n维向量 a ( x 11 , x 12 , … , x 1 n ) a(x_{11},x_{12},\ldots,x_{1n}) a(x11,x12,,x1n) b ( x 21 , x 22 , … , x 2 n ) b(x_{21},x_{22},\ldots,x_{2n}) b(x21,x22,,x2n)间的标准化欧氏距离的公式:
d 12 = ∑ k = 1 n ( x 1 k − x 2 k s k ) 2 d12 = \sqrt{\sum^n_{k=1}(\frac{x_{1k}-x_{2k}}{s_k})^2} d12=k=1n(skx1kx2k)2
如果将方差的倒数看成是一个权重,这个公式可以看成是一种加权欧氏距离(Weighted Euclidean distance)。

#标准化欧氏距离
x = [1,3,6,4,7]
y = [3,2,5,5,6]

def st_Ecld_Distance(v1,v2):
    sumxy = 0.0
    X=np.vstack([v1,v2])
    sk=np.var(X,axis=0,ddof=1)
    for i in range(len(x)):
        sumxy += ((v1[i]-v2[i]))**2/sk[i]
    return sqrt(sumxy)
x = [1,3,6,4,7]
y = [3,2,5,5,6]
print(st_Ecld_Distance(x,y))
# 结果为3.1622776601683795

#方法二:根据scipy库求解
from scipy.spatial.distance import pdist
d2=pdist(X,'seuclidean')
马氏距离(Mahalanobis Distance)

马氏距离是由印度统计学家马哈拉诺比斯(P. C. Mahalanobis)提出的,表示点与一个分布之间的距离。它是一种有效的计算两个未知样本集的相似度的方法。与欧氏距离不同的是,它考虑到各种特性之间的联系(例如:一条关于身高的信息会带来一条关于体重的信息,因为两者是有关联的),并且是尺度无关的(scale-invariant),即独立于测量尺度。

对于一个均值为:
μ = ( μ 1 , μ 2 , μ 3 , … , μ p ) \mu=(\mu_1,\mu_2,\mu_3,\ldots,\mu_p) μ=(μ1,μ2,μ3,,μp)
协方差矩阵为Σ的多变量向量,且
x = ( x 1 , x 2 , x 3 , … , x p ) x=(x_1,x_2,x_3,\ldots,x_p) x=(x1,x2,x3,,xp)
其马氏距离为:
( x − μ ) T Σ − 1 ( x − μ ) \sqrt{(x-\mu)^TΣ^{-1}(x-\mu)} (xμ)TΣ1(xμ)

马氏距离也可以定义为两个服从同一分布并且其协方差矩阵为Σ的随机变量 x ⃗ \vec{x} x y ⃗ \vec{y} y 的差异程度:
M a h a l a n o b i s D i s t a n c e = ( x ⃗ − y ⃗ ) T Σ − 1 ( x ⃗ − y ⃗ ) Mahalanobis Distance = \sqrt{(\vec{x}-\vec{y})^TΣ^{-1}(\vec{x}-\vec{y})} MahalanobisDistance=(x y )TΣ1(x y )

马氏距离要求样本数要大于维数,否则无法求协方差矩阵

import numpy as np
x = [3,4,5,6]
y = [2,2,8,4]

#马氏距离要求样本数要大于维数,否则无法求协方差矩阵
#此处的数据并不表示2个4维向量进行的马氏距离的求解,而是4个2维向量表示距离。此处进行转置,表示4个样本,每个样本2维
X=np.vstack([x,y])
XT=X.T

#方法一:根据公式求解
covmatrix=np.cov(X)   #两个维度之间协方差矩阵
covmatrixI = np.linalg.inv(covmatrix) #协方差矩阵的逆矩阵
#马氏距离计算两个样本之间的距离,此处共有4个样本,两两组合,共有6个距离。
n=XT.shape[0]
d1=[]
for i in range(0,n):
    for j in range(i+1,n):
        delta=XT[i]-XT[j]
        d=np.sqrt(np.dot(np.dot(delta,covmatrixI),delta.T))
        d1.append(d)
print(d1)
#结果为
#>[0.9258200997725515, 2.1712405933672376, 2.420153478013917, 2.1712405933672376, 1.5583874449479593, 2.32992949004287]
        
#方法二:根据scipy库求解
from scipy.spatial.distance import pdist
d2=pdist(XT,'mahalanobis')
#结果为
#>[0.9258201  2.17124059 2.42015348 2.17124059 1.55838744 2.32992949]

对于马氏距离的理解稍有复杂,希望自己之后也能够再次重写马氏距离的具体内容。
参考内容:
Ph0en1x的学习笔记——马氏距离(Mahalanobis Distance):https://zhuanlan.zhihu.com/p/46626607
距离度量以及python实现:https://www.cnblogs.com/denny402/p/7027954.html

除上述直接的距离之外,常用的表示距离的形式,还有相似度,并且,相似度的倒数往往也会作为距离的代表。

余弦相似度(Cosine Similarity)

余弦相似度,又称为余弦相似性,是通过计算两个向量的夹角余弦值来评估他们的相似度。余弦相似度将向量根据坐标值,绘制到向量空间中,如最常见的二维空间。
余弦相似性通过测量两个向量的夹角的余弦值来度量它们之间的相似性。0度角的余弦值是1,而其他任何角度的余弦值都不大于1;并且其最小值是-1。从而两个向量之间的角度的余弦值确定两个向量是否大致指向相同的方向。两个向量有相同的指向时,余弦相似度的值为1;两个向量夹角为90°时,余弦相似度的值为0;两个向量指向完全相反的方向时,余弦相似度的值为-1。这结果是与向量的长度无关的,仅仅与向量的指向方向相关。余弦相似度通常用于正空间,因此给出的值为-1到1之间。

注意:

  • 这上下界对任何维度的向量空间中都适用,而且余弦相似性最常用于高维正空间。例如在信息检索中,每个词项被赋予不同的维度,而一个维度由一个向量表示,其各个维度上的值对应于该词项在文档中出现的频率。余弦相似度因此可以给出两篇文档在其主题方面的相似度。它通常用于文本挖掘中的文件比较。此外,在数据挖掘领域中,会用到它来度量集群内部的凝聚力。

c o s   S i m i l a r i t y = ∑ i = 1 n A i × B i ∑ i = 1 n ( A i ) 2 ∑ i = 1 n ( B i ) 2 cos \ Similarity=\frac{\sum_{i=1}^nA_i\times B_i}{\sqrt{\sum_{i=1}^n(A_i)^2}\sqrt{\sum_{i=1}^n(B_i)^2}} cos Similarity=i=1n(Ai)2 i=1n(Bi)2 i=1nAi×Bi

def cosSimilarity(v1,v2):
    sumxx = 0.0
    sumyy = 0.0
    sumxy = 0.0
    for i,j in zip(v1,v2): 
        sumxx += i**2
        sumyy += j**2
        sumxy += i*j
    return sumxy/(sqrt(sumxx)*sqrt(sumyy))
    
v1 = [2,1,0,3]
v2 = [1,3,1,2]
print(cosSimilarity(v1,v2))
改进的余弦相似度(Adjusted Cosine Similarity)

改进的余弦相似度相当于是对余弦相似度有一个归一化的过程
a d j   c o s   s i m ( U i , U j ) = ∑ k ∈ K ( r i k − r i ˉ ) ( r j k − r j ˉ ) ∑ k ∈ K ( r i k − r i ˉ ) 2 ∑ k ∈ K ( r j k − r j ˉ ) 2 adj \ cos \ sim(U_i,U_j)=\frac{\sum_{k\in{K}}(r_{ik}-\bar{r_i})(r_{jk}-\bar{r_j})}{\sqrt{\sum_{k\in{K}}(r_{ik}-\bar{r_i})^2}\sqrt{\sum_{k\in{K}}(r_{jk}-\bar{r_j})^2}} adj cos sim(Ui,Uj)=kK(rikriˉ)2 kK(rjkrjˉ)2 kK(rikriˉ)(rjkrjˉ)

def adjustCosSim(v1,v2):
    v1_avg = np.mean(v1)
    v2_avg = np.mean(v2)
    sumxx = 0.0
    sumyy = 0.0
    sumxy = 0.0
    for i,j in zip(v1,v2):
        sumxx += (i-v1_avg)**2
        sumyy += (j-v2_avg)**2
        sumxy += (i-v1_avg)*(j-v2_avg)
    return sumxy/(sqrt(sumxx)*sqrt(sumyy))

v1 = [2,1,0,3]
v2 = [1,3,1,2]
adjustCosSim(v1,v2)
皮尔逊相关系数( Pearson Correlation Coefficient)

皮尔逊相关系数( Pearson correlation coefficient),又称皮尔逊积矩相关系数(Pearson product-moment correlation coefficient,简称 PPMCC或PCCs),是用于度量两个变量X和Y之间的相关(线性相关),其值介于-1与1之间。
皮尔逊相关系数的三种公式 :
P e a r s o n ( X , Y ) = ∑ ( X , Y ) σ X σ Y Pearson(X,Y)=\frac{\sum(X,Y)}{\sigma_X\sigma_Y} Pearson(X,Y)=σXσY(X,Y)
用户u和用户i之间的Pearson相似度计算方式为
P C C ( u , v ) = ∑ i ∈ I u v ( r u i − r u ˉ ) ( r v i − r v ˉ ) ∑ i ∈ I u v ( r u i − r u ˉ ) ( r v i − r v ˉ ) PCC(u,v)=\frac{\sum_{i\in{I_{uv}}}(r_{ui}-\bar{r_u})(r_{vi}-\bar{r_v})}{\sqrt{\sum_{i\in{I_{uv}}}(r_{ui}-\bar{r_u})(r_{vi}-\bar{r_v})}} PCC(u,v)=iIuv(ruiruˉ)(rvirvˉ) iIuv(ruiruˉ)(rvirvˉ)
P C C ( X , Y ) = ∑ X Y − ∑ X ∑ Y N ( ∑ X − ∑ X N ) 2 ( ∑ Y − ∑ Y N ) 2 PCC(X,Y)=\frac{\sum XY-\frac{\sum X\sum Y}{N}}{\sqrt{(\sum X-\frac{\sum X}{N})^2(\sum Y-\frac{\sum Y}{N})^2}} PCC(X,Y)=(XNX)2(YNY)2 XYNXY

#pearson相关系数
def pearson(v1,v2):
    sumx = sum(v1)
    sumy = sum(v2)
    N = len(v1)
    sumxx = 0.0
    sumyy = 0.0
    sumxy = 0.0
    for i in range(N):
        sumxx += v1[i]**2
        sumyy += v2[i]**2
        sumxy += v1[i]*v2[i]

    up = sumxy-sumx*sumy/N
    down = sqrt(sumxx-sumx**2/N)*sqrt(sumyy-sumy**2/N)
    return up/down

def pearson2(v1,v2):
    sumx = sum(v1)
    sumy = sum(v2)
    N = len(v1)
    sumxx = 0.0
    sumyy = 0.0
    sumxy = 0.0
    for i,j in zip(v1,v2):
        sumxx += i**2
        sumyy += j**2
        sumxy += i*j
    up = sumxy-sumx*sumy/N
    down = sqrt(sumxx-sumx**2/N)*sqrt(sumyy-sumy**2/N)
    return up/down

def mutipl(a,b):
    sumab = 0.0
    for i in range(len(a)):
        sumab += a[i]*b[i]
    return sumab

def pearson3(v1,v2):
    sumx = sum(v1)
    sumy = sum(v2)
    N = len(v1)
    sumxx = mutipl(v1,v1)
    sumyy = mutipl(v2,v2)
    sumxy = mutipl(v1,v2)

    up = sumxy-sumx*sumy/N
    down = sqrt(sumxx-sumx**2/N)*sqrt(sumyy-sumy**2/N)
    return up/down

x = [1,2,5,4,6]
y = [3,2,5,5,6]
print(pearson(x,y))
print(pearson2(x,y))
print(pearson3(x,y))
#结果为:0.9097992698698116
杰卡德相似系数(Jaccard Similarity Coefficient)

Jaccard index,又称为Jaccard相似系数(Jaccard similarity coefficient)用于比较有限样本集之间的相似性与差异性。Jaccard系数值越大,样本相似度越高。

给定两个集合A,B,Jaccard 系数定义为A与B交集的大小与A与B并集的大小的比值,定义如下:
J ( A , B ) = ∣ A ⋂ B ∣ ∣ A ⋃ B ∣ J(A,B)=\frac{|A \bigcap B|}{|A \bigcup B|} J(A,B)=ABAB
当集合A,B都为空时,J(A,B)定义为1,J(A,B)的取值范围为[0,1],1表示相似度很高,0表示相似度极低。
与Jaccard 系数相关的指标叫做Jaccard 距离,用于描述集合之间的不相似度。Jaccard 距离越大,样本相似度越低。公式定义如下:
D J ( A , B ) = 1 − J ( A , B ) = ∣ A ⋃ B ∣ − ∣ A ⋂ B ∣ ∣ A ⋃ B ∣ D_{J}(A,B) = 1-J(A,B)=\frac{|A \bigcup B|-|A \bigcap B|}{|A \bigcup B|} DJ(A,B)=1J(A,B)=ABABAB

def JacSim(v1,v2):
    v1 = set(v1)
    v2 = set(v2)
    intersection = v1 & v2 # 交集
    union = v1 | v2 # 并集
    return len(intersection)/len(union)

x = 'spam'
y = ['h','a','m']
JacSim(x,y)
  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值