NLTK 将分词的句子转换为 synset 格式

8

我想使用NLTK获取单个单词与句子中每个单词之间的相似度。

NLTK可以像下面展示的那样获取两个特定单词之间的相似度。此方法需要给出对单词的具体引用,在本例中是“dog.n.01”,其中dog是一个名词,我们想使用第一个(01)NLTK定义。

dog = wordnet.synset('dog.n.01')
cat = wordnet.synset('cat.n.01')
print  dog.path_similarity(cat)
>> 0.2

问题在于我需要从每个句子中获取词语的词性信息。NLTK软件包可以获取句子中每个单词的词性,如下所示。然而,这些词性('NN'、'VB'、'PRP'等)与synset所需的格式不匹配。
text = word_tokenize("They refuse to permit us to obtain the refuse permit")
pos_tag(text)
>> [('They', 'PRP'), ('refuse', 'VBP'), ('to', 'TO'), ('permit', 'VB'), ('us', 'PRP'), ('to', 'TO'), ('obtain', 'VB'), ('the', 'DT'), ('refuse', 'NN'), ('permit', 'NN')]

在NLTK中,是否可以从pos_tag()的结果中获得与synset格式相同的数据?这里的synset格式是类似于dog.n.01的格式。

2个回答

10

您可以使用一个简单的转换函数:

from nltk.corpus import wordnet as wn

def penn_to_wn(tag):
    if tag.startswith('J'):
        return wn.ADJ
    elif tag.startswith('N'):
        return wn.NOUN
    elif tag.startswith('R'):
        return wn.ADV
    elif tag.startswith('V'):
        return wn.VERB
    return None

在对句子进行标记之后,您可以使用此函数将句子内的单词与SYNSET绑定。以下是一个示例:

from nltk.stem import WordNetLemmatizer
from nltk import pos_tag, word_tokenize

sentence = "I am going to buy some gifts"
tagged = pos_tag(word_tokenize(sentence))

synsets = []
lemmatzr = WordNetLemmatizer()

for token in tagged:
    wn_tag = penn_to_wn(token[1])
    if not wn_tag:
        continue

    lemma = lemmatzr.lemmatize(token[0], pos=wn_tag)
    synsets.append(wn.synsets(lemma, pos=wn_tag)[0])

print synsets

结果: [Synset('be.v.01'), Synset('travel.v.01'), Synset('buy.v.01'), Synset('gift.n.01')]


我发现了这个lesk的例子,但是你的代码似乎给出了更好的结果,我想知道为什么(只是好奇):http://www.nltk.org/howto/wsd.html - Hamman Samuel
1
Lesk算法并不是非常有效。这段代码之所以可能效果更好,仅仅是因为它获取了第一个同义词集。在WordNet中,同义词集按照频率排序。换句话说,如果我们不考虑上下文,第一个同义词集是最有可能的。 - bogs

1
您可以使用WordNet.synset的替代形式:
wordnet.synset('dog', pos=wordnet.NOUN)

您仍然需要将pos_tag提供的标签翻译成wordnet.sysnset支持的标签 - 不幸的是,我不知道是否存在一个预构建的字典来做到这一点,因此(除非我错过了这样的对应表的存在),您需要构建自己的(您可以执行这个步骤并将其存储为pickle以供之后重新加载)。

请参见http://www.nltk.org/book/ch05.html第1小节,了解如何获取特定标记集的帮助 - 例如,nltk.help.upenn_tagset('N.*')将确认UPenn标记集(我相信是由pos_tag使用的默认标记集)使用'N'后跟某些内容来标识synset将会视为wordnet.NOUN的变体。

我还没有尝试过http://www.nltk.org/_modules/nltk/tag/mapping.html,但它可能正是您所需的 - 不妨试试!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接