我正在尝试为句子中的重要词语(即非“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
这是我目前正在使用的代码,如你所见,我首先对输入进行词形还原,以减少将来匹配的数量(我计划在成千上万的句子上运行这个),理论上,我会在之后进行词干提取,以进一步减少生成的冗余词汇的数量,然而,这种方法几乎总是会返回如下形式的错误:
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等)将词链接到最接近的正确分类其他关键词。也许结合编辑距离度量,但同样,我没有找到任何关于此的文档。
回答:
显然,nltk允许检索与一个词相关的所有同义词集。当然,通常会有多个同义词集,反映不同的词义。为了功能性地找到同义词(或两个词是否是同义词),你必须尝试匹配最接近的同义词集,这是通过上述提到的任何相似性度量来实现的。我编写了一些基本代码来实现这一点,如下所示,如何判断两个词是否是同义词:
from nltk.corpus import wordnetfrom nltk.stem.wordnet import WordNetLemmatizerimport itertoolsdef Synonym_Checker(word1, word2): """检查word1和word2是否是同义词。如果是,返回True,否则返回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 matchprint Synonym_Checker("tomato", "Lycopersicon_esculentum")
我可能会尝试实施更强的词干提取算法,但在最初的几次测试中,这段代码实际上对我能找到的每个词都有效。如果有人有关于如何改进这个算法的想法,或者有任何改进这个答案的方法,我很乐意听取建议。