余弦相似度 | 文本分析:基础

1、且说文本分析

我一直觉得,在数据分析领域,只有文本分析是最“接地气儿”的,“接地气儿”不是指最简单,而是我们普通大众的使用它最多。

我们每天使用互联网,但不一定每个人都炒股,不一定都做行业研究,也不一定都搞科研,因此那些高大上的模型对大部分人来说都是飘忽在天上的,只有文本分析,他的产出结果是直接惠及到几乎全部人。

比如,你总得打字,会使用到输入法的模糊匹配;你总得网购,刷新页面的时候就会看到某宝给你推荐的产品;你总得看新闻,APP会根据你以往的输入给你推荐文章......

文本分析最基本的可以看正则表达式,我曾经写过SAS和Python的相关文章:

导语:SAS正则表达式,统计师入门文本分析的捷径mp.weixin.qq.com
统计师的Python日记【第九天:正则表达式】mp.weixin.qq.com

今天这个小系列,介绍的是计算文本分析中,相似度的思想。


2、文本相似度

计算文本相似度有什么用?

  • 反垃圾文本的捞取

“诚聘淘宝兼职”、“诚聘打字员”...这样的小广告满天飞,作为网站或者APP的运营者,不可能手动将所有的广告文本放入屏蔽名单里,挑几个典型广告文本,与它满足一定相似度就进行屏蔽。

  • 推荐系统

在微博和各大BBS上,每一篇文章/帖子的下面都有一个推荐阅读,那就是根据一定算法计算出来的相似文章。

  • 冗余过滤

我们每天接触过量的信息,信息之间存在大量的重复,相似度可以帮我们删除这些重复内容,比如,大量相似新闻的过滤筛选。

这里有一个在线计算程序,你们可以感受一下

忘了说了,复制下面地址到浏览器:51tools.info/textsimila


3、余弦相似度

(1)基本思想

余弦相似度,就是用空间中两个向量的夹角,来判断这两个向量的相似程度:

  • 当两个向量夹角越大,距离越远,最大距离就是两个向量夹角180°;
  • 夹角越小,距离越近,最小距离就是两个向量夹角0°,完全重合。

借鉴这一思想,我们可以计算出两个文本的相似程度。但,我们真的要用夹角的大小去衡量吗?

文本1与文本2之间的夹角估计有37°;

文本A与文本C之间的夹角大概72.8°

相似度,个么侬就好好弄一个相似程度好伐?比如99%相似、10%相似,更关键的是,夹角这个东西——

我不会算!

谁来跟我说说两个空间向量的角度怎么计算?哪本书有?

一个更好的方法是计算夹角的余弦,对,就是那个初二学的——cos(θ)!这个不仅有公式可以算,而且结果也很有意义,是一个0-1的取值。

所以,用余弦夹角来计算两个文本的距离的步骤就是:

  • 首先,将两个文本数字化,变成两个向量;
  • 其次,计算两个向量的夹角余弦cos(θ)

余弦定理告诉我们:

不记得的翻看书本......

然而对于两个向量a、b的夹角余弦呢?

它的公式为:

分子就是2个向量的内积,分母是两个向量的模长乘积。


---------------------

用两个向量的坐标即可计算出来,简单了解一下这个推导:



---------------------


这是两个二维向量,如果是两个n维向量的夹角余弦相似度,只要记得,分子依然是向量内积,分母是两个向量模长乘积。

知道了向量的夹角余弦相似度计算方法,现在只要想办法将文本变成向量就可以了。



(2)文本的余弦相似度计算

文本是由词组成的,我们一般通过计算词频来构造文本向量——词频向量。

比如有一句话:

我是数说君,我爱你们,你们爱我吗?

这段文本是由几个词组成的:

我/ 是/ 数说君 我/ 爱/ 你们 你们/ 爱/ 我/ 吗

其中“我”出现了3次,“是”出现一次......依次计算,我们就可以构造如下词频向量:

我3, 是1, 数说君1, 爱2, 你们2, 吗1 → (3,1,1,2,2,1)

这就是一个6维向量了。

需要注意的是,如果这时候有另一段文本需要跟它比较,比如就是:

我是数说君,我爱你们,你们爱我吧?

这时候我们应该这样分词:

我3, 是1, 数说君1, 爱2, 你们2, 吗0, 吧1 → (3,1,1,2,2,0,1)

这里“吗”这个维度也需要加上,相应的,别忘了第一句话中也要加上“吧”这个维度:

我3, 是1, 数说君1, 爱2, 你们2, 吗1, 吧0 → (3,1,1,2,2,1,0)

这就是两个7维向量了,现在可以将这两个文本向量进行夹角余弦的相似度比较,带入上面的公式:

两个向量内积=3*3+1+1+2*2+2*2=19

两个向量模长乘积=sqrt(9+1+1+4+4+1)*sqrt(9+1+1+4+4+1)=20

两个向量夹角余弦相似度=19/20=95%

所以这两段文本的相似度为95%。

这里有2个问题值得提一下:

(1)当两个词频向量进行比较的时候,维度会扩大。

比如刚刚例子中,彼此没有出现的“吗”、“吧”两个维度会加进来,保证比较的两段文本维度统一。那么问题来了,如果两段很长的文本进行比较(比如上万字的文章),岂不是维度要扩增很多倍?而且矩阵会非常稀疏,就是很多取值都是0,计算开销大且效率低,怎么办?

因此需要寻求一种有效的特征降维方法,能够在不损伤核心信息的情况下降低向量空间的维数,比如TF-IDF算法。这就是后面会介绍的。

(2)英文文本的比较

与中文不同的是,英文不需要分词,因为英文天然就是由一个一个词组组成的。

I Love Shushuojun → I/ Love/ Shushuojun


更多内容,欢迎关注我的微信公众号“数说工作室”。

编辑于 2018-08-08

文章被以下专栏收录