使用nltk的一般同义词和词性处理

时间:2012-06-12 22:01:03

标签: python machine-learning nlp nltk wordnet

我正在尝试为句子中的单词创建一个通用的同义词标识符,这些标识符很重要(即不是“a”或“the”),我在python中使用自然语言工具包(nltk)。我遇到的问题是nltk中的同义词查找器需要一个词性参数才能链接到它的同义词。我试图解决这个问题是使用nltk中存在的简化词性标记,然后减少第一个字母以便将此参数传递给同义词查找器,但是这不起作用。

def synonyms(Sentence):
    Keywords = []
    Equivalence = WordNetLemmatizer()
    Stemmer = stem.SnowballStemmer('english')
    for word in Sentence:
        word = Equivalence.lemmatize(word)
    words = nltk.word_tokenize(Sentence.lower())
    text = nltk.Text(words)
    tags = nltk.pos_tag(text)
    simplified_tags = [(word, simplify_wsj_tag(tag)) for word, tag in tags]
    for tag in simplified_tags:
        print tag
        grammar_letter = tag[1][0].lower()
        if grammar_letter != 'd':
            Call = tag[0].strip() + "." + grammar_letter.strip() + ".01"
            print Call
            Word_Set = wordnet.synset(Call)
            paths = Word_Set.lemma_names
            for path in paths:
                Keywords.append(Stemmer.stem(path))
    return Keywords

这是我目前正在处理的代码,正如你所看到的那样,我首先将输入变为lematizing以减少从长远来看我将拥有的匹配数量(我打算在成千上万的句子上运行它) ,理论上我会在此之后产生这个词以进一步促进这种效应并减少我产生的冗余单词的数量,但是这种方法几乎总是以下面的形式返回错误:

Traceback (most recent call last):
  File "C:\Python27\test.py", line 45, in <module>
    synonyms('spray reddish attack force')
  File "C:\Python27\test.py", line 39, in synonyms
    Word_Set = wordnet.synset(Call)
  File "C:\Python27\lib\site-packages\nltk\corpus\reader\wordnet.py", line 1016, in synset
    raise WordNetError(message % (lemma, pos))
WordNetError: no lemma 'reddish' with part of speech 'n'

我对这些将要运行的数据没有多少控制权,所以简单地清理我的语料库并不是一个真正的选择。关于如何解决这个问题的任何想法?

我做了更多的研究,并且我有很好的领导,但我仍然不确定如何实现它。在未找到或错误分配的单词的情况下,我想使用相似性度量(Leacock Chodorow,Wu-Palmer等)将该单词链接到最接近的正确分类的其他关键字。也许与编辑距离测量相结合,但我再也找不到任何类型的文档。

2 个答案:

答案 0 :(得分:7)

显然nltk允许检索与单词相关的所有同义词。当然,通常有一些反映不同的词义。为了在功能上找到同义词(或者如果两个单词是同义词),您必须尝试匹配可能的最接近的同义词集,这可以通过上面提到的任何相似性度量来实现。我精心设计了一些基本代码,如下所示,如何找到两个单词是否是同义词:

from nltk.corpus import wordnet
from nltk.stem.wordnet import WordNetLemmatizer
import itertools


def Synonym_Checker(word1, word2):
    """Checks if word1 and word2 and synonyms. Returns True if they are, otherwise False"""
    equivalence = WordNetLemmatizer()
    word1 = equivalence.lemmatize(word1)
    word2 = equivalence.lemmatize(word2)

    word1_synonyms = wordnet.synsets(word1)
    word2_synonyms = wordnet.synsets(word2)

    scores = [i.wup_similarity(j) for i, j in list(itertools.product(word1_synonyms, word2_synonyms))]
    max_index = scores.index(max(scores))
    best_match = (max_index/len(word1_synonyms), max_index % len(word1_synonyms)-1)

    word1_set = word1_synonyms[best_match[0]].lemma_names
    word2_set = word2_synonyms[best_match[1]].lemma_names
    match = False
    match = [match or word in word2_set for word in word1_set][0]

    return match

print Synonym_Checker("tomato", "Lycopersicon_esculentum")

我可能会尝试逐步实施更强大的词干算法,但是对于我做的前几个测试,这段代码实际上适用于我能找到的每个词。如果有人对如何改进这个算法有任何想法,或者有任何改进这个答案的话,我很乐意听到。

答案 1 :(得分:1)

您可以使用Word_Set = wordnet.synset(Call)包裹try:并忽略WordNetError例外吗?看起来你的错误是某些单词没有被正确分类,但是对于无法识别的单词也会出现这种异常,所以抓住异常对我来说似乎是一个好主意。