2 回答
TA贡献1802条经验 获得超5个赞
Matcher 并不是真正合适的工具。您应该改为修改标记器。
如果您想保留其他所有内容的处理方式并且只更改连字符的行为,您应该修改现有的中缀模式并保留所有其他设置。当前的英文中缀模式定义在这里:
https://github.com/explosion/spaCy/blob/58533f01bf926546337ad2868abe7fc8f0a3b3ae/spacy/lang/punctuation.py#L37-L49
您可以在不定义自定义分词器的情况下添加新模式,但如果不定义自定义分词器,则无法删除模式。因此,如果您注释掉连字符模式并定义自定义标记器:
import spacy
from spacy.tokenizer import Tokenizer
from spacy.lang.char_classes import ALPHA, ALPHA_LOWER, ALPHA_UPPER, CONCAT_QUOTES, LIST_ELLIPSES, LIST_ICONS
from spacy.util import compile_infix_regex
def custom_tokenizer(nlp):
infixes = (
LIST_ELLIPSES
+ LIST_ICONS
+ [
r"(?<=[0-9])[+\-\*^](?=[0-9-])",
r"(?<=[{al}{q}])\.(?=[{au}{q}])".format(
al=ALPHA_LOWER, au=ALPHA_UPPER, q=CONCAT_QUOTES
),
r"(?<=[{a}]),(?=[{a}])".format(a=ALPHA),
#r"(?<=[{a}])(?:{h})(?=[{a}])".format(a=ALPHA, h=HYPHENS),
r"(?<=[{a}0-9])[:<>=/](?=[{a}])".format(a=ALPHA),
]
)
infix_re = compile_infix_regex(infixes)
return Tokenizer(nlp.vocab, prefix_search=nlp.tokenizer.prefix_search,
suffix_search=nlp.tokenizer.suffix_search,
infix_finditer=infix_re.finditer,
token_match=nlp.tokenizer.token_match,
rules=nlp.Defaults.tokenizer_exceptions)
nlp = spacy.load("en")
nlp.tokenizer = custom_tokenizer(nlp)
print([t.text for t in nlp("It's 1.50, up-scaled haven't")])
# ['It', "'s", "'", '1.50', "'", ',', 'up-scaled', 'have', "n't"]
在初始化新的 Tokenizer 以保留现有的 tokenizer 行为时,您确实需要提供当前的前缀/后缀/token_match 设置。另请参阅(德语,但非常相似):https ://stackoverflow.com/a/57304882/461847
编辑添加(因为这看起来确实不必要地复杂,你真的应该能够重新定义中缀模式而无需加载全新的自定义标记器):
如果您刚刚加载了模型(对于 v2.1.8)并且您还没有调用nlp(),您也可以直接替换infix_re.finditer而不创建自定义标记器:
nlp = spacy.load('en')
nlp.tokenizer.infix_finditer = infix_re.finditer
有一个缓存错误应该有望在 v2.2 中得到修复,它可以让它在任何时候都能正常工作,而不仅仅是新加载的模型。(否则这种行为非常令人困惑,这就是为什么创建自定义标记器对于 v2.1.8 来说是一个更好的通用建议。)
添加回答
举报