计算文本相似度

article/2025/9/11 11:09:11

计算文本相似度
推荐 2 收藏

简单讲解

上一章有提到过[基于关键词的空间向量模型]的算法,将用户的喜好以文档描述并转换成向量模型,对商品也是这么处理,然后再通过计算商品文档和用户偏好文档的余弦相似度。

文本相似度计算在信息检索、数据挖掘、机器翻译、文档复制检测等领域有着广泛的应用。

比如舆论控制,我们假设你开发了一个微博网站,并且已经把世界上骂人的句子都已经收录进了数据库,那么当一个用户发微博时会先跟骂人句子的数据库进行比较,如果符合里面的句子就不让用户发出。

通常情况下,很多工程师就会想到用like或者where的sql语法去查找。可是当情况更为复杂呢?

数据库存放了“你是个坏人”,用户要发“小明是个坏人”,这时应该怎么办呢?

最简单的办法就是通过判断文本的相似程度来决定用户发的内容是否是骂人的。

本章节就几种简单的判断文本相似性的算法来讲解,帮助大家更好的理解。

相关算法

1、余弦相似性

余弦(余弦函数),三角函数的一种。在Rt△ABC(直角三角形)中,∠C=90°,角A的余弦是它的邻边比三角形的斜边,即cosA=b/c,也可写为cosA=AC/AB。余弦函数:f(x)=cosx(x∈R)

这是一个非常常见的算法,相信大家都应该学过余弦定理了,简单来说这个算法就是通过计算两个向量的夹角余弦值来评估他们的相似度。

对于二维空间,根据向量点积公式,显然可以得知(ps,这个公式不是这个算法的重点,可以不用强记):

假设向量a、b的坐标分别为(x1,y1)、(x2,y2) 。则:

设向量 A = (A1,A2,...,An),B = (B1,B2,...,Bn) 。推广到多维,数学家已经帮我们证明了,所以你只要记住下面的公式:

简单来说可以写成下面的式子:

(式子中的x和y是指词频)

比如我们要判断两句话

A=你是个坏人 B=小明是个坏人

① 先进行分词

A=你 / 是 / 个 / 坏人 B=小明 / 是 / 个 / 坏人

② 列出所有的词

{ 你 小明 是 个 坏人 }

③计算词频(出现次数)

A={1 0 1 1} (每个数字对应上面的字) B={0 1 1 1}

然后把词频带入公式

最终=0.667(只余3位),可以百度"2除以(根号3乘以根号3)"看到计算结果。

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

简单来说上面计算出的值代表两个句子大概六成相似,越接近1就越相似。

2、简单共有词

通过计算两篇文档共有的词的总字符数除以最长文档字符数来评估他们的相似度。

假设有A、B两句话,先取出这两句话的共同都有的词的字数然后看哪句话更长就除以哪句话的字数。

同样是A、B两句话,共有词的字符长度为4,最长句子长度为6,那么4/6,≈0.667。

3、编辑距离

编辑距离(Edit Distance),又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。一般来说,编辑距离越小,两个串的相似度越大。由俄罗斯科学家Vladimir Levenshtein(找不到他照片233333)在1965年提出这个概念。

例如将“BABAY是个好人”转成“BABY是个帅哥”,编辑举例就是2~~(好人变帅哥只要2就好...)~~: BABY是个帅人(好→帅) BABY是个帅哥(人→哥)

然后拿编辑距离去除以两者之间的最大长度,2/6≈0.333,意味着只要变动这么多就可以从A变成B,所以不用变动的字符便代表了相似度,1-0.333=0.667。

4、SimHash + 汉明距离

simhash是谷歌发明的算法,据说很nb,可以将一个文档转换成64位的字节,然后我们可以通过判断两个字节的汉明距离就知道是否相似了。

汉明距离是以理查德·卫斯里·汉明的名字命名的。在信息论中,两个等长字符串之间的汉明距离是两个字符串对应位置的不同字符的个数。换句话说,它就是将一个字符串变换成另外一个字符串所需要替换的字符个数。例如:

1011101 与 1001001 之间的汉明距离是 2。

"toned" 与 "roses" 之间的汉明距离是 3。

首先我们来计算SimHash:

① 提取文档关键词得到[word,weight]这个一个数组。(举例 [美国,4])

② 用hash算法将word转为固定长度的二进制值的字符串[hash(word),weight]。(举例 [100101,4])

③ word的hash从左到右与权重相乘,如果为1则乘以1 ,如果是0则曾以-1。(举例4,-4,-4,4,-4,4)

④ 接着计算下个数,直到将所有分词得出的词计算完,然后将每个词第三步得出的数组中的每一个值相加。(举例美国和51区,[4,-4,-4,4,-4,4]和[5 -5 5 -5 5 5]得到[9 -9 1 -1 1 9])

⑤ 对第四步得到的数组中每一个值进行判断,如果>0记为1,如果<0记为0。(举例[101011])

第四步得出的就是这个文档的SimHash。

这样我们就能将两个不同长度的文档转换为同样长度的SimHash值,so,我们现在可以计算第一个文档的值和第二个文档的汉明距离(一般<3就是相似度高的)。

SimHash本质上是局部敏感性的hash(如果是两个相似的句子,那么只会有部分不同),和md5之类的不一样。 正因为它的局部敏感性,所以我们可以使用海明距离来衡量SimHash值的相似度。

如果想要小数形式的可以这么做:1 - 汉明距离 / 最长关键词数组长度。

5、Jaccard相似性系数

Jaccard 系数,又叫Jaccard相似性系数,用来比较样本集中的相似性和分散性的一个概率。Jaccard系数等于样本集交集与样本集合集的比值,即J = |A∩B| ÷ |A∪B|。

说白了就是交集除以并集,两个文档的共同都有的词除以两个文档所有的词。

6、欧几里得距离

欧几里得距离是用得非常广的公式,设A(x1, y1),B(x2, y2)是平面上任意两点那么两点间的距离距离(A,B)=平方根((x1-x2...)^2+(y1-y2....)^2)

我们可以拿两个文档所有的词(不重复)在A文档的词频作为x,在B文档的作为y进行计算。

同样拿A=你是个坏人、B=小明是个坏人 这两句话作为例子,词频分别为A={1 0 1 1} 、B={0 1 1 1}。

那么距离为根号2,≈ 1.414(余3位)

然后可以通过1 ÷ (1 + 欧几里德距离)得到相似度。

7、曼哈顿距离

曼哈顿距离(Manhattan Distance)是由十九世纪的赫尔曼·闵可夫斯基所创词汇,是种使用在几何度量空间的几何学用语,用以标明两个点上在标准坐标系上的绝对轴距总和。

跟欧几里德距离有点像,简单来说就是d(i,j)=|x1-x2...|+|y1-y2...|,同理xn和yn分别代表两个文档所有的词(不重复)在A和B的词频。

然后可以通过1 ÷ (1 + 曼哈顿距离)得到相似度。

其它

公式生成工具:http://private.codecogs.com/latex/eqneditor.php


http://chatgpt.dhexx.cn/article/H1YuNTiK.shtml

相关文章

计算文本相似度的常用算法

文章目录 1. 余弦相似度2. TF-IDF模型2.1 词频TF的计算方法2.2 反文档频率IDF的计算方法2.3 TF-IDF的计算方法 3. 基于语义相似度的计算 —— DSSM4. LSI/LSA模型5. LDA模型6. 编辑距离计算7. 杰卡德系数计算8. Word2Vec计算9. BM25 NLP、数据挖掘领域中&#xff0c;文本分析是…

LCS、LIS

LCS是最长公共子序列的表示&#xff1a; 题目链接 代码也十分简单就不敲了。 LIS是最长上升子序列的英文缩写。 (动态规划) O(n2)O(n2) 状态表示&#xff1a;f[i]表示从第一个数字开始算&#xff0c;以w[i]结尾的最大的上升序列。(以w[i]结尾的所有上升序列中属性为最大值的…

LCMV相关的算法

写这个程序的时候&#xff0c;我们遵循如下的设计过程&#xff1a; 第一&#xff1a;设计LCMV&#xff1b; 第二&#xff1a;降秩LCMV&#xff1b; 第三&#xff1a;自适应降秩LCMV&#xff1b; 下面我首先给你捋一下整个算法的大致思路&#xff1a; 输入信号&#xff1a; …

SCC算法求强连通分量简单讲解证明及实现

目录 强连通分量SCC算法简介两个概念dfs结束时间转置图 SCC算法伪代码描述SCC算法正确性证明引理1&#xff1a;引理2&#xff1a;SCC证明不错找不漏找 代码实现 强连通分量 连通分量要求任意两点可达&#xff0c;而强连通分量要求任意两点互相可达&#xff0c;即必须存在a->…

最长公共子串LCS (Longest Common Subsequence) 算法

三个方法都有所借鉴&#xff0c;但代码部分是自己试着写出来的&#xff0c;虽然最后的运行结果都是正确的&#xff0c;但此过程中难免会有考虑不周全的地方&#xff0c;如发现代码某些地方有误&#xff0c;欢迎指正。同时有新的想法&#xff0c;也可以提出! 采用顺序结构存储串…

常考的经典算法--最长公共子序列(LCS)与最长公共子串(DP)

《1》最长公共子序列&#xff08;LCS&#xff09;与最长公共子串(DP) http://blog.csdn.net/u012102306/article/details/53184446 https://segmentfault.com/a/1190000007963594 http://www.cppblog.com/mysileng/archive/2013/05/14/200265.html 1. 问题描述 子串应该比…

LCS算法学习

LCS的定义 最长公共子序列&#xff0c;即Longest Common Subsequence&#xff0c;LCS。一个序列S任意删除若干个字符得到新序列T&#xff0c;则T叫做S的子序列&#xff1b;两个序列X和Y的公共子序列中&#xff0c;长度最长的那个&#xff0c;定义为X和Y的最长公共子序列。 字符…

算法系列之六:最长公共子序列(LCS)问题(连续子序列)的三种解法

最长公共子序列&#xff08;LCS&#xff09;问题有两种方式定义子序列&#xff0c;一种是子序列不要求不连续&#xff0c;一种是子序列必须连续。上一章介绍了用两种算法解决子序列不要求连续的最终公共子序列问题&#xff0c;本章将介绍要求子序列必须是连续的情况下如何用算法…

Hirschberg的LCS算法实现

解决Longest Common Subsequence(LCS)问题最常用的算法是Dyanmic programing&#xff0c;细节可以参考Ch15.4 of Introduction of Algorithm(2ED), MIT press, p 350。这个算法最大的问题是他的空间复杂度是O(m*n)。这样&#xff0c;当两个序列达到上万个节点时&#xff0c;内存…

SLIC算法

基础知识 在介绍SLIC之前&#xff0c;先来介绍以下Lab颜色空间的介绍。 Lab色彩模型是由亮度(L)要素和与有关色彩的a,b要素组成&#xff0c;L的值由0(黑色)到100(白色)&#xff0c;a表示从洋红色至绿色的范围(a为负值表示绿色而正值表示品红)&#xff0c;b表示从黄色至蓝色的…

动态规划之LCS算法

一、前言 LCS是Longest Common Subsequence的缩写&#xff0c;即最长公共子序列。一个序列&#xff0c;如果是两个或多个已知序列的子序列&#xff0c;且是所有子序列中最长的&#xff0c;则为最长公共子序列。 另外还有个分支问题&#xff1a;最长公共子串。子串的字符位置必…

LCS算法的C++实现

这两天忙里偷闲看了July的团队提供的LCS算法视频&#xff0c;真的如视频标题一样&#xff0c;十分钟搞定LCS算法。 感谢July大神&#xff0c;感谢其团队的邹博。 这里附上视频链接&#xff1a;http://www.julyedu.com/video/play?course17 说是十分钟搞定&#xff0c;其实是…

算法学习 - 最长公共子序列(LCS)C++实现

最长公共子序列 最长公共子序列的问题很简单&#xff0c;就是在两个字符串中找到最长的子序列&#xff0c;这里明确两个含义&#xff1a; 子串&#xff1a;表示连续的一串字符 。子序列&#xff1a;表示不连续的一串字符。 所以这里要查找的是不连续的最长子序列&#xff0c; …

SLIC算法介绍

SLIC&#xff08;simple linear iterativeclustering&#xff09;&#xff0c;即 简单线性迭代聚类 。 &#x1f49b;它是2010年提出的一种思想简单、实现方便的算法&#xff0c;将彩色图像转化为CIELAB颜色空间和XY坐标下的5维特征向量&#xff0c;然后对5维特征向量构造距离度…

LSC算法

1.问题 给定序列 X<x_1,x_2,…,x_m> Y<y_1,y_2,…,y_j> 求X和Y的最长公共子序列(LCS) 2.解析 X<x1,x2,x3,x4…,xi> Y<y1,y2,y3,y4…,yi> 如果Z<z1,z2,z3,z4…,zk>是他们的最长公共子序列 则&#xff1a; &#xff08;1&#xff09;xi yi&…

LCS算法详解

程序员编程艺术第十一章&#xff1a;最长公共子序列(LCS)问题 0、前言 程序员编程艺术系列重新开始创作了&#xff08;前十章&#xff0c;请参考程序员编程艺术第一~十章集锦与总结&#xff09;。回顾之前的前十章&#xff0c;有些代码是值得商榷的&#xff0c;因当时的代码只顾…

LCS 最大公共序列算法

这些天在了解chrome的courgette, 了解了rsync算法, 也了解了courgette使用了bsdiff 算法, 然后知道了bsdiff算法里主要使用的是 LCS 算法, 这里参考了july大牛的文章: http://blog.csdn.net/v_july_v/article/details/6695482 自己做一点概括性的总结, 用以备忘, 也把自…

最长公共子序列(LCS)算法

一、最长公共字串与最长公共子序列 最长公共子串&#xff08;Longest Common Substirng&#xff09; 子串是串的一个连续的部分&#xff0c;子串中字符的位置必须连续。 例如&#xff1a;有两个字符串ABCBDAB 和 BDCABA&#xff0c;则它们的最长公共子串是&#xff1a;AB。 …

LCS(longest common sequence)算法的实现(十分详细)

一、问题描述 有两个字符串&#xff0c;求二者的最长公共子序列。 最长公共子序列&#xff1a;不必连续但必须有序的子列&#xff08;与子串区分&#xff0c;子串是连续的&#xff09; 二&#xff1a;解决方法 第一种方法&#xff1a;穷举法 &#xff0c;就是一个一个的对比&a…

LCS算法

LCS算法 LCS算法&#xff1a; LCS是Longest Common Subsequence的缩写&#xff0c;即最长公共子序列。一个序列&#xff0c;如果是两个或多个已知序列的子序列&#xff0c;且是所有子序列中最长的&#xff0c;则为最长公共子序列。LCS不是唯一的&#xff0c;它可以有很多种&am…