search具有相似文字的文章的algorithm

我有一个数据库中的许多文章(标题,文本),我正在寻找一个algorithm来findX最类似的文章,如Stack Overflow的“相关问题”,当你问一个问题。

我尝试了谷歌search,但只发现了有关其他“类似文字”问题的网页,比如将每篇文章与所有其他文章进行比较,并在某处存储相似度。 所以我在刚input的文本中“实时”做这个事情。

怎么样?

编辑距离不是一个可能的候选人,因为它会拼写/字顺依赖性,并且考虑到您实际上感兴趣search的文档的大小和数量,Will会引导您相信在计算上更昂贵。

像Lucene的东西是要走的路。 您将所有文档编入索引,然后在查找与给定文档类似的文档时,将给定文档转换为查询,然后search索引。 Lucene内部将使用tf-idf和一个倒排索引来使整个过程花费的时间与可能匹配的文档数量成正比,而不是集合中的文档总数。

这取决于你的类似的定义。

编辑距离algorithm是(拉丁语言)字典build议的标准algorithm,可以在整个文本上工作。 两个文本是相似的,如果他们有相同的顺序基本相同的单词(呃字母)。 所以下面的两个书评会是相当类似的:

1)“这是一本很棒的书”

2)“这些不是很好的书”

(删除,插入,删除或改变将(2)转换为(1)的字母数目称为“编辑距离”。)

要实现这一点,你会想要以编程方式访问每一个审查。 这可能不像听起来那么昂贵,如果成本太高,你可以将比较作为后台任务,并将它们存储在数据库领域本身。

另一种方法是理解(拉丁)语言的结构。 如果你去掉短语(非首字母大写或引用)的单词,并且为单词(或前缀)分配权重,那么你可以做一个贝叶斯(Bayesianesque)比较。 以下两个书评可能会被模仿,并发现是类似的:

3)“法国革命等于是战争与和平等于法国。” – >法国/法国(2)革命(1)战争(1)和平(1)(注意,法国和法国已经使用了字典)

4)“这本书是对法国菜的一场革命”。 – >法国(1)革命(1)

要实现这一点,你会想要在创build/更新时在评论中标识“关键字”,并find类似的评论在查询的where子句中使用这些关键字(最好是“全文”search数据库是否支持它),也许还会对结果集进行后处理,以findfind的候选人。

书籍也有类别 – 法国的惊悚片与法国的历史研究类似吗? 标题和文字以外的元数据可能对保持结果的相关性有用。

在这个链接的教程听起来像它可能是你所需要的。 这很容易遵循,工作得很好。

他的algorithm奖励常见的子string和这些子string的通用sorting,所以应该很好地挑选相似的标题。

我build议使用Apache Lucene ( 一个完全用Java编写的高性能,全function的文本search引擎库)为您的文章编制索引 它几乎适用于任何需要全文search的应用程序,特别是跨平台的应用程序 。 一旦索引,你可以很容易地find相关的文章。

一个常用的algorithm是自组织映射 。 这是一种neural network,将自动分类您的文章。 然后,您可以简单地find当前文章在地图中的位置以及与其相关的所有文章。 algorithm的重要部分是如何vector量化你的input 。 有几种方法可以处理文本。 你可以散列你的文件/标题,你可以计算单词,并使用它作为一个n维向量等。希望这会有所帮助,虽然我可能已经打开了一个潘多拉的盒子给你一个无尽的人工智能旅程。

所以SO只是在标题上进行比较,而不是在问题的正文上进行比较,所以只能在相当短的string上进行比较。

您可以使用他们的algorithm(不知道它是什么样子)文章标题和关键字。 如果你有更多的CPU时间刻录,也可以在你的文章的摘要。

借用Lucene对全文的build议,但要注意java不是必需的; .NET端口可用 。 另请参阅主要的Lucene页面链接到其他项目,包括露西,一个C端口 。

也许你所寻找的东西是可以解释的 。 我只有粗略的知识,但是释义是一种自然语言处理的概念,用来确定文本的两段经文是否意味着相同的事物 – 虽然可能使用完全不同的词语。

不幸的是,我不知道有什么工具可以让你做到这一点(尽pipe我有兴趣find一个)

您可以使用SQL Server全文索引来获得智能比较,我相信SO是使用ajax调用,它执行查询来返回类似的问题。

你在用什么技术?

如果你正在寻找类似伤口的单词,你可以转换成soundex和soundex单词匹配…为我工作

我尝试了一些方法,但都没有效果。一个可能会得到一个相对满意的结果是这样的:首先:获取所有文本的每个段落的Google SimHash代码,并将其存储在数据库中。 第二:SimHash代码的索引。 第三:如上所述处理你的文本进行比较,得到一个SimHash代码,并通过SimHash索引search所有文本,这些索引间隔如海明距离5-10。 然后比较模糊与术语向量。 这可能适用于大数据。

你可以使用1)Minhash / LSH https://en.wikipedia.org/wiki/MinHash

(另见: http : //infolab.stanford.edu/~ullman/mmds/book.pdf )

要么

2)协作过滤: https : //en.wikipedia.org/wiki/Collaborative_filtering

在@ alex77的答案中的链接指向一个由该文章的作者独立发现的索伦森 – 骰子系数 – 文章写得非常好,值得一读。

我已经结束了使用这个系数为我自己的需要。 但是,原始系数在处理时会产生错误的结果

  • 包含一个拼写错误的三个字母的单词对,例如[and,amd]
  • 三个字母词对是anagrams例如[and,dan]

在第一种情况下,骰子错误地报告系数为零,而在第二种情况下,系数变为0.5,这是误导性的高。

已经有人提出了一个改进,其实质上包括了这个词的第一个和最后一个字母,并创build了一个额外的二元组。

在我看来,对于3个字母的单词来说,这个改进只是需要的 – 用更长的字眼来说,其他两个字母都有缓冲效果来掩盖问题。 我的代码实现了这个改进如下。

 function wordPairCount(word) { var i,rslt = [],len = word.length - 1; for(i=0;i < len;i++) rslt.push(word.substr(i,2)); if (2 == len) rslt.push(word[0] + word[len]); return rslt; } function pairCount(arr) { var i,rslt = []; arr = arr.toLowerCase().split(' '); for(i=0;i < arr.length;i++) rslt = rslt.concat(wordPairCount(arr[i])); return rslt; } function commonCount(a,b) { var t; if (b.length > a.length) t = b, b = a, a = t; t = a.filter(function (e){return b.indexOf(e) > -1;}); return t.length; } function myDice(a,b) { var bigrams = [], aPairs = pairCount(a), bPairs = pairCount(b); debugger; var isct = commonCount(aPairs,bPairs); return 2*commonCount(aPairs,bPairs)/(aPairs.length + bPairs.length); } $('#rslt1').text(myDice('WEB Applications','PHP Web Application')); $('#rslt2').text(myDice('And','Dan')); $('#rslt3').text(myDice('and','aMd')); $('#rslt4').text(myDice('abracadabra','abracabadra')); 
 *{font-family:arial;} table { width:80%; margin:auto; border:1px solid silver; } thead > tr > td { font-weight:bold; text-align:center; background-color:aqua; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script> <table> <thead> <tr> <td>Phrase 1</td> <td>Phrase 2</td> <td>Dice</td> </tr> <thead> <tbody> <tr> <td>WEB Applications</td> <td>PHP Web Application</td> <td id='rslt1'></td> </tr> <tr> <td>And</td> <td>Dan</td> <td id='rslt2'></td> </tr> <tr> <td>and</td> <td>aMd</td> <td id='rslt3'></td> </tr> <tr> <td>abracadabra</td> <td>abracabadra</td> <td id='rslt4'></td> </tr> </tbody> </table> 

比较摘要之间相似性的最简单和最快的方法可能是利用设定的概念。 首先将抽象文本转换为一组单词。 然后检查每个集合有多less重叠。 Python的设置function来完成这项任务。 您会惊讶地发现,这种方法与GScholar,ADS,WOS或Scopus提供的那些“相似/相关论文”选项相比有多好。