【问题标题】:Python NLTK Lemmatization of the word 'further' with wordnetPython NLTK 使用 wordnet 对“进一步”一词进行词形还原
【发布时间】:2014-05-24 19:45:00
【问题描述】:

我正在使用 python、NLTK 和 WordNetLemmatizer 开发词形分析器。 这是一个随机文本,输出我所期望的内容

from nltk.stem import WordNetLemmatizer
from nltk.corpus import wordnet
lem = WordNetLemmatizer()
lem.lemmatize('worse', pos=wordnet.ADJ) // here, we are specifying that 'worse' is an adjective

输出:'bad'

lem.lemmatize('worse', pos=wordnet.ADV) // here, we are specifying that 'worse' is an adverb

输出:'worse'

嗯,这里的一切都很好。行为与其他形容词相同,例如 'better'(对于不规则形式)或 'older'(请注意,与 'elder' 相同的测试将永远不会输出 'old',但我猜 wordnet 并不是一个详尽的列表所有现有的英文单词)

当我尝试使用'furter'这个词时,我的问题就来了:

lem.lemmatize('further', pos=wordnet.ADJ) // as an adjective

输出:'further'

lem.lemmatize('further', pos=wordnet.ADV) // as an adverb

输出:'far'

这与 'worse' 字的行为完全相反!

谁能解释我为什么?是来自 wordnet synsets 数据的错误还是来自我对英语语法的误解?

如果问题已经得到解答,请原谅,我已经在 google 和 SO 上搜索过,但是当指定关键字“进一步”时,由于这个词的流行,我可以找到任何相关的东西,除了混乱......

提前谢谢你, 罗曼 G.

【问题讨论】:

  • 很好地理解了 wordnet 的特殊性 =)

标签: python nltk wordnet lemmatization


【解决方案1】:

WordNetLemmatizer 使用._morphy 函数来访问其单词的引理;来自http://www.nltk.org/_modules/nltk/stem/wordnet.html 并返回最小长度的可能引理。

def lemmatize(self, word, pos=NOUN):
    lemmas = wordnet._morphy(word, pos)
    return min(lemmas, key=len) if lemmas else word

._morphy 函数迭代地应用规则以获得引理;规则不断减少单词的长度并将词缀替换为MORPHOLOGICAL_SUBSTITUTIONS。然后看是否还有其他更短但与缩减词相同的词:

def _morphy(self, form, pos):
    # from jordanbg:
    # Given an original string x
    # 1. Apply rules once to the input to get y1, y2, y3, etc.
    # 2. Return all that are in the database
    # 3. If there are no matches, keep applying rules until you either
    #    find a match or you can't go any further

    exceptions = self._exception_map[pos]
    substitutions = self.MORPHOLOGICAL_SUBSTITUTIONS[pos]

    def apply_rules(forms):
        return [form[:-len(old)] + new
                for form in forms
                for old, new in substitutions
                if form.endswith(old)]

    def filter_forms(forms):
        result = []
        seen = set()
        for form in forms:
            if form in self._lemma_pos_offset_map:
                if pos in self._lemma_pos_offset_map[form]:
                    if form not in seen:
                        result.append(form)
                        seen.add(form)
        return result

    # 0. Check the exception lists
    if form in exceptions:
        return filter_forms([form] + exceptions[form])

    # 1. Apply rules once to the input to get y1, y2, y3, etc.
    forms = apply_rules([form])

    # 2. Return all that are in the database (and check the original too)
    results = filter_forms([form] + forms)
    if results:
        return results

    # 3. If there are no matches, keep applying rules until we find a match
    while forms:
        forms = apply_rules(forms)
        results = filter_forms(forms)
        if results:
            return results

    # Return an empty list if we can't find anything
    return []

但是如果单词在例外列表中,它会返回一个保存在exceptions 中的固定值,参见http://www.nltk.org/_modules/nltk/corpus/reader/wordnet.html 中的_load_exception_map

def _load_exception_map(self):
    # load the exception file data into memory
    for pos, suffix in self._FILEMAP.items():
        self._exception_map[pos] = {}
        for line in self.open('%s.exc' % suffix):
            terms = line.split()
            self._exception_map[pos][terms[0]] = terms[1:]
    self._exception_map[ADJ_SAT] = self._exception_map[ADJ]

回到你的例子,worse -> badfurther -> far 不能从规则中实现,因此它必须来自例外列表。由于它是一个例外列表,因此必然存在不一致之处。

例外列表保存在~/nltk_data/corpora/wordnet/adv.exc~/nltk_data/corpora/wordnet/adv.exc

来自adv.exc

best well
better well
deeper deeply
farther far
further far
harder hard
hardest hard

来自adj.exc

...
worldliest worldly
wormier wormy
wormiest wormy
worse bad
worst bad
worthier worthy
worthiest worthy
wrier wry
...

【讨论】:

  • 按照你说的,我编辑了文件管理器adj.exc,并添加了行:further far。结果是:lem.lemmatize('further', pos=wordnet.ADJ) >> far。完美,非常感谢,这是一个很好的答案!
  • 哦,简单的更正,在我的情况下(Mac OS X),例外列表保存在~/nltk_data/corpora/wordnet/*.exc(而不是~/nltk_data/wordnet/*.exc)中。
  • 嗨@alvas 已经有一段时间了 - 尝试对 noun.exc 和 lem.lemmatize('investment', pos=wordnet.NOUN) 使用相同的方法没有在例外列表中返回我的映射.知道可能出了什么问题吗?
猜你喜欢
  • 2015-09-10
  • 2018-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多