相似度计算方法总结

2024-05-16 07:38
文章标签 总结 计算方法 相似

本文主要是介绍相似度计算方法总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

转自:http://blog.sina.com.cn/s/blog_62b83291010127bf.html


   在数据分析和数据挖掘的过程中,我们经常需要知道个体间差异的大小,进而评价个体的相似性和类别。最常见的是数据分析中的相关分析,数据挖掘中的分 类和聚类算法,如K最近邻(KNN)和K均值(K-Means)。当然衡量个体差异的方法有很多,最近查阅了相关的资料,这里整理罗列下。

  为了方便下面的解释和举例,先设定我们要比较X个体和Y个体间的差异,它们都包含了N个维的特征,即X=(x1, x2, x3, … xn),Y=(y1, y2, y3, … yn)。下面来看看主要可以用哪些方法来衡量两者的差异,主要分为距离度量和相似度度量。


距离度量

  距离度量(Distance)用于衡量个体在空间上存在的距离,距离越远说明个体间的差异越大。


欧几里得距离(Euclidean Distance)

  欧氏距离是最常见的距离度量,衡量的是多维空间中各个点之间的绝对距离。公式如下:

Euclidean Distance

  因为计算是基于各维度特征的绝对数值,所以欧氏度量需要保证各维度指标在相同的刻度级别,比如对身高(cm)和体重(kg)两个单位不同的指标使用欧式距离可能使结果失效。


明可夫斯基距离(Minkowski Distance)

  明氏距离是欧氏距离的推广,是对多个距离度量公式的概括性的表述。公式如下:

Minkowski Distance

  这里的p值是一个变量,当p=2的时候就得到了上面的欧氏距离。


曼哈顿距离(Manhattan Distance)

  曼哈顿距离来源于城市区块距离,是将多个维度上的距离进行求和后的结果,即当上面的明氏距离中p=1时得到的距离度量公式,如下:

Manhattan Distance


切比雪夫距离(Chebyshev Distance)

  切比雪夫距离起源于国际象棋中国王的走法,我们知道国际象棋国王每次只能往周围的8格中走一步,那么如果要从棋盘中A格(x1, y1)走到B格(x2, y2)最少需要走几步?扩展到多维空间,其实切比雪夫距离就是当p趋向于无穷大时的明氏距离:

Chebyshev Distance

  其实上面的曼哈顿距离、欧氏距离和切比雪夫距离都是明可夫斯基距离在特殊条件下的应用。


马哈拉诺比斯距离(Mahalanobis Distance)

  既然欧几里得距离无法忽略指标度量的差异,所以在使用欧氏距离之前需要对底层指标进行数据的标准化,而基于各指标维度进行标准化后再使用欧氏距离就衍生出来另外一个距离度量——马哈拉诺比斯距离(Mahalanobis Distance),简称马氏距离。


相似度度量

  相似度度量(Similarity),即计算个体间的相似程度,与距离度量相反,相似度度量的值越小,说明个体间相似度越小,差异越大。


向量空间余弦相似度(Cosine Similarity)

  余弦相似度用向量空间中两个向量夹角的余弦值作为衡量两个个体间差异的大小。相比距离度量,余弦相似度更加注重两个向量在方向上的差异,而非距离或长度上。公式如下:

Cosine Similarity


皮尔森相关系数(Pearson Correlation Coefficient)

  即相关分析中的相关系数r,分别对X和Y基于自身总体标准化后计算空间向量的余弦夹角。公式如下:

Pearson Correlation Coefficient


Jaccard相似系数(Jaccard Coefficient)

  Jaccard系数主要用于计算符号度量或布尔值度量的个体间的相似度,因为个体的特征属性都是由符号度量或者布尔值标识,因此无法衡量差异具 体值的大小,只能获得“是否相同”这个结果,所以Jaccard系数只关心个体间共同具有的特征是否一致这个问题。如果比较X与Y的Jaccard相似系 数,只比较xn和yn中相同的个数,公式如下:

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,相似度为负值并且差异 不小,但显然更加符合现实。


欧氏距离与余弦相似度

  欧氏距离是最常见的距离度量,而余弦相似度则是最常见的相似度度量,很多的距离度量和相似度度量都是基于这两者的变形和衍生,所以下面重点比较下两者在衡量个体差异时实现方式和应用环境上的区别。

  借助三维坐标系来看下欧氏距离和余弦相似度的区别:

distance and similarity

  从图上可以看出距离度量衡量的是空间各点间的绝对距离,跟各个点所在的位置坐标(即个体特征维度的数值)直接相关;而余弦相似度衡量的是空间向 量的夹角,更加的是体现在方向上的差异,而不是位置。如果保持A点的位置不变,B点朝原方向远离坐标轴原点,那么这个时候余弦相似度cosθ是保持不变 的,因为夹角不变,而A、B两点的距离显然在发生改变,这就是欧氏距离和余弦相似度的不同之处。


  根据欧氏距离和余弦相似度各自的计算方式和衡量特征,分别适用于不同的数据分析模型:欧氏距离能够体现个体数值特征的绝对差异,所以更多的用于 需要从维度的数值大小中体现差异的分析,如使用用户行为指标分析用户价值的相似度或差异;而余弦相似度更多的是从方向上区分差异,而对绝对的数值不敏感, 更多的用于使用用户对内容评分来区分用户兴趣的相似度和差异,同时修正了用户间可能存在的度量标准不统一的问题(因为余弦相似度对绝对数值不敏感)。


  上面都是对距离度量和相似度度量的一些整理和汇总,在现实的使用中选择合适的距离度量或相似度度量可以完成很多的数据分析和数据挖掘的建模,后续会有相关的介绍。

附件为python部分相似度算法:

#!/usr/bin/python
#coding=utf-8
critics = {
       'Lisa':{
               'Lady in the water':2.5,
               'Snake on a plane' :3.5
       },
       'Tom':{
               'Lady in the water':3.0,
               'Snake on a plane' :4.0
       },
       'Jerry':{
               'Lady in the water':2.0,
               'Snake on a plane' :3.0
       },
       'WXM':{
               'Lady in the water':3.3,
               'Snake on a plane' :4.2
       },
       'jhz':{
               'Lady in the water':3.9,
               'Snake on a plane' :4.5
       }
}

from math import sqrt
"""
欧几里得空间法 计算相似度
"""
def sim_distance(p1, p2):
       c = set(p1.keys())&set(p2.keys())
       if not c:
               return 0
       sum_of_squares = sum([pow(p1.get(sk)-p2.get(sk),2) for sk in c])
       p = 1/(1+sqrt(sum_of_squares))
       return p
 
"""
皮尔逊相关度
"""
def sim_distance_pearson(p1,p2):
       c = set(p1.keys())&set(p2.keys())
       if not c:
               return 0
       s1 = sum([p1.get(sk) for sk in c])
       s2 = sum([p2.get(sk) for sk in c])
       sq1 = sum([pow(p1.get(sk),2) for sk in c])
       sq2 = sum([pow(p2.get(sk),2) for sk in c])
       ss = sum([p1.get(sk)*p2.get(sk) for sk in c])
       n = len(c)
       num = ss-s1*s2/n
       den = sqrt((sq1-pow(s1,2)/n)*(sq2-pow(s2-2)/n))
       if den == 0:
               return 0
       p = num/den
       return p
 
"""
Jaccard系数
"""
def sim_distance_jaccard(p1,p2):
       c = set(p1.keys())&set(p2.keys())
       if not c:
               return 0
       ss = sum([p1.get(sk)*p2.get(sk) for sk in c])
       sq1 = sum([pow(sk,2) for sk in p1.values()])
       sq2 = sum([pow(sk,2) for sk in p2.values()])
       p = float(ss)/(sq1+sq2-ss)
       return p
 
"""
余弦相似度
"""
def sim_distance_cos(p1,p2):
       c = set(p1.keys())&set(p2.keys())
       if not c:
               return 0
       ss = sum([p1.get(sk)*p2.get(sk) for sk in c])
       sq1 = sqrt(sum([pow(p1.get(sk),2) for sk in p1.values()]))
       sq2 = sqrt(sum([pow(p2.get(sk),2) for sk in p2.values()]))
       p = float(ss)/(sq1*sq2)
       return p

"""
得到top相似度高的前几位
"""
def topMatches(prefs,person,n=5,similarity=sim_distance_pearson):
       scores = [similarity(prefs,person,other) for other in prefs if other != person]
       scores.sort()
       scores.reverse()
       return scores[0:n]

"""
#利用所有他人评价值加权平均,为某人提供建议.
"""
def getRecommendations(prefs, person, similarity=sim_distance):
       totals = {}
       simSums = {}
 
       for other in prefs:
               if other == person: continue
               sim = similarity(prefs,person,other)
               #忽略评价值为0或小于0的情况.
               if sim<=0: continue
               for item in prefs[other]:
                       #只对自己还未曾看过的影片进行评价.
                       if item not in prefs[person] or prefs[person][item] == 0 :
                             totals.setdefault(item, 0)
                             totals[item] += sim*prefs[other][item]
                             #相似度之和
                             simSums.setdefault(item, 0)
                             simSums[item] += sim
               #建立一个归一化的列表.
               rankings = [(total/simSums[item],item) \
                                       for item,total in totals.items()]
               rankings.sort()
               rankings.reverse()
               return rankings

参考文献:

[1]http://webdataanalysis.net/reference-and-source/distance-and-similarity/
[2]http://wpxiaomo.sinaapp.com/archives/424
[3]http://wpxiaomo.sinaapp.com/archives/423
[4]集体智慧编程

这篇关于相似度计算方法总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/994283

相关文章

关于C++中的虚拟继承的一些总结(虚拟继承,覆盖,派生,隐藏)

1.为什么要引入虚拟继承 虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。如:类D继承自类B1、B2,而类B1、B2都继承自类A,因此在类D中两次出现类A中的变量和函数。为了节省内存空间,可以将B1、B2对A的继承定义为虚拟继承,而A就成了虚拟基类。实现的代码如下: class A class B1:public virtual A; class B2:pu

十五.各设计模式总结与对比

1.各设计模式总结与对比 1.1.课程目标 1、 简要分析GoF 23种设计模式和设计原则,做整体认知。 2、 剖析Spirng的编程思想,启发思维,为之后深入学习Spring做铺垫。 3、 了解各设计模式之间的关联,解决设计模式混淆的问题。 1.2.内容定位 1、 掌握设计模式的"道" ,而不只是"术" 2、 道可道非常道,滴水石穿非一日之功,做好长期修炼的准备。 3、 不要为了

人工智能机器学习算法总结神经网络算法(前向及反向传播)

1.定义,意义和优缺点 定义: 神经网络算法是一种模仿人类大脑神经元之间连接方式的机器学习算法。通过多层神经元的组合和激活函数的非线性转换,神经网络能够学习数据的特征和模式,实现对复杂数据的建模和预测。(我们可以借助人类的神经元模型来更好的帮助我们理解该算法的本质,不过这里需要说明的是,虽然名字是神经网络,并且结构等等也是借鉴了神经网络,但其原型以及算法本质上还和生物层面的神经网络运行原理存在

Java注解详细总结

什么是注解?         Java注解是代码中的特殊标记,比如@Override、@Test等,作用是:让其他程序根据注解信息决定怎么执行该程序。         注解不光可以用在方法上,还可以用在类上、变量上、构造器上等位置。 自定义注解  现在我们自定义一个MyTest注解 public @interface MyTest{String aaa();boolean bbb()

tensorboard-----summary用法总结

Tensorflow学习笔记——Summary用法         最近在研究tensorflow自带的例程speech_command,顺便学习tensorflow的一些基本用法。 其中tensorboard 作为一款可视化神器,可以说是学习tensorflow时模型训练以及参数可视化的法宝。 而在训练过程中,主要用到了tf.summary()的各类方法,能够保存训练过程以及参数分布图并在

七种排序方式总结

/*2018.01.23*A:YUAN*T:其中排序算法:冒泡排序,简单排序,直接插入排序,希尔排序,堆排序,归并排序,快速排序*/#include <stdio.h>#include <math.h>#include <malloc.h>#define MAXSIZE 10000#define FALSE 0#define TRUE 1typedef struct {i

Java实现MD5加密总结

Java实现MD5加密总结 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 1. 什么是MD5加密 MD5是一种常用的哈希算法,用于将任意长度的数据通过哈希运算转换为固定长度的数据串,通常为128位的二进制串,常用于对密码等敏感信息进行加密存储或传输。 2. Java实现MD5加密的方法 2.1 使用java.sec

Linux通配符总结

Linux通配符总结 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 在Linux系统中,通配符是一种用于匹配文件名或路径名的特殊字符。通过使用通配符,可以方便地匹配多个文件或目录,从而进行文件操作或查找。 2. 常用的通配符 在Linux系统中,常用的通配符包括以下几种: *:匹配任意长度的任意字符。?:匹配任意单个字符

【Linux文件系统】被打开的文件与文件系统的文件之间的关联刨析总结

操作系统管理物理内存以及与外设磁盘硬件进行数据的交换 操作系统如何管理物理内存呢? 其实操作系统内核先对内存先描述再组织的!操作系统管理内存的基本单位是4KB,操作系统会为每一个4KB大小的物理内存块创建一个描述该4KB内存块的struct page结构体,该结构体存储着这4KB内存块的属性信息,通过管理struct page来对内存进行管理,page结构体的大小比较小,OS通常将它们组成一个

Java反射详细总结

什么是反射?         反射,指的是加载类的字节码到内存,并以编程的方法解刨出类中的各个成分(成员变量、方法、构造器等)。         反射获取的是类的信息,那么反射的第一步首先获取到类才行。由于Java的设计原则是万物皆对象,获取到的类其实也是以对象的形式体现的,叫字节码对象,用Class类来表示。获取到字节码对象之后,再通过字节码对象就可以获取到类的组成成分了,这些组成成分其实也