【问题标题】:Is there a way to turn off specific built-in tokenization rules in Spacy?有没有办法在 Spacy 中关闭特定的内置标记化规则?
【发布时间】:2019-05-24 09:17:19
【问题描述】:

Spacy 自动将诸如“dont”和“don't”之类的单词缩写标记为“do”和“nt”/“n't”。例如,像“我不明白”这样的句子将被标记为:[“I”、“do”、“nt”、“understand”]

我知道这通常对许多 NLP 任务很有帮助,但是有没有办法抑制这个 special tokenization rule in Spacy 使得结果是 ["I", "dont", "understand"]反而?

这是因为我正在尝试评估我的自定义 Spacy NER 模型的性能(BIO 标记方案的 f1-score),并且输入句子中的标记数量与谓词标记的数量不匹配导致我的评估代码存在问题:

  • 输入(3 个标记):[("I", "O"), ("dont", "O"), ("understand", "O")]

  • 预测(4 个标记):[("I", "O"), ("do", "O"), ("nt", "O"), ("understand" , "O")]

当然,如果有人对在 Spacy 中对顺序标记任务执行评估的更好方法有任何建议(可能像 seqeval 包,但与 Spacy 的令牌格式更兼容),那也将不胜感激。

【问题讨论】:

  • 如果您需要空格标记器,请参阅spacy.io/usage/linguistic-features#custom-tokenizer-example
  • @WiktorStribiżew 感谢您的评论。我在寻找潜在解决方案时确实考虑了这一点,但我没有立即尝试,因为它不会摆脱逗号和句号等尾随标点符号。在看到您的评论后试一试,结果证明这足以解决我的问题,我意识到在处理的输入数据中已经处理了尾随标点符号。出于好奇,除了制作自己的自定义标记器并仅重新实现所需的规则之外,是否没有办法选择性地停用一些特殊情况标记化规则?

标签: nlp tokenize spacy


【解决方案1】:

特殊情况标记化规则在相应语言数据的tokenizer_exceptions.py 中定义(see here 用于英语“nt”缩写)。创建new Tokenizer 时,可以通过rules 参数传入这些特殊情况规则。

方法 1:具有不同特殊情况规则的自定义分词器

因此,您可以为您的用例做的一件事是使用相同的前缀、后缀和中缀规则重构英语 Tokenizer,但只有一组过滤的标记器异常。标记器异常由字符串键入,因此您可以删除 "dont" 的条目以及您需要的任何其他内容。但是,代码非常冗长,因为您正在重建整个标记器:

from spacy.lang.en import English
from spacy.lang.punctuation import TOKENIZER_PREFIXES, TOKENIZER_SUFFIXES, TOKENIZER_INFIXES                                                                          
from spacy.lang.en import TOKENIZER_EXCEPTIONS  
from spacy.tokenizer import Tokenizer
from spacy.util import compile_prefix_regex, compile_suffix_regex, compile_infix_regex

prefix_re = compile_prefix_regex(TOKENIZER_PREFIXES).search
suffix_re = compile_suffix_regex(TOKENIZER_SUFFIXES).search
infix_re = compile_infix_regex(TOKENIZER_INFIXES).finditer
filtered_exc = {key: value for key, value in TOKENIZER_EXCEPTIONS.items() if key not in ["dont"]} 

nlp = English()
tokenizer = Tokenizer(
    nlp.vocab, 
    prefix_search=prefix_re, 
    suffix_search=suffix_re, 
    infix_finditer=infix_re, 
    rules=filtered_exc
)
nlp.tokenizer = tokenizer
doc = nlp("I dont understand")

方法 2:事后合并(或拆分)令牌

另一种方法是保持标记化不变,但在顶部添加规则 merge 某些标记向后重新组合在一起以匹配所需的标记化。这显然在运行时会变慢,但它可能更容易实现和推理,因为您可以从“哪些令牌当前被分离但应该是一个?”的角度来处理它。为此,您可以使用rule-based Matcherretokenizer 将匹配的标记重新合并在一起。从 spaCy v2.1 开始,它还支持拆分,以防万一。

from spacy.lang.en import English
from spacy.matcher import Matcher

nlp = English()
matcher = Matcher(nlp.vocab)
patterns = [[{"LOWER": "do"}, {"LOWER": "nt"}]]
matcher.add("TO_MERGE", None, *patterns)

doc = nlp("I dont understand")
matches = matcher(doc)
with doc.retokenize() as retokenizer:
    for match_id, start, end in matches:
        span = doc[start:end]
        retokenizer.merge(span)

上述模式将匹配两个标记(每个标记一个字典),其小写形式是“do”和“nt”(例如“DONT”、“dont”、“DoNt”)。您可以在模式中添加更多字典列表来描述其他标记序列。对于每个匹配项,您可以创建一个 Span 并将其合并到一个令牌中。为了使这个逻辑更优雅,您还可以将其包装为 custom pipeline component,这样当您在文本上调用 nlp 时,它会自动应用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-24
    • 1970-01-01
    • 1970-01-01
    • 2017-02-24
    • 1970-01-01
    • 1970-01-01
    • 2018-08-24
    相关资源
    最近更新 更多