【问题标题】:Python NLTK WUP Similarity Score not unity for exact same wordPython NLTK WUP 相似度分数对于完全相同的单词不统一
【发布时间】:2015-09-01 14:16:59
【问题描述】:

如下所示的简单代码给出了两种情况的相似度得分 0.75。如您所见,这两个词完全相同。为了避免任何混淆,我还将一个词与它本身进行了比较。分数从 0.75 开始下降。这是怎么回事?

from nltk.corpus import wordnet as wn
actual=wn.synsets('orange')[0]
predicted=wn.synsets('orange')[0]
similarity=actual.wup_similarity(predicted)
print similarity
similarity=actual.wup_similarity(actual)
print similarity

【问题讨论】:

  • 这确实很奇怪。我希望有一个 1.0,但我想我知道原因。如果没有其他人这样做,我明天早上有空时会回复。
  • 谢谢。让我也快速指出,这也发生在其他词上。此外,即使我明确写出字符串也会发生这种情况。例如,即使变量定义为actual=wn.synset('apple.n.01') predicted=wn.synset('apple.n.01'),也会发生错误。忽略多次编辑,我想在评论中添加一个换行符,这显然是不可能的
  • 希望回答对你有帮助=)

标签: python nlp nltk similarity


【解决方案1】:

这是一个有趣的问题。

TL;DR

对不起,这个问题没有简短的答案 =(


太长了,想看

查看wup_similarity() 的代码,问题不在于相似度计算,而在于NLTK 遍历WordNet 层次结构以获取lowest_common_hypernym() 的方式(参见https://github.com/nltk/nltk/blob/develop/nltk/corpus/reader/wordnet.py#L805)。

通常,同义词集与其自身之间的最低共同上位词必须是自身:

>>> from nltk.corpus import wordnet as wn
>>> y = wn.synsets('car')[0]
>>> y.lowest_common_hypernyms(y, use_min_depth=True)
[Synset('car.n.01')]

但在orange 的情况下,它也给出fruit

>>> from nltk.corpus import wordnet as wn
>>> x = wn.synsets('orange')[0]
>>> x.lowest_common_hypernyms(x, use_min_depth=True)
[Synset('fruit.n.01'), Synset('orange.n.01')]

我们必须从https://github.com/nltk/nltk/blob/develop/nltk/corpus/reader/wordnet.py#L805 的文档字符串中查看lowest_common_hypernym() 的代码

获取两个同义词集作为上位词的最低同义词集列表。 当use_min_depth == False 这意味着同义词集显示为 返回具有最小最大深度的 selfother 的上位词 或者如果在同一深度有多个这样的同义词集,它们都会被返回 但是,如果 use_min_depth == True 则具有/具有最低的同义词集 返回两个路径中的最小深度和出现

所以让我们试试lowest_common_hypernym()use_min_depth=False

>>> x.lowest_common_hypernyms(x, use_min_depth=False)
[Synset('orange.n.01')]

似乎这样解决了绑定路径的歧义。但是wup_similarity() API 没有use_min_depth 参数:

>>> x.wup_similarity(x, use_min_depth=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: wup_similarity() got an unexpected keyword argument 'use_min_depth'

注意区别在于use_min_depth==False 时,lowest_common_hypernym 在遍历同义词集时检查最大深度。但是当use_min_depth==True 时,它会检查最小深度,请参阅https://github.com/nltk/nltk/blob/develop/nltk/corpus/reader/wordnet.py#L602

因此,如果我们追踪最低通用的超词代码:

>>> synsets_to_search = x.common_hypernyms(x)
>>> synsets_to_search
[Synset('citrus.n.01'), Synset('natural_object.n.01'), Synset('orange.n.01'), Synset('object.n.01'), Synset('plant_organ.n.01'), Synset('edible_fruit.n.01'), Synset('produce.n.01'), Synset('food.n.02'), Synset('physical_entity.n.01'), Synset('entity.n.01'), Synset('reproductive_structure.n.01'), Synset('solid.n.01'), Synset('matter.n.03'), Synset('plant_part.n.01'), Synset('fruit.n.01'), Synset('whole.n.02')]

# if use_min_depth==True
>>> max_depth = max(x.min_depth() for x in synsets_to_search)
>>> max_depth
8
>>> unsorted_lowest_common_hypernym = [s for s in synsets_to_search if s.min_depth() == max_depth]
>>> unsorted_lowest_common_hypernym
[Synset('orange.n.01'), Synset('fruit.n.01')]
>>> 
# if use_min_depth==False
>>> max_depth = max(x.max_depth() for x in synsets_to_search)
>>> max_depth
11
>>> unsorted_lowest_common_hypernym = [s for s in synsets_to_search if s.max_depth() == max_depth]
>>> unsorted_lowest_common_hypernym
[Synset('orange.n.01')]

这种带有wup_similarity的奇怪现象实际上在代码cmets中突出显示,https://github.com/nltk/nltk/blob/develop/nltk/corpus/reader/wordnet.py#L843

# Note that to preserve behavior from NLTK2 we set use_min_depth=True
# It is possible that more accurate results could be obtained by
# removing this setting and it should be tested later on
subsumers = self.lowest_common_hypernyms(other, simulate_root=simulate_root and need_root, use_min_depth=True)

当列表中的第一个 subsumer 在https://github.com/nltk/nltk/blob/develop/nltk/corpus/reader/wordnet.py#L843被选中时:

subsumer = subsumers[0]

当然,在橙色同义词的情况下,首先选择水果,因为它是列表中与最低常用上位词相关的第一个。

总而言之,默认参数是一种功能,而不是像 NLTK v2.x 那样保持可重复性的错误。

因此解决方案可能是手动更改 NLTK 源以强制 use_min_depth=False

https://github.com/nltk/nltk/blob/develop/nltk/corpus/reader/wordnet.py#L845


已编辑

要解决此问题,您可能可以对相同的同义词进行临时检查:

def wup_similarity_hacked(synset1, synset2):
  if synset1 == synset2:
    return 1.0
  else:
    return synset1.wup_similarity(synset2)

【讨论】:

  • 您应该在 NLTK github repo 或 google-dev 组 groups.google.com/forum/#!forum/nltk-dev 中提出这个问题
  • @alvas 的回复太棒了。非常感谢。我确实会在 repo 中打开一个问题并在 google-dev 上发布关于此的内容。但与此同时,我希望有一个快速(呃)修复。我使用树冠,但我不确定如何使用更改后的代码与之集成。我希望该函数有一个参数来关闭它。但这是一个非常有用的答案,再次感谢。
  • 您可以在运行 wup_similarity 之前尝试临时检查。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-07
  • 1970-01-01
  • 2019-07-02
  • 1970-01-01
  • 2021-06-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多