在 spacy 中自定义 Tokenizer

customize Tokenizer in spacy

我正在使用 Spacy v2

我在文档中查找日期,我希望分词器将它们合并

例如:

doc= 'Customer: Johnna 26 06 1989'

默认分词器结果如下:

('Customer:', 'customer:', 'NUM', 'CD', 'amod', 'Xxxxx:', False, False)
('Johnna', 'Johnna ', 'PROPN', 'NNP', 'ROOT', 'xxxx', True, False)
('26', '26', 'NUM', 'CD', 'compound', 'dd', False, False)
('06', '06', 'NUM', 'CD', 'appos', 'dd', False, False)
('1989', '1989', 'NUM', 'CD', 'nummod', 'dddd', False, False)

虽然我希望它看起来像:

('Customer:', 'customer:', 'NUM', 'CD', 'amod', 'Xxxxx:', False, False)
('Johnna', 'Johnna ', 'PROPN', 'NNP', 'ROOT', 'xxxx', True, False)
('26 06 1989', '26', 'NUM', 'CD', 'compound', 'dd dd dd', False, False)

我尝试创建自定义分词器,但不确定是否需要更改前缀或后缀_ 以及如何定义大小写。

def __customize_tokenizer(self):
        prefix_re = re.compile(r'\d+\s+\d+')    
        return Tokenizer(self._nlp.vocab, prefix_search = prefix_re.search)

谢谢,

尼尔

分词器算法不支持这种模式:它不支持异常中的正则表达式,词缀模式不应用于空格。

相反,一种选择是使用 Matcher 查找这些案例,它确实支持正则表达式,并使用 retokenizer 合并标记:

import spacy
from spacy.matcher import Matcher

nlp = spacy.blank("en")
matcher = Matcher(nlp.vocab)
matcher.add("DATE", [[{"ORTH": {"REGEX": "\d\d"}}, {"ORTH": {"REGEX": "\d\d"}}, {"ORTH": {"REGEX": "\d\d\d\d"}}]])

text = "This is a date 01 02 2000 in a sentence."

doc = nlp(text)

with doc.retokenize() as retokenizer:
    for match_id, start, end in matcher(doc):
        retokenizer.merge(doc[start:end])

print([t.text for t in doc])
# ['This', 'is', 'a', 'date', '01 02 2000', 'in', 'a', 'sentence', '.']

如果需要,您可以将匹配和重新标记化放入管道开头的自定义组件中,请参阅:https://v2.spacy.io/usage/processing-pipelines#custom-components

您可以只使用 nlp.add_pipe("merge_entities"):

Merge named entities into a single token. Also available via the string name "merge_entities".

查看 Python 片段:

doc = nlp('Customer: Johnna 26 06 1989')
nlp.add_pipe("merge_entities")
print([(t.text, t.pos_, t.lemma_) for t in doc])
# => [
#      ('Customer', 'NOUN', 'customer'), 
#      (':', 'PUNCT', ':'), 
#      ('Johnna', 'PROPN', 'Johnna'),
#      ('26 06 1989', 'NUM', '26 06 1989')
#    ]