20-余弦相似度及其R实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20-余弦相似度及其R实现相关的知识,希望对你有一定的参考价值。

参考技术A

余弦相似度 (Cosine Similarity) 通过计算两个向量的夹角余弦值来评估他们的相似度。将向量根据坐标值,绘制到向量空间中,求得他们的夹角,并得出夹角对应的余弦值,此余弦值就可以用来表征这两个向量的相似性。夹角越小,余弦值越接近于1,它们的方向越吻合,则越相似。

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

在文本处理中,要使用余弦相似度算法,首先得将文本向量化,将词用“词向量”的方式表示可谓是将 Deep Learning 算法引入 NLP 领域的一个核心技术。自然语言处理转化为机器学习问题的第一步都是通过一种方法将这些文本数学化。其思路如下:

举例:
句子A:这只皮靴号码大了。那只号码合适。
句子B:这只皮靴号码不小,那只更合适。

1、中文分词:
使用结巴分词对上面两个句子分词后,分别得到两个词集:

2、列出所有词,将listA和listB放在一个set中,构成词包:

3、使用词集分别对listA和listB计算词频。

4、对listA和listB进行oneHot编码后得到的结果如下:
listAcode = [1, 2, 1, 2, 1, 1, 1, 1, 0, 0]
listBcode = [1, 2, 1, 1, 0, 0, 1, 1, 1, 1]
5、得出两个句子的词频向量之后,就变成了计算两个向量之间夹角的余弦值,值越大相似度越高。

6、两个向量的余弦值为0.805823,接近1,说明两句话相似度很高。

两个句子的相似度计算步骤如下:
1.通过中文分词,把完整的句子分成独立的词集合;
2.求出两个词集合的并集(词包);
3.计算各自词集的词频并将词频向量化;
4.代入余弦公式就可以求出文本相似度。
注意,词包确定之后,词的顺序是不能再修改的,不然会影响到向量的变化。

以上是对两个句子做相似度计算,如果是对两篇文章做相似度计算,步骤如下:
1.找出各自文章的关键词并合成一个词集合;
2.求出两个词集合的并集(词包);
3.计算各自词集的词频并将词频向量化;
4.代入余弦公式就可以求出文本相似度。
句子的相似度计算只是文章相似度计算的一个子部分。文章的关键词提取可以通过其他的算法来实现。

词频TF(Term Frequency),是一个词语在文章或句子中出现的次数。要在一篇很长的文章中寻找关键字(词),就一般的理解,一个词对文章越关键在文章中出现的次数就越多,于是我们就采用“词频”进行统计。

但是这也不是绝对的,比如“地”,“的”,“啊”等词,它们出现的次数对一篇文章的中心思想是没有帮助的,只是中文语法结构的一部分而已。这类词也被称为“停用词”,所以,在计算一篇文章的词频时,停用词是应该过滤掉的。

仅仅过滤掉停用词就能解决问题吗?也不一定。比如分析政府工作报告,“中国”这个词语必定在每篇文章中都出现很多次,但是对于每份报告的主干思想有帮助吗?对比“反腐败”、“人工智能”、“大数据”、“物联网”等词语,“中国”这个词语在文章中应该是次要的。

TF算法的优点是简单快速,结果比较符合实际情况。缺点是单纯以“词频”做衡量标准,不够全面,词性和词的出现位置等因素没有考虑到,而且有时重要的词可能出现的次数并不多。这种算法无法体现词的位置信息,位置靠前的词与位置靠后的词,都被视为重要性相同,这是不科学的。

联系到层次分析法的思想,可以赋予每个词特定的权重,给那类最常见的词赋予较小的权重,相应的较少见的词赋予较大的权重,这个权重叫做“逆文档频率”(Inverse Doucument Frequency,缩写为IDF),它的大小与一个词的常见程度成反比。而TF-IDF值就是将词频TF和逆文档频率IDF相乘,值越大,说明该词对文章的重要性越高。这就是TF-IDF算法。

R tm 包余弦相似度

【中文标题】R tm 包余弦相似度【英文标题】:R tm package cosine similary 【发布时间】:2019-08-06 16:04:14 【问题描述】:

我正在尝试使用 R tm 包来解决字符串比较问题(单字字符串,而不是多字文本)。 我已经使用了 Levenshtein 距离,它可以在这些方面给我一个有意义的结果,但我并不完全满意。 在阅读了一篇我觉得有趣的文章后,我现在正在尝试使用余弦相似度。

我研究了文档,也阅读了一些文章,但在这个时间点上,我想我还没有理解算法的能力。

当我将术语作为单词时,我可以使用它。

例如

docs <- c ("open letters", "closed letters", "letters)
terms <- "open", "closed", "letters")

但我无法要求系统处理每一个字母 c ("a", "b", "c", "d")

这将导致使用术语文档矩阵进行字符串比较。 但也许我的错误已经存在。

在 tm 中实现单个单词字符串比较会是什么?

感谢您的帮助, 附:我没有发布代码,因为这是一个更普遍的问题,但我可以创建一个示例以防万一。

尼古拉

这是根据建议的工作代码:

doc <- c( "closed door", "Open door", "door", "doo", "oor", "house" )
doc_corpus <- Corpus( VectorSource(doc) )
control_list <- list(removePunctuation = TRUE, tolower = TRUE)
tdm <- DocumentTermMatrix(doc_corpus,  control = character_tokenize(doc))
tf <- as.matrix(tdm)

【问题讨论】:

请分享一些示例数据。这也不清楚“但我无法要求系统处理每个字母 c(“a”、“b”、“c”、“d”)”。 你想要做词干? 不清楚你想要什么。余弦相似度通过确定词汇表的相似程度来比较文本。如果您想要更细粒度的东西(如字母),请使用 Levenshtein 距离。这是余弦相似度的一个简单示例:***.com/a/1750187/5028841 在下面的单独评论中我澄清了我的意图 您需要做的是将文本标记为单个字符而不是单词(更标准的标记)。像character_tokenize &lt;- function(x) strsplit(x, split = "") 这样的标记化函数 谢谢,emilliman5 工作得很好。这是最终代码: library(tm) doc 【参考方案1】:

这是我明白我能做到的。 给我一个文档,在我的例子中是字符串的“doc”向量,如果匹配被完全激活(例如关闭 -> 关闭的门),系统将为我提供 TDM 矩阵,其中的术语将为 1,但门与 oor 不匹配。

示例:

library(tm)
doc <- c( "closed door", "Open door", "door", "doo", "oor", "house" )
doc_corpus <- Corpus( VectorSource(doc) )
control_list <- list(removePunctuation = TRUE, tolower = TRUE)
tdm <- TermDocumentMatrix(doc_corpus,  control_list)
tf <- as.matrix(tdm)

关键是我读过我也可以这样做,其中术语是单个字母,我想确认这是否可能

所以要有一个 TDM 来构建然后余弦距离来计算字符串之间的距离。 但我在文档中找不到任何内容。

感谢您的帮助, 尼古拉

【讨论】:

请将此添加到您的原始帖子中,而不是作为答案

以上是关于20-余弦相似度及其R实现的主要内容,如果未能解决你的问题,请参考以下文章

R中的余弦相似度矩阵

R tm 包余弦相似度

余弦相似度计算

余弦相似度

余弦计算相似度理解以及计算

余弦相似度聚类