特殊情况标记化规则在相应语言数据的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 Matcher 和retokenizer 将匹配的标记重新合并在一起。从 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 时,它会自动应用。