检查两个单词是否相互关联

时间:2013-09-18 12:00:39

标签: python python-2.7 nlp nltk

我有两个清单:一个是用户的利益;第二,关于一本书的关键词。我想根据他给定的兴趣列表向用户推荐这本书。我正在使用SequenceMatcher类的Python库difflib来匹配类似的词,如“游戏”,“游戏”,“游戏”,“游戏玩家”等。ratio函数给了我介于[0,1]之间的数字表示2个字符串的相似程度。但我陷入了一个例子,我计算了“循环”和“射击”之间的相似性。它出来是0.6667

for interest in self.interests:
    for keyword in keywords:
       s = SequenceMatcher(None,interest,keyword)
       match_freq = s.ratio()
       if match_freq >= self.limit:
            #print interest, keyword, match_freq
            final_score += 1
            break 

还有其他方法可以在Python中执行这种匹配吗?

3 个答案:

答案 0 :(得分:10)

首先一个词可以有很多感官,当你试图找到相似的词时,你可能需要一些词义消歧http://en.wikipedia.org/wiki/Word-sense_disambiguation

考虑到一对单词,如果我们采用最相似的一对意义来判断两个单词是否相似,我们可以试试这个:

from nltk.corpus import wordnet as wn
from itertools import product

wordx, wordy = "cat","dog"
sem1, sem2 = wn.synsets(wordx), wn.synsets(wordy)

maxscore = 0
for i,j in list(product(*[sem1,sem2])):
  score = i.wup_similarity(j) # Wu-Palmer Similarity
  maxscore = score if maxscore < score else maxscore

您可以使用其他相似功能。 http://nltk.googlecode.com/svn/trunk/doc/howto/wordnet.html。唯一的问题是当你遇到不在wordnet中的单词时。然后我建议你回到difflib

答案 1 :(得分:4)

首先,我想到正则表达式执行额外的测试以区分低比率的匹配。它可以是一个解决特定问题的解决方案,例如以 ing 结尾的单词。但这只是一个有限的案例,并且可能是许多其他需要为每个案例添加特定处理的案例。

然后我认为我们可以尝试找到额外的标准来消除没有语义匹配的单词,这些单词的字母比例足以被检测为匹配,尽管比率很低,
同时捕捉具有低比率的真实语义匹配术语,因为它们很短。

这是一种可能性

from difflib import SequenceMatcher

interests = ('shooting','gaming','looping')
keywords = ('loop','looping','game')

s = SequenceMatcher(None)

limit = 0.50

for interest in interests:
    s.set_seq2(interest)
    for keyword in keywords:
        s.set_seq1(keyword)
        b = s.ratio()>=limit and len(s.get_matching_blocks())==2
        print '%10s %-10s  %f  %s' % (interest, keyword,
                                      s.ratio(),
                                      '** MATCH **' if b else '')
    print

给出

  shooting loop        0.333333  
  shooting looping     0.666667  
  shooting game        0.166667  

    gaming loop        0.000000  
    gaming looping     0.461538  
    gaming game        0.600000  ** MATCH **

   looping loop        0.727273  ** MATCH **
   looping looping     1.000000  ** MATCH **
   looping game        0.181818  

请注意以下文档:

  

SequenceMatcher计算并缓存有关的详细信息   第二个序列,所以如果你想比较一个序列与许多序列   序列,使用set_seq2()设置常用序列一次和   重复调用set_seq1(),每个其他序列调用一次。

答案 2 :(得分:3)

这是因为SequenceMatcher基于edit distance或类似的东西。语义相似性更适合你的情况或两者的混合。

看看你正在使用python的NLTK包(code example),也许这个paper

对于使用c ++的人来说,可以查看此open source project以获取参考