余弦相似度及基于python的三种代码实现、与欧氏距离的区别
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的三种代码实现、与欧氏距离的区别的更多相关文章
- 基于Redis的三种分布式爬虫策略
前言: 爬虫是偏IO型的任务,分布式爬虫的实现难度比分布式计算和分布式存储简单得多. 个人以为分布式爬虫需要考虑的点主要有以下几个: 爬虫任务的统一调度 爬虫任务的统一去重 存储问题 速度问题 足够“ ...
- 学习Python的三种境界
前言 王国维在<人间词话>中将读书分为了三种境界:"古今之成大事业.大学问者,必经过三种之境界:'昨夜西风凋碧树,独上高楼,望尽天涯路'.此第一境也.'衣带渐宽终不悔,为伊消得人 ...
- python selenium 三种等待方式详解[转]
python selenium 三种等待方式详解 引言: 当你觉得你的定位没有问题,但是却直接报了元素不可见,那你就可以考虑是不是因为程序运行太快或者页面加载太慢造成了元素不可见,那就必须要加等待 ...
- Python的三种格式化输出
今天刚学了python的三种格式化输出,以前没接触过这么有趣的输出方式,现在来分享一下. #!/user/bin/env python#coding:utf-8#三种格式化输出 #第一种格式化输出na ...
- mac学习Python第一天:安装、软件说明、运行python的三种方法
一.Python安装 从Python官网下载Python 3.x的安装程序,下载后双击运行并安装即可: Python有两个版本,一个是2.x版,一个是3.x版,这两个版本是不兼容的. MAC 系统一般 ...
- SPI、I2C、UART三种串行总线协议的区别和SPI接口介绍(转)
SPI.I2C.UART三种串行总线协议的区别 第一个区别当然是名字: SPI(Serial Peripheral Interface:串行外设接口); I2C(INTER IC BUS) UART( ...
- C++的三种继承方式详解以及区别
目录 目录 C++的三种继承方式详解以及区别 前言 一.public继承 二.protected继承 三.private继承 四.三者区别 五.总结 后话 C++的三种继承方式详解以及区别 前言 我发 ...
- Python使用三种方法实现PCA算法[转]
主成分分析(PCA) vs 多元判别式分析(MDA) PCA和MDA都是线性变换的方法,二者关系密切.在PCA中,我们寻找数据集中最大化方差的成分,在MDA中,我们对类间最大散布的方向更感兴趣. 一句 ...
- python三种导入模块的方法和区别
方法一: import modname 模块是指一个可以交互使用,或者从另一Python 程序访问的代码段.只要导入了一个模块,就可以引用它的任何公共的函数.类或属性.模块可以通过这种方法来 使用其它 ...
随机推荐
- CommonLang3 --StringUtils使用指南
转载自(http://blog.csdn.net/xuxiaoxie/article/details/52095930)public static boolean isEmpty(CharSequen ...
- [代码解析]Mask R-CNN介绍与实现(转)
文章来源 DFann 版权声明:如果你觉得写的还可以,可以考虑打赏一下.转载请联系. https://blog.csdn.net/u011974639/article/details/78483779 ...
- Docker 坑点记录
1 关于 Docker Windows 文件夹问题 C:\Users Docker Machine tries to auto-share your /Users (OS X) or C:\Users ...
- awk字符串处理
awk 字符串处理函数 awk提供了许多强大的字符串函数,见下表:awk内置字符串函数gsub(r,s) 在整个$0中用s替代rgsub(r,s,t) 在整个t中用s替代rindex(s, ...
- Memcached prepend 命令
Memcached prepend 命令用于向已存在 key(键) 的 value(数据值) 前面追加数据 . 语法: prepend 命令的基本语法格式如下: prepend key flags e ...
- pip 批量更新
1. pip3 list --outdated >> requests 现将要更新的列表写入requests 2.对文件中的数据进行处理 Package Version ...
- Spring Boot技术栈博客笔记(1)
要实现的核心功能 用户管理 安全设置 博客管理 评论管理 点赞管理 分类管理 标签管理 首页搜索 核心技术 数据存储 随着spring3发布以来,spring团队减少使用xml配置的使用,采用大量约定 ...
- Mahout 0.10.1安装(Hadoop2.6.0)及Kmeans测试
1.版本和安装路径 Ubuntu 14.04 Mahout_Home=/opt/mahout-0.10.1 Hadoop_Home=/usr/local/hadoop Mavent_Home=/opt ...
- javascript的几种使用多行字符串的方式
JS里并没有标准的多行字符串的表示方法,但是在用模板的时候,为了保证模板的可阅读性,我们又不可避免的使用多行字符串,所以出现了各种搞法,这里以一段jade的模板作为示例,简单总结和对比一下. 字符串相 ...
- CodeForces 297D Color the Carpet (脑补题)
题意 一个h*w的矩阵上面涂k种颜色,并且每行相邻格子.每列相邻格子都有=或者!=的约束.要求构造一种涂色方案使得至少有3/4的条件满足. 思路 脑补神题--自己肯定想不出来T_T-- 官方题解: 2 ...