参考自:
欧氏距离与余弦相似度
欧氏距离和余弦相似度
在数据分析和数据挖掘的过程中,我们经常需要知道个体间差异的大小,进而评价个体的相似性和类别。最常见的是数据分析中的相关分析,数据挖掘中的分类和聚类算法,如K最近邻(KNN)和K均值(K-Means)。
来衡量两者的差异的方法,主要分为距离度量和相似度度量。
距离度量
距离度量(Distance)用于衡量个体在空间上存在的距离,距离越远说明个体间的差异越大。
欧几里得距离(Euclidean Distance)
欧氏距离是最常见的距离度量,衡量的是多维空间中各个点之间的绝对距离。公式如下:
因为计算是基于各维度特征的绝对数值,所以欧氏度量需要保证各维度指标在相同的刻度级别,比如对身高(cm)和体重(kg)两个单位不同的指标使用欧式距离可能使结果失效。
其他距离度量还有:明可夫斯基距离(Minkowski Distance)、曼哈顿距离(Manhattan Distance)、切比雪夫距离(Chebyshev Distance)、马哈拉诺比斯距离(Mahalanobis Distance)等。
相似度度量
相似度度量(Similarity),即计算个体间的相似程度,与距离度量相反,相似度度量的值越小,说明个体间相似度越小,差异越大。
向量空间余弦相似度(Cosine Similarity)
余弦相似度用向量空间中两个向量夹角的余弦值作为衡量两个个体间差异的大小。相比距离度量,余弦相似度更加注重两个向量在方向上的差异,而非距离或长度上。公式如下:
或
其他相似度度量还有:皮尔森相关系数(Pearson Correlation Coefficient)、Jaccard相似系数(Jaccard Coefficient)等。
调整余弦相似度(Adjusted Cosine Similarity)
虽然余弦相似度对个体间存在的偏见可以进行一定的修正,但是因为只能分辨个体在维之间的差异,没法衡量每个维数值的差异,会导致这样一个情况:比如用户对内容评分,5分制,X和Y两个用户对两个内容的评分分别为(1,2)和(4,5),使用余弦相似度得出的结果是0.98,两者极为相似,但从评分上看X似乎不喜欢这2个内容,而Y比较喜欢,余弦相似度对数值的不敏感导致了结果的误差,需要修正这种不合理性,就出现了调整余弦相似度,即所有维度上的数值都减去一个均值,比如X和Y的评分均值都是3,那么调整后为(-2,-1)和(1,2),再用余弦相似度计算,得到-0.8,相似度为负值并且差异不小,但显然更加符合现实。
欧氏距离和余弦相似度
欧氏距离是最常见的距离度量,而余弦相似度则是最常见的相似度度量,很多的距离度量和相似度度量都是基于这两者的变形和衍生,所以下面重点比较下两者在衡量个体差异时实现方式和应用环境上的区别。
两者相同的地方,就是在机器学习中都可以用来计算相似度,但是两者的含义有很大差别,以我的理解就是:
前者是看成坐标系中两个点,来计算两点之间的距离;
后者是看成坐标系中两个向量,来计算两向量之间的夹角。
前者因为是点,所以一般指位置上的差别,即距离;
后者因为是向量,所以一般指方向上的差别,即所成夹角。
从图上可以看出距离度量衡量的是空间各点间的绝对距离,跟各个点所在的位置坐标(即个体特征维度的数值)直接相关;而余弦相似度衡量的是空间向量的夹角,更加的是体现在方向上的差异,而不是位置。如果保持A点的位置不变,B点朝原方向远离坐标轴原点,那么这个时候余弦相似度cosθ是保持不变的,因为夹角不变,而A、B两点的距离显然在发生改变,这就是欧氏距离和余弦相似度的不同之处。
根据欧氏距离和余弦相似度各自的计算方式和衡量特征,分别适用于不同的数据分析模型:欧氏距离能够体现个体数值特征的绝对差异,所以更多的用于需要从维度的数值大小中体现差异的分析,如使用用户行为指标分析用户价值的相似度或差异;而余弦相似度更多的是从方向上区分差异,而对绝对的数值不敏感,更多的用于使用用户对内容评分来区分用户兴趣的相似度和差异,同时修正了用户间可能存在的度量标准不统一的问题(因为余弦相似度对绝对数值不敏感)。
计算
假设||A||、||B||表示向量A、B的2范数,例如向量[1,2,3]的2范数为:
√(1²+2²+3²) = √14
numpy中提供了范数的计算工具:linalg.norm()
所以计算cosθ起来非常方便(假定A、B均为列向量):
num = float(A.T * B) #若为行向量则 A * B.T
denom = linalg.norm(A) * linalg.norm(B)
cos = num / denom #余弦值
sim = 0.5 + 0.5 * cos #归一化
因为有了linalg.norm(),欧氏距离公式实现起来更为方便:
dist = linalg.norm(A - B)
sim = 1.0 / (1.0 + dist) #归一化
关于归一化:
因为余弦值的范围是 [-1,+1] ,相似度计算时一般需要把值归一化到 [0,1],一般通过如下方式:
sim = 0.5 + 0.5 * cosθ
若在欧氏距离公式中,取值范围会很大,一般通过如下方式归一化:
sim = 1 / (1 + dist(X,Y))