WordNet:迭代同义词集
WordNet: Iterate over synsets
对于一个项目,我想测量文本中“以人为本”的词的数量。我计划使用 WordNet 来完成这项工作。我从来没有使用过它,我不太确定如何处理这个任务。我想使用 WordNet 来计算属于某些同义词集的单词数量,例如 sysnets“human”和“person”。
我想出了以下(简单的)代码:
word = 'girlfriend'
word_synsets = wn.synsets(word)[0]
hypernyms = word_synsets.hypernym_paths()[0]
for element in hypernyms:
print element
结果:
Synset('entity.n.01')
Synset('physical_entity.n.01')
Synset('causal_agent.n.01')
Synset('person.n.01')
Synset('friend.n.01')
Synset('girlfriend.n.01')
我的第一个问题是,如何正确地迭代上位词?在上面的代码中,它打印得很好。但是,当使用“if”语句时,例如:
count_humancenteredness = 0
for element in hypernyms:
if element == 'person':
print 'found person hypernym'
count_humancenteredness +=1
我收到“AttributeError: 'str' object has no attribute '_name'”。当一个词确实属于“person”或“human”同义词集时,我可以使用什么方法来迭代我的词的上位词并执行一个动作(例如,增加以人为中心的计数)。
其次,这是一种有效的方法吗?我假设迭代几个文本和迭代每个名词的上位词将花费相当长的时间。也许还有另一种方法可以使用 WordNet 更有效地执行我的任务。
感谢您的帮助!
wrt 错误消息
hypernyms = word_synsets.hypernym_paths()
returns SynSet
s 列表的列表。
因此
if element == 'person':
尝试将 SynSet
对象与字符串进行比较。 SynSet
.
不支持这种比较
试试
target_synsets = wn.synsets('person')
if element in target_synsets:
...
或
if u'person' in element.lemma_names():
...
相反。
wrt 效率
目前,您对输入文本中的每个单词执行上位词查找。正如您所注意到的,这不一定有效。但是,如果这足够快,就到此为止,不要优化未损坏的部分。
为了加快查找速度,您可以预先编译一个“person related”单词的列表,方法是使用下位词的传递闭包,如解释的那样here.
类似
person_words = set(w for s in p.closure(lambda s: s.hyponyms()) for w in s.lemma_names())
应该可以解决问题。这将 return 一组 ~ 10,000
个单词,存储在主内存中不会太多。
单词计数器的一个简单版本然后变成了
from collections import Counter
word_count = Counter()
for word in (w.lower() for w in words if w in person_words):
word_count[word] += 1
不过,在将词传递给 WordNet 之前,您可能还需要使用词干提取或其他形态缩减对输入词进行预处理。
要获取同义词集的所有下位词,您可以使用以下function(使用 NLTK 3.0.3 测试,dhke 的闭包技巧在此版本上不起作用):
def get_hyponyms(synset):
hyponyms = set()
for hyponym in synset.hyponyms():
hyponyms |= set(get_hyponyms(hyponym))
return hyponyms | set(synset.hyponyms())
示例:
from nltk.corpus import wordnet
food = wordnet.synset('food.n.01')
print(len(get_hyponyms(food))) # returns 1526
对于一个项目,我想测量文本中“以人为本”的词的数量。我计划使用 WordNet 来完成这项工作。我从来没有使用过它,我不太确定如何处理这个任务。我想使用 WordNet 来计算属于某些同义词集的单词数量,例如 sysnets“human”和“person”。
我想出了以下(简单的)代码:
word = 'girlfriend'
word_synsets = wn.synsets(word)[0]
hypernyms = word_synsets.hypernym_paths()[0]
for element in hypernyms:
print element
结果:
Synset('entity.n.01')
Synset('physical_entity.n.01')
Synset('causal_agent.n.01')
Synset('person.n.01')
Synset('friend.n.01')
Synset('girlfriend.n.01')
我的第一个问题是,如何正确地迭代上位词?在上面的代码中,它打印得很好。但是,当使用“if”语句时,例如:
count_humancenteredness = 0
for element in hypernyms:
if element == 'person':
print 'found person hypernym'
count_humancenteredness +=1
我收到“AttributeError: 'str' object has no attribute '_name'”。当一个词确实属于“person”或“human”同义词集时,我可以使用什么方法来迭代我的词的上位词并执行一个动作(例如,增加以人为中心的计数)。
其次,这是一种有效的方法吗?我假设迭代几个文本和迭代每个名词的上位词将花费相当长的时间。也许还有另一种方法可以使用 WordNet 更有效地执行我的任务。
感谢您的帮助!
wrt 错误消息
hypernyms = word_synsets.hypernym_paths()
returns SynSet
s 列表的列表。
因此
if element == 'person':
尝试将 SynSet
对象与字符串进行比较。 SynSet
.
试试
target_synsets = wn.synsets('person')
if element in target_synsets:
...
或
if u'person' in element.lemma_names():
...
相反。
wrt 效率
目前,您对输入文本中的每个单词执行上位词查找。正如您所注意到的,这不一定有效。但是,如果这足够快,就到此为止,不要优化未损坏的部分。
为了加快查找速度,您可以预先编译一个“person related”单词的列表,方法是使用下位词的传递闭包,如解释的那样here.
类似
person_words = set(w for s in p.closure(lambda s: s.hyponyms()) for w in s.lemma_names())
应该可以解决问题。这将 return 一组 ~ 10,000
个单词,存储在主内存中不会太多。
单词计数器的一个简单版本然后变成了
from collections import Counter
word_count = Counter()
for word in (w.lower() for w in words if w in person_words):
word_count[word] += 1
不过,在将词传递给 WordNet 之前,您可能还需要使用词干提取或其他形态缩减对输入词进行预处理。
要获取同义词集的所有下位词,您可以使用以下function(使用 NLTK 3.0.3 测试,dhke 的闭包技巧在此版本上不起作用):
def get_hyponyms(synset):
hyponyms = set()
for hyponym in synset.hyponyms():
hyponyms |= set(get_hyponyms(hyponym))
return hyponyms | set(synset.hyponyms())
示例:
from nltk.corpus import wordnet
food = wordnet.synset('food.n.01')
print(len(get_hyponyms(food))) # returns 1526