返回文本之间关联的函数?

时间:2011-01-24 23:21:07

标签: algorithm text full-text-search relevance

考虑我有一个

string1 = "hello hi goodmorning evening [...]"

我有一些小关键字

compare1 = "hello evening"
compare2 = "hello hi"

我需要一个返回文本和关键字之间关联的函数。例如:

function(string1,compare1);  // returns: 4
function(string1,compare2);  // returns: 5 (more relevant)

请注意5和4只是例如。

你可以说 - 编写一个计算出现次数的函数 - 但是对于这个例子,这不起作用,因为它们都有2次出现,但是compare1的相关性较低,因为“hello evening”在string1中找不到(2个字你好和傍晚比你好,你好。

有没有任何已知算法可以做到这一点?

ADD1:

在这种情况下像编辑距离这样的算法不起作用。 因为string1是一个完整的文本(如300-400个单词),比较字符串最多为4-5个单词。

7 个答案:

答案 0 :(得分:8)

动态编程算法

您正在寻找的内容与Smith–Waterman algorithm的内容非常相似。

来自维基百科:

  

该算法最初是由Temple F. Smith和Michael S. Waterman在1981年提出的。与Needleman-Wunsch算法一样,它是一个变体,Smith-Waterman是dynamic programming algorithm。因此,它具有所需的性质,即保证找到关于所使用的评分系统的最佳局部对齐(其包括替换矩阵和间隙评分方案)。

让我们看一个实际的例子,这样你就可以评估它的用处。

假设我们有一个文本:

text = "We the people of the United States, in order to form a more 
perfect union, establish justice, insure domestic tranquility, 
provide for the common defense, 

  promote the general welfare, 

  and secure the blessings of liberty to ourselves and our posterity, 
do ordain and establish this Constitution for the United States of 
America.";  

我隔离了我们要匹配的片段,只是为了方便阅读。

我们将亲和力(或相似性)与字符串列表进行比较:

list = {
   "the general welfare",
   "my personal welfare",
   "general utopian welfare",
   "the general",
   "promote welfare",
   "stackoverflow rulez"
   };  

我已经实现了算法,因此我将计算相似度并将结果标准化:

sw = SmithWatermanSimilarity[ text, #] & /@ list;
swN = (sw - Min[sw])/(Max[sw] - Min[sw])  

然后我们绘制结果:

enter image description here

我认为这与您的预期结果非常相似。

HTH!

一些实现(带源代码)

答案 1 :(得分:4)

了解从输入数据中创建N-gram然后匹配N-gram。我有一个解决方案,我将每个n-gram视为向量空间中的维度(在我的情况下变为4000维的空间)然后亲和力是两个向量之间角度的余弦(此处涉及点积) )。

困难的部分是提出一个以您想要的方式定义亲和力的指标。

另一种方法是根据compare_x数据中窗口中的单词数量来查看滑动窗口和得分。最终得分是总和。

答案 2 :(得分:2)

py-editdist会在两个字符串之间提供Levenshtein edit distance,这是一个可能有用的指标。​​

请参阅:http://www.mindrot.org/projects/py-editdist/

该页面的代码示例:

import editdist

# Calculate the edit distance between two strings
d = editdist.distance("abc", "bcdef")

相关:https://stackoverflow.com/questions/682367/good-python-modules-for-fuzzy-string-comparison

答案 3 :(得分:1)

我认为这里有一个非常好的和完整的答案 http://answers.google.com/answers/threadview?id=337832

对不起它的谷歌答案!

答案 4 :(得分:0)

在这里,您可以找到用于计算字符串之间距离的度量标准列表,以及一个仅执行该操作的开源Java库。 http://en.wikipedia.org/wiki/String_metric 特别是,看看Smith-Waterman算法,记住他们所谓的“Alphabet”可以由我们称之为字符串的东西组成:所以,给定字母

{A = "hello", B = "hi",C = "goodmorning",D = "evening"}

并调用距离d,你的函数试图计算

d(ABCD,AB) vs d(ABCD,AC)

答案 5 :(得分:0)

那么,您可以计算比较文本片段的出现次数,即:

“a-b-c” - > “a”,“b”,“c”,“a-b”,“b-c”,“a-b-c”(可能是“a-c”,如果你想要的话)

然后计算每个的出现次数,并将它们相加,可能具有(字符串长度)/(整个字符串的长度)的权重。

然后你只需要一种方法来制作这些作品,并对所有作品进行检查。

答案 6 :(得分:0)

尽管Levenshtein distance目前可能不适合您的目的,但对它的修改可能是:尝试通过单独存储插入,删除和替换来实现它。

距离将是以下之和:

  • 所有替代
  • 每组连续插入/删除中的空格数减1:
    • (在您的情况下:“hi goodmorning”仅计为两次编辑,'[...]'计为一次。)

当然,你必须对此进行测试,但如果效果不好,请尝试使用连续插入/删除的总和(因此,“早上好”只有1次编辑)。

修改

PS:这假设对Levenshtein的工作方式做了一个相对重大的改变,你想首先“对齐”你的数据(找出重要的(超过两个字符)重叠的位置,并插入可以算作的'null'字符插入)。

此外,这只是一个未经考验的想法,所以欢迎任何改进的想法。