Есть ли способ отключить определенные встроенные правила токенизации в Spacy? - PullRequest
1 голос
/ 24 мая 2019

Spacy автоматически токенизирует сокращения слов, такие как "dont" и "not", в "do" и "nt" / "n't". Например, предложение типа «я не понимаю» будет разбито на: [«I», «do», «nt», «понимают»] .

Я понимаю, что это обычно полезно во многих задачах НЛП, но есть ли способ подавить это специальное правило токенизации в Spacy , чтобы результат был ["I", "dont", "понять"] вместо?

Это связано с тем, что я пытаюсь оценить производительность (f1-оценка для схемы тегов BIO) моей пользовательской модели Spacy NER и вызывает несоответствие количества токенов во входном предложении и количества предикатных тегов токенов. проблемы для моего кода оценки по линии:

  • Ввод (3 токена): [("I", "O"), ("dont", "O"), ("понять", "O")]

  • Предсказано (4 токена): [("I", "O"), ("do", "O"), ("nt", "O"), ("понять" , "О")]

Конечно, если у кого-то есть предложения по лучшему способу оценки задач последовательного тегирования в Spacy (возможно, как пакет seqeval , но более совместимый с форматом токенов Spacy), это было бы очень полезно а также.

1 Ответ

1 голос
/ 01 июня 2019

Правила токенизации в особом случае определены в tokenizer_exceptions.py в соответствующих данных языка ( см. Здесь для английских сокращений "nt").Когда вы создаете новый 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. Слияние (или разделение) токенов впоследствии

Альтернативным подходом было бы сохранитьтокенизация как таковая, но добавьте к ней правила, которые объединяют определенные токены обратно вместе, чтобы соответствовать желаемому токенизации.Это, очевидно, будет медленнее во время выполнения, но это может быть проще для реализации и рассуждений, потому что вы можете подойти к нему с точки зрения «Какие токены в настоящее время разделены, но должны быть единичными?».Для этого вы можете использовать на основе правил 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)

Приведенный выше шаблон будет соответствовать двум токенам (по одному dict на токен), чьи строчные буквы - "do" и "nt"(например," DONT "," Dont "," DoNt ").Вы можете добавить больше списков диктов к шаблонам, чтобы описать другие последовательности токенов.Для каждого совпадения вы можете создать Span и объединить его в один токен.Чтобы сделать эту логику более элегантной, вы можете также обернуть ее как пользовательский конвейерный компонент , чтобы она автоматически применялась при вызове nlp для текста.

...