为什么NLTK中的wn.all_synsets()函数在WordNet中不能返回同义词集列表?

3

我为这个问题编写代码:

名词同义词集中有多少百分比没有下位词?您可以使用wn.all_synsets('n')获取所有名词同义词集。

这是我的代码:

import nltk
from nltk.corpus import wordnet as wn

all_noun = wn.all_synsets('n')
print(all_noun)
print(wn.all_synsets('n'))
all_num = len(set(all_noun))
noun_have_hypon = [word for word in wn.all_synsets('n') if len(word.hyponyms()) >= 1]
noun_have_num = len(noun_have_hypon)
print('There are %d nouns, and %d nouns without hyponyms, the percentage is %f' %
  (all_num, noun_have_num, (all_num-noun_have_num)/all_num*100))

当我运行这段代码时,输出结果为:

<generator object all_synsets at 0x10927b1b0>

<generator object all_synsets at 0x10e6f0bd0>

有82115个名词,其中16693个没有下位词,所占比例为79.671193

但如果将

noun_have_hypon = [word for word in wn.all_synsets('n') if len(word.hyponyms()) >= 1]

改为

noun_have_hypon = [word for word in all_noun if len(word.hyponyms()) >= 1]

输出结果会变成

<generator object all_synsets at 0x10917b1b0>

<generator object all_synsets at 0x10e46aab0>

有82115个名词,其中0个没有下位词,所占比例为100.000000

为什么两者不相等尽管all_noun = wn.all_synsets('n'),而0x10927b1b0和0x10e6f0bd0的意义是什么?

0x10927b1b0和0x10e6f0bd0只是内存位置,这意味着wordnet.all_synets()返回的任何对象都没有定义有意义的__str__方法。 - grochmal
@grochmal,明白了!谢谢!!! - 李恒通
1个回答

6

这与NLTK无关,更多的是生成器表达式 vs. 列表推导式之间的区别。

让我们通过一个小例子来说明:

首先,让我们创建一个返回简单列表的函数:

>>> def some_func_that_returns_a_list():
...     list_to_be_returned = []
...     for i in range(10):
...             list_to_be_returned.append(i)
...     return list_to_be_returned
... 
>>> some_func_that_returns_a_list()
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

请注意,在some_func_that_returns_a_list()函数中,需要创建一个列表并将值放入其中,然后函数才能返回到调用它的代码位置。
同样地,我们可以使用生成器来实现需要返回的相同列表,但是使用了yield关键字,稍有不同:
>>> def some_func_that_returns_a_generator():
...     for i in range(10):
...             yield i
... 
>>> 

请注意,在该函数中没有实例化要返回的列表。
当您尝试调用该函数时:
>>>some_func_that_returns_a_generator()
<generator object some_func_that_returns_a_generator at 0x7f312719a780>

你会收到生成器的字符串表示,即描述该函数的内容。此时,还没有实例化任何值,并且生成器的指针应该比实例化列表的函数小:
>>> import sys
>>> sys.getsizeof(some_func_that_returns_a_generator())
80
>>> sys.getsizeof(some_func_that_returns_a_list())
200

由于生成器不会实例化所需的列表值,它只会逐个弹出正在yield的项目,因此您需要“手动”循环遍历生成器以获取列表,例如:

>>> list(some_func_that_returns_a_generator())
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [i for i in some_func_that_returns_a_generator()]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

但在这种情况下,它是“即时”创建列表,如果您不想停止列表,而是逐个读取元素,则生成器会更有优势(就内存而言)。

另请参见:


因此,在NLTK wn.all_synsets() WordNet API的情况下,您可以简单地执行以下操作:

>>> from nltk.corpus import wordnet as wn
>>> nouns_in_wordnet = list(wn.all_synsets('n'))

但请注意,它会将所有名词Synsets保存在内存中。
如果您想筛选具有超过1个上位词的名词,可以使用filter()函数避免实例化完整的名词列表。
>>> filter(lambda ss: len(ss.hypernyms()) > 0, wn.all_synsets('n'))

最后,如果不将Synsets存储在内存中而是实时计算它们的数量,可以这样做:
>>> len(filter(lambda ss: len(ss.hypernyms()) > 0, wn.all_synsets('n')))
74389

或者更简洁地说:
>>> sum(1 for ss in wn.all_synsets('n') if len(ss.hypernyms()) > 0)
74389

但是最有可能的是,您想要访问Synsets,因此您可能正在寻找:
>>> nouns_with_hyper = filter(lambda ss: len(ss.hypernyms()) > 0, wn.all_synsets('n'))
>>> len(nouns_with_hyper)
74389

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