1.余弦相似度可用来计算两个向量的相似程度

对于如何计算两个向量的相似程度问题,可以把这它们想象成空间中的两条线段,都是从原点([0, 0, ...])出发,指向不同的方向。两条线段之间形成一个夹角,如果夹角为0度,意味着方向相同、线段重合;如果夹角为90度,意味着形成直角,方向完全不相似;如果夹角为180度,意味着方向正好相反。因此,我们可以通过夹角的大小,来判断向量的相似程度。夹角越小,就代表越相似。

以二维空间为例,上图的a和b是两个向量,我们要计算它们的夹角θ。余弦定理告诉我们,可以用下面的公式求得:

假定a向量是[x1, y1],b向量是[x2, y2],那么可以将余弦定理改写成下面的形式:

余弦的这种计算方法对n维向量也成立。假定A和B是两个n维向量,A是 [A1, A2, ..., An] ,B是 [B1, B2, ..., Bn] ,则A与B的夹角θ的余弦等于:

余弦值越接近1,就表明夹角越接近0度,也就是两个向量越相似,这就叫"余弦相似性"

余弦值的范围在[-1,1]之间,值越趋近于1,代表两个向量的方向越接近;越趋近于-1,他们的方向越相反;接近于0,表示两个向量近乎于正交。

特殊情况分析:

(1)夹角为0度 :此时向量A与向量B应该是最相似的,余弦相似度应该为1。按照公式(4),我们计算很容易计算出来cosθ=1。

(2)夹角为90度 :此时余弦相似度为0。

(3)夹角为180度 :此时余弦相似度为-1,两个向量的方向完全相反。

一般情况下,相似度都是归一化到[0,1]区间内,因此余弦相似度表示为 cosineSIM = 0.5cosθ + 0.5

2. 余弦相似度的python实现

import numpy as np

def bit_product_sum(x, y):
return sum([item[0] * item[1] for item in zip(x, y)]) def cosine_similarity(x, y, norm=False):
""" 计算两个向量x和y的余弦相似度 """
assert len(x) == len(y), "len(x) != len(y)"
zero_list = [0] * len(x)
if x == zero_list or y == zero_list:
return float(1) if x == y else float(0) # method 1
res = np.array([[x[i] * y[i], x[i] * x[i], y[i] * y[i]] for i in range(len(x))])
cos = sum(res[:, 0]) / (np.sqrt(sum(res[:, 1])) * np.sqrt(sum(res[:, 2]))) # method 2
# cos = bit_product_sum(x, y) / (np.sqrt(bit_product_sum(x, x)) * np.sqrt(bit_product_sum(y, y))) # method 3
# dot_product, square_sum_x, square_sum_y = 0, 0, 0
# for i in range(len(x)):
# dot_product += x[i] * y[i]
# square_sum_x += x[i] * x[i]
# square_sum_y += y[i] * y[i]
# cos = dot_product / (np.sqrt(square_sum_x) * np.sqrt(square_sum_y)) return 0.5 * cos + 0.5 if norm else cos # 归一化到[0, 1]区间内 if __name__ == '__main__':
print cosine_similarity([0, 0], [0, 0]) # 1.0
print cosine_similarity([1, 1], [0, 0]) # 0.0
print cosine_similarity([1, 1], [-1, -1]) # -1.0
print cosine_similarity([1, 1], [2, 2]) # 1.0
print cosine_similarity([3, 3], [4, 4]) # 1.0
print cosine_similarity([1, 2, 2, 1, 1, 1, 0], [1, 2, 2, 1, 1, 2, 1]) # 0.938194187433

 

3. 余弦相识度 vs 欧氏距离

余弦距离使用两个向量夹角的余弦值作为衡量两个个体间差异的大小。相比欧氏距离,余弦距离更加注重两个向量在方向上的差异

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

从上图可以看出,欧氏距离衡量的是空间各点的绝对距离,跟各个点所在的位置坐标直接相关而余弦距离衡量的是空间向量的夹角,更加体现在方向上的差异,而不是位置

如果保持A点位置不变,B点朝原方向远离坐标轴原点,那么这个时候余弦距离是保持不变的(因为夹角没有发生变化),而A、B两点的距离显然在发生改变,这就是欧氏距离和余弦距离之间的不同之处。

欧氏距离和余弦距离各自有不同的计算方式和衡量特征,因此它们适用于不同的数据分析模型:

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

正因为余弦相似度在数值上的不敏感,会导致这样一种情况存在:

用户对内容评分,按5分制,X和Y两个用户对两个内容的评分分别为(1,2)和(4,5),使用余弦相似度得到的结果是0.98,两者极为相似。但从评分上看X似乎不喜欢2这个 内容,而Y则比较喜欢,余弦相似度对数值的不敏感导致了结果的误差,需要修正这种不合理性就出现了调整余弦相似度,即所有维度上的数值都减去一个均值,比如X和Y的评分均值都是3,那么调整后为(-2,-1)和(1,2),再用余弦相似度计算,得到-0.8,相似度为负值并且差异不小,但显然更加符合现实。 那么是否可以在(用户-商品-行为数值)矩阵的基础上使用调整余弦相似度计算呢?从算法原理分析,复杂度虽然增加了,但是应该比普通余弦夹角算法要强。

4. 在计算文本相似度上基本流程

  (1)使用TF-IDF算法,找出两篇文章的关键词;

  (2)每篇文章各取出若干个关键词(比如20个),合并成一个集合,计算每篇文章对于这个集合中的词的词频(为了避免文章长度的差异,可以使用相对词频);

  (3)生成两篇文章各自的词频向量;

  (4)计算两个向量的余弦相似度,值越大就表示越相似。

参考:

http://www.ruanyifeng.com/blog/2013/03/cosine_similarity.html

https://www.cnblogs.com/guoxueyuan/p/7779239.html

http://blog.csdn.net/zz_dd_yy/article/details/51926305

https://www.cnblogs.com/wxiaoli/p/6940702.html

http://blog.csdn.net/jediael_lu/article/details/77863419

余弦相似度及基于python的三种代码实现、与欧氏距离的区别的更多相关文章

  1. 基于Redis的三种分布式爬虫策略

    前言: 爬虫是偏IO型的任务,分布式爬虫的实现难度比分布式计算和分布式存储简单得多. 个人以为分布式爬虫需要考虑的点主要有以下几个: 爬虫任务的统一调度 爬虫任务的统一去重 存储问题 速度问题 足够“ ...

  2. 学习Python的三种境界

    前言 王国维在<人间词话>中将读书分为了三种境界:"古今之成大事业.大学问者,必经过三种之境界:'昨夜西风凋碧树,独上高楼,望尽天涯路'.此第一境也.'衣带渐宽终不悔,为伊消得人 ...

  3. python selenium 三种等待方式详解[转]

    python selenium 三种等待方式详解   引言: 当你觉得你的定位没有问题,但是却直接报了元素不可见,那你就可以考虑是不是因为程序运行太快或者页面加载太慢造成了元素不可见,那就必须要加等待 ...

  4. Python的三种格式化输出

    今天刚学了python的三种格式化输出,以前没接触过这么有趣的输出方式,现在来分享一下. #!/user/bin/env python#coding:utf-8#三种格式化输出 #第一种格式化输出na ...

  5. mac学习Python第一天:安装、软件说明、运行python的三种方法

    一.Python安装 从Python官网下载Python 3.x的安装程序,下载后双击运行并安装即可: Python有两个版本,一个是2.x版,一个是3.x版,这两个版本是不兼容的. MAC 系统一般 ...

  6. SPI、I2C、UART三种串行总线协议的区别和SPI接口介绍(转)

    SPI.I2C.UART三种串行总线协议的区别 第一个区别当然是名字: SPI(Serial Peripheral Interface:串行外设接口); I2C(INTER IC BUS) UART( ...

  7. C++的三种继承方式详解以及区别

    目录 目录 C++的三种继承方式详解以及区别 前言 一.public继承 二.protected继承 三.private继承 四.三者区别 五.总结 后话 C++的三种继承方式详解以及区别 前言 我发 ...

  8. Python使用三种方法实现PCA算法[转]

    主成分分析(PCA) vs 多元判别式分析(MDA) PCA和MDA都是线性变换的方法,二者关系密切.在PCA中,我们寻找数据集中最大化方差的成分,在MDA中,我们对类间最大散布的方向更感兴趣. 一句 ...

  9. python三种导入模块的方法和区别

    方法一: import modname 模块是指一个可以交互使用,或者从另一Python 程序访问的代码段.只要导入了一个模块,就可以引用它的任何公共的函数.类或属性.模块可以通过这种方法来 使用其它 ...

随机推荐

  1. T-shirt again

    T-shirt again 标签(空格分隔): 软工实践 第一次获得小黄裳是在大一下的C++课上,见T-shirt 0.0... 这次在软工课上能再次获得小黄裳,是我没有想到的,个人觉得里面有蛮多的运 ...

  2. 比较字符串CompareTo的用法及注意

    CompareTo用法 static void Main(string[] args)         {             string str = "1";        ...

  3. params

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Ch06 ...

  4. 源码安装GCC-4.9.2

    本文参考:http://cuchadanfan.blog.51cto.com/9940284/1689556  感谢原作者的分享! 首先安装基础包,安装网络依赖的时候要用 [root@localhos ...

  5. 5.scala中的对象

    排版乱?请移步原文获得更好的阅读体验 1.单例对象 scala中没有静态类或者静态方法,都是通过object实现的,它表示某个类的单例对象.如object People是class People的单例 ...

  6. 2017ACM/ICPC广西邀请赛-重现赛1005 CS course

    2017-08-31 16:19:30 writer:pprp 这道题快要卡死我了,队友已经告诉我思路了,但是做题速度很缓慢,很费力,想必是因为之前 的训练都是面向题解编程的缘故吧,以后不能这样了,另 ...

  7. Math.Round 四舍五入问题 解惑 !

    前言: 一定要说 坑爹的微软! 坑爹的微软! 坑爹的微软!  重要的事情说 三遍 ! 摘录 SMDN 示例 下面的示例演示就近舍入. C# C++ VB   Math.Round(3.44, 1); ...

  8. ThinkPHP开发笔记-前后端数据交互

    此处就是 Controller 和 View 相互传数据. 1.Controller 向 View 的页面传数据.在控制器中把变量传递给模板,使用 assign 方法对模板变量赋值.例如: 在Cont ...

  9. SpringBoot学习(2)

    三.日志 1.日志框架 springboot:底层是spring框架,spring框架默认使用JCL; springboot选用SLF4j和logback; 2.SLF4j使用 1.如何在系统中使用S ...

  10. jquery 表格自动拆分(方便打印)插件-printTable

    /** * jquery 表格打印插件 * * 作者: LiuJunGuang * 日期:2013年6月4日 * 分页样式(需要自定义): * @media print { * .pageBreak ...