常见的相似度计算方式
1.欧氏距离(Euclidean Distance)
欧氏距离(也称欧几里得度量)指在mmm维空间中两个点之间的真实距离,或者向量的自然长度(即该点到原点的距离)。 在二维和三维空间中的欧氏距离就是两点之间的实际距离。
计算公式:
dist(A,B)=∑i=1n(Ai−Bi)2dist(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 npvec1 = 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)))
2.曼哈顿距离(Manhattan Distance)
在欧几里得空间的固定直角坐标系上两点所形成的线段对轴产生的投影的距离总和。
计算公式
dist(A,B)=∑i=1n∣Ai−Bi∣dist(A,B)=\\sum\\limits^n\\limits_{i=1}|A_i-B_i| dist(A,B)=i=1∑n∣Ai−Bi∣
使用场景
- 在数据完整(无维度数据缺失)的情况下, 需要将空间划分成网格, 然后以网格为单位来进行度量, 允许4个方向
import numpy as npvec1 = 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))
3.切比雪夫距离(Chebyshev Distance)
切比雪夫距离(Chebyshev distance)是向量空间中的一种度量,二个点之间的距离定义为其各坐标数值差的最大值 。 此距离中,加入了优化的成分,通过最值来定义距离。
计算公式
dist(A,B)=maxi∣Ai−Bi∣dist(A,B)=\\max\\limits_i|A_i-B_i| dist(A,B)=imax∣Ai−Bi∣
dist(A,B)=limp→∞(∑i=1n∣Ai−Bi∣p)1pdist(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
使用场景
- 需要将空间划分成网格, 然后以网格为单位来进行度量, 允许8个方向
import numpy as npvec1 = 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()
4.闵可夫斯基距离(Minkowski Distance)
闵氏距离不是一种距离,而是一组距离的定义。
计算公式
dist(A,B)=p∑i=1n∣Ai−Bi∣pdist(A,B)=p\\sqrt{\\sum\\limits^n\\limits_{i=1}|A_i-B_i|^p} dist(A,B)=pi=1∑n∣Ai−Bi∣p
使用场景
- 当 p=1p=1p=1 时,就是曼哈顿距离
- 当 p=2p=2p=2 时,就是欧氏距离
- 当 p→∞p→∞p→∞ 时,就是切比雪夫距离
闵氏距离的缺点主要有两个:
(1)将各个分量的量纲(scale),也就是“单位”当作相同的看待了。
(2)没有考虑各个分量的分布(期望,方差等)可能是不同的。
import numpy as npvec1 = 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)
5.汉明距离(Hamming Distance)
在信息论中,两个等长字符串之间的汉明距离(Hamming distance)是两个字符串对应位置的不同字符的个。
)]
计算公式
dist(A,B)=∑i=0nA[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 npvec1 = 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]
6.余弦相似度(Cosine Similarity)
余弦相似度,又称为余弦相似性,是通过计算两个向量的夹角余弦值来评估他们的相似度
计算公式
dist(A,B)=A⋅B∣A∣∣B∣dist(A,B)=\\frac{A · B}{|A||B|} dist(A,B)=∣A∣∣B∣A⋅B
dist(A,B)=∑i=1nAiBi∑i=1nAi2∑i=1nBi2dist(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 npvec1 = 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:余弦相似度有没有什么问题?
在推荐场景下,现有用户-物品评分矩阵,给用户推荐相似物品,没有考虑到不同用户对物品的平均打分的偏差情况。举个栗子:假如一个用户的品味很高,给每个推荐的物品打分均很低,则此用户很难与其他用户相似。
解决方法:引入偏置(皮尔逊相关系数)
7.皮尔森相关系数(Pearson Correlation Coefficient)
用于度量两个变量之间的相关程度
计算公式
P(A,B)=∑i=1n(Ai−A‾)(Bi−B‾)∑i=1n(Ai−A‾)2∑i=1n(Bi−B‾)2P(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 npvec1 = np.array([1, 3, 4])
vec2 = np.array([4, 2, 4])p = np.corrcoef(vec1, vec2)
P的取值在-1与1之间。取值为1时,表示两个随机变量之间呈完全正相关关系;取值为-1时,表示两个随机变量之间呈完全负相关关系;取值为0时,表示两个随机变量之间线性无关。
8.杰卡德相似系数(Jaccard Similarity Coefficient)
用于比较有限样本集之间的相似性与差异性,两个总结:数数
计算公式
J(A,B)=∣A⋂B∣∣A⋃B∣J(A,B)=\\frac{|A\\bigcap B|}{|A\\bigcup B|} J(A,B)=∣A⋃B∣∣A⋂B∣
举个栗子: 假设样本 AAA 和样本 BBB 是两个 nnn 维向量,而且所有维度的取值都是 000或 111。例如,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) 。我们将样本看成一个集合,111表示集合包含该元素,000表示集合不包含该元素。
ppp:样本 AAA 与 BBB 都是 111 的维度的个数
qqq:样本 AAA 是 111 而 BBB 是 000 的维度的个数
rrr:样本 AAA 是 000 而 BBB 是 111 的维度的个数
sss:样本 AAA 与 BBB 都是 000 的维度的个数
那么样本A与B的杰卡德相似系数可以表示为:
J=pp+q+rJ=\\frac{p}{p+q+r} J=p+q+rp
此处分母之所以不加s的原因在于:
对于杰卡德相似系数来说,它处理的都是非对称二元变量。非对称的意思是指状态的两个输出不是同等重要的,例如,疾病检查的阳性和阴性结果。
使用场景
- 比较文本相似度,用于文本查重与去重;
- 计算对象间距离,用于数据聚类或衡量两个集合的区分度等。
import numpy as np
import scipy.spatial.distance as distvec1 = 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