【问题标题】:Python nltk incorrect sentence tokenization with custom abbrevations使用自定义缩写的 Python nltk 不正确的句子标记化
【发布时间】:2020-03-18 10:43:54
【问题描述】:

我正在使用nltk tokenize 库来拆分英文句子。 许多句子包含诸如e.g.eg. 之类的缩写,因此我用这些自定义缩写更新了标记器。 不过,我发现了一个奇怪的标记化行为:

import nltk

nltk.download("punkt")
sentence_tokenizer = nltk.data.load("tokenizers/punkt/english.pickle")

extra_abbreviations = ['e.g', 'eg']
sentence_tokenizer._params.abbrev_types.update(extra_abbreviations)

line = 'Required experience with client frameworks (e.g. React, Vue.js) and testing (e.g. Karma, Tape)'

for s in sentence_tokenizer.tokenize(line):
    print(s)

# OUTPUT
# Required experience with client frameworks (e.g. React, Vue.js) and testing (e.g.
# Karma, Tape)

如您所见,分词器不会在第一个缩写(正确)上拆分,但在第二个缩写(不正确)上拆分。

奇怪的是,如果我将Karma 这个词改成其他任何东西,它就可以正常工作。

import nltk

nltk.download("punkt")
sentence_tokenizer = nltk.data.load("tokenizers/punkt/english.pickle")

extra_abbreviations = ['e.g', 'eg']
sentence_tokenizer._params.abbrev_types.update(extra_abbreviations)

line = 'Required experience with client frameworks (e.g. React, Vue.js) and testing (e.g. SomethingElse, Tape)'

for s in sentence_tokenizer.tokenize(line):
    print(s)

# OUTPUT
# Required experience with client frameworks (e.g. React, Vue.js) and testing (e.g. SomethingElse, Tape)

任何线索为什么会发生这种情况?

【问题讨论】:

    标签: python nlp nltk tokenize


    【解决方案1】:

    您可以看到为什么 punkt 使用 debug_decisions 方法做出中断选择。

    >>> for d in sentence_tokenizer.debug_decisions(line):
    ...     print(nltk.tokenize.punkt.format_debug_decision(d))
    ... 
    Text: '(e.g. React,' (at offset 47)
    Sentence break? None (default decision)
    Collocation? False
    'e.g.':
        known abbreviation: True
        is initial: False
    'react':
        known sentence starter: False
        orthographic heuristic suggests is a sentence starter? unknown
        orthographic contexts in training: {'MID-UC', 'MID-LC'}
    
    Text: '(e.g. Karma,' (at offset 80)
    Sentence break? True (abbreviation + orthographic heuristic)
    Collocation? False
    'e.g.':
        known abbreviation: True
        is initial: False
    'karma':
        known sentence starter: False
        orthographic heuristic suggests is a sentence starter? True
        orthographic contexts in training: {'MID-LC'}
    
    

    这告诉我们在用于训练的语料库中,“react”和“React”都出现在句子的中间,所以它不会在你的行中的“React”之前中断。但是,仅出现小写形式的“业力”,因此它认为这是一个可能的句子起点。

    注意,这与库的文档一致:

    但是,Punkt 旨在从类似于目标域的语料库中无监督地学习参数(缩写列表等)。因此,预打包的模型可能不适合:使用PunktSentenceTokenizer(text) 从给定文本中学习参数。

    PunktTrainer 从文本部分学习参数,例如缩写列表(无监督)。直接使用PunktTrainer 允许增量训练和修改用于决定什么被视为缩写等的超参数。

    因此,虽然针对这种特殊情况的快速破解是调整私人 _params 进一步说“业力”也可能出现在句子中间:

    >>> sentence_tokenizer._params.ortho_context['karma'] |= nltk.tokenize.punkt._ORTHO_MID_UC
    >>> sentence_tokenizer.tokenize(line)
    ['Required experience with client frameworks (e.g. React, Vue.js) and testing (e.g. Karma, Tape)']
    

    也许您应该从包含所有这些库名称的 CV 中添加额外的训练数据:

    from nltk.tokenize.punkt import PunktSentenceTokenizer, PunktTrainer
    trainer = PunktTrainer()
    # tweak trainer params here if helpful
    trainer.train(my_corpus_of_concatted_tech_cvs)
    sentence_tokenizer = PunktSentenceTokenizer(trainer.get_params())
    

    【讨论】:

    • 感谢您的回答,非常有用。不幸的是,这只是一个例子,有很多句子有同样的问题。如果前一个标记是缩写,有没有办法建议忽略启发式(大写标记)?
    • @revy 已编辑以澄清我使用您自己的训练数据的意思。
    • 我很欣赏如何训练分词器的例子。我在文档中没有找到。
    猜你喜欢
    • 2012-01-12
    • 2019-08-07
    • 2011-08-12
    • 1970-01-01
    • 2016-04-20
    • 2011-08-20
    • 1970-01-01
    • 2022-09-30
    相关资源
    最近更新 更多