欧氏距离(也称欧几里得度量)指在 m m m维空间中两个点之间的真实距离,或者向量的自然长度(即该点到原点的距离)。 在二维和三维空间中的欧氏距离就是两点之间的实际距离。
计算公式:
d i s t ( A , B ) = ∑ i = 1 n ( A i − B i ) 2 dist(A,B)=\sqrt{\sum\limits^n\limits_{i=1}(A_i-B_i)^2} dist(A,B)=i=1∑n(Ai−Bi)2
理解欧氏距离的比较通俗的一种方式,是通过二维向量的距离来进行理解。直观上的感觉,某个点到另一个点的直线距离
使用场景:
随着数据维度的增加,欧几里得距离的作用就越小 。
import numpy as np
vec1 = np.array([1, 3, 4])
vec2 = np.array([4, 2, 4])
# x_norm=np.linalg.norm(x, ord=None, axis=None, keepdims=False)
# x: 表示矩阵(也可以是一维),ord:范数类型
d = np.linalg.norm(vec1-vec2, ord=2)
# 或者
d = np.sqrt(np.sum(np.square(vec1-vec2)))
在欧几里得空间的固定直角坐标系上两点所形成的线段对轴产生的投影的距离总和。
计算公式
d i s t ( A , B ) = ∑ i = 1 n ∣ A i − B i ∣ dist(A,B)=\sum\limits^n\limits_{i=1}|A_i-B_i| dist(A,B)=i=1∑n∣Ai−Bi∣
使用场景
import numpy as np
vec1 = np.array([1, 3, 4])
vec2 = np.array([4, 2, 4])
d = np.linalg.norm(vec1-vec2, ord=1)
# 或者
d = np.sum(np.abs(vec1-vec2))
切比雪夫距离(Chebyshev distance)是向量空间中的一种度量,二个点之间的距离定义为其各坐标数值差的最大值 。 此距离中,加入了优化的成分,通过最值来定义距离。
计算公式
d i s t ( A , B ) = max i ∣ A i − B i ∣ dist(A,B)=\max\limits_i|A_i-B_i| dist(A,B)=imax∣Ai−Bi∣
d i s t ( A , B ) = lim p → ∞ ( ∑ i = 1 n ∣ A i − B i ∣ p ) 1 p dist(A,B)=\lim\limits_{p \to \infty}\left(\sum\limits^n\limits_{i=1}|A_i-B_i|^p\right)^{\frac{1}{p}} dist(A,B)=p→∞lim(i=1∑n∣Ai−Bi∣p)p1
使用场景
import numpy as np
vec1 = np.array([1, 3, 4])
vec2 = np.array([4, 2, 4])
d = np.linalg.norm(vec1-vec2, ord=np.inf)
# 或者
d = np.abs(vec1-vec2).max()
计算公式
d i s t ( A , B ) = p ∑ i = 1 n ∣ A i − B i ∣ p dist(A,B)=p\sqrt{\sum\limits^n\limits_{i=1}|A_i-B_i|^p} dist(A,B)=pi=1∑n∣Ai−Bi∣p
使用场景
闵氏距离的缺点主要有两个:
(1)将各个分量的量纲(scale),也就是“单位”当作相同的看待了。
(2)没有考虑各个分量的分布(期望,方差等)可能是不同的。
import numpy as np
vec1 = np.array([1, 3, 4])
vec2 = np.array([4, 2, 4])
"""
ord=1: 一范数
ord=2: 二范数
ord=np.inf: 无穷范数
"""
d = np.linalg.norm(vec1-vec2, ord=arg)
在信息论中,两个等长字符串之间的汉明距离(Hamming distance)是两个字符串对应位置的不同字符的个。
计算公式
d i s t ( A , B ) = ∑ i = 0 n A [ i ] ⊕ B [ i ] dist(A,B)=\sum\limits^n\limits_{i=0}A[i]\oplus B[i] dist(A,B)=i=0∑nA[i]⊕B[i]
使用场景
当两个向量的长度不相等时,汉明距离很难使用。
import numpy as np
vec1 = np.array([1, 1, 0, 1, 0, 1, 0, 0, 1])
vec2 = np.array([0, 1, 1, 0, 0, 0, 1, 1, 1])
d = len(np.nonzero(vec1-vec2)[0])
# 或者
d = np.shape(np.nonzero(vec1-vec2)[0])[0]
余弦相似度,又称为余弦相似性,是通过计算两个向量的夹角余弦值来评估他们的相似度
计算公式
d i s t ( A , B ) = A ⋅ B ∣ A ∣ ∣ B ∣ dist(A,B)=\frac{A · B}{|A||B|} dist(A,B)=∣A∣∣B∣A⋅B
d i s t ( A , B ) = ∑ i = 1 n A i B i ∑ i = 1 n A i 2 ∑ i = 1 n B i 2 dist(A,B)=\frac{\sum\limits^n\limits_{i=1}A_iB_i}{\sqrt{\sum\limits^n\limits_{i=1}A^2_i}\sqrt{\sum\limits^n\limits_{i=1}B^2_i}} dist(A,B)=i=1∑nAi2i=1∑nBi2i=1∑nAiBi
使用场景
import numpy as np
vec1 = np.array([1, 3, 4])
vec2 = np.array([4, 2, 4])
d = np.dot(vec1,vec2)/(np.linalg.norm(vec1)*(np.linalg.norm(vec2)))
Q:余弦相似度有没有什么问题?
在推荐场景下,现有用户-物品评分矩阵,给用户推荐相似物品,没有考虑到不同用户对物品的平均打分的偏差情况。举个栗子:假如一个用户的品味很高,给每个推荐的物品打分均很低,则此用户很难与其他用户相似。
解决方法:引入偏置(皮尔逊相关系数)
计算公式
P ( A , B ) = ∑ i = 1 n ( A i − A ‾ ) ( B i − B ‾ ) ∑ i = 1 n ( A i − A ‾ ) 2 ∑ i = 1 n ( B i − B ‾ ) 2 P(A,B)=\frac{\sum\limits^n\limits_{i=1}(A_i-\overline A)(B_i-\overline B)}{\sqrt{\sum\limits^n\limits_{i=1}(A_i-\overline A)^2}\sqrt{\sum\limits^n\limits_{i=1}(B_i-\overline B)^2}} P(A,B)=i=1∑n(Ai−A)2i=1∑n(Bi−B)2i=1∑n(Ai−A)(Bi−B)
使用场景
import numpy as np
vec1 = np.array([1, 3, 4])
vec2 = np.array([4, 2, 4])
p = np.corrcoef(vec1, vec2)
P的取值在-1与1之间。取值为1时,表示两个随机变量之间呈完全正相关关系;取值为-1时,表示两个随机变量之间呈完全负相关关系;取值为0时,表示两个随机变量之间线性无关。
用于比较有限样本集之间的相似性与差异性,两个总结:数数
计算公式
J ( A , B ) = ∣ A ⋂ B ∣ ∣ A ⋃ B ∣ J(A,B)=\frac{|A\bigcap B|}{|A\bigcup B|} J(A,B)=∣A⋃B∣∣A⋂B∣
举个栗子: 假设样本 A A A 和样本 B B B 是两个 n n n 维向量,而且所有维度的取值都是 0 0 0或 1 1 1。例如, A ( 0 , 1 , 1 , 0 ) A\ (0,1,1,0) A (0,1,1,0) 和 B ( 1 , 0 , 1 , 1 ) B\ (1,0,1,1) B (1,0,1,1) 。我们将样本看成一个集合, 1 1 1表示集合包含该元素, 0 0 0表示集合不包含该元素。
p p p:样本 A A A 与 B B B 都是 1 1 1 的维度的个数
q q q:样本 A A A 是 1 1 1 而 B B B 是 0 0 0 的维度的个数
r r r:样本 A A A 是 0 0 0 而 B B B 是 1 1 1 的维度的个数
s s s:样本 A A A 与 B B B 都是 0 0 0 的维度的个数
那么样本A与B的杰卡德相似系数可以表示为:
J = p p + q + r J=\frac{p}{p+q+r} J=p+q+rp
此处分母之所以不加s的原因在于:
对于杰卡德相似系数来说,它处理的都是非对称二元变量。非对称的意思是指状态的两个输出不是同等重要的,例如,疾病检查的阳性和阴性结果。
使用场景
import numpy as np
import scipy.spatial.distance as dist
vec1 = np.array([1, 1, 0, 1, 0, 1, 0, 0, 1])
vec2 = np.array([0, 1, 1, 0, 0, 0, 1, 1, 1])
d = dist.pdist(np.array([vec1, vec2]), "jaccard")
Q:杰卡德相似度的缺点:
杰卡德相似度算法没有考虑向量中潜在数值的大小,而是简单的处理为0和1,会导致信息的损失。
本文仅作为学习记录所用,不用作商业用途,谢谢理解。
参考:https://segmentfault.com/a/1190000019307297