Почему spaCy не сохраняет дефисы внутри слова во время токенизации, как это делает Stanford CoreNLP? - PullRequest
0 голосов
/ 12 сентября 2018

SpaCy Версия: 2.0.11

Версия Python: 3.6.5

ОС: Ubuntu 16.04

Примеры моих предложений:

Marketing-Representative- won't die in car accident.

или

Out-of-box implementation

Ожидаемые токены:

["Marketing-Representative", "-", "wo", "n't", "die", "in", "car", "accident", "."]

["Out-of-box", "implementation"]

SpaCyТокены (по умолчанию Tokenizer):

["Marketing", "-", "Representative-", "wo", "n't", "die", "in", "car", "accident", "."]

["Out", "-", "of", "-", "box", "implementation"]

Я попытался создать собственный токенизатор, но он не будет обрабатывать все крайние случаи, как обрабатывается spaCy с использованием tokenizer_exceptions(Код ниже):

import spacy
from spacy.tokenizer import Tokenizer
from spacy.util import compile_prefix_regex, compile_infix_regex, compile_suffix_regex
import re
nlp = spacy.load('en')
prefix_re = compile_prefix_regex(nlp.Defaults.prefixes)
suffix_re = compile_suffix_regex(nlp.Defaults.suffixes)
infix_re = re.compile(r'''[.\,\?\:\;\...\‘\’\`\“\”\"\'~]''')

def custom_tokenizer(nlp):
    return Tokenizer(nlp.vocab, prefix_search=prefix_re.search,
                                suffix_search=suffix_re.search,
                                infix_finditer=infix_re.finditer,
                                token_match=None)
nlp.tokenizer = custom_tokenizer(nlp)
doc = nlp("Marketing-Representative- won't die in car accident.")
for token in doc:
    print(token.text)

Вывод:

Marketing-Representative-
won
'
t
die
in
car
accident
.

Мне нужен кто-то, чтобы направить меня к подходящему способу сделать это.

Либо внесение изменений вприведенное выше регулярное выражение могло бы сделать это или любым другим способом, или я даже попробовал Matche-based Matcher от spaCy, но не смог создать правило для обработки дефисов между более чем двумя словами, например, «из коробки», чтобы можно было создать Matcher дляиспользоваться с span.merge ().

В любом случае мне нужно, чтобы слова, содержащие дефисы внутри слова, становились единым токеном, как это обрабатывает Stanford CoreNLP.

1 Ответ

0 голосов
/ 18 сентября 2018

Хотя это и не задокументировано на spacey сайте использования ,

Похоже, нам просто нужно добавить regex для * fix, с которым мы работаем, в данном случае - infix.

Кроме того, похоже, что мы можем расширить nlp.Defaults.prefixes с помощью пользовательского regex

infixes = nlp.Defaults.prefixes + (r"[./]", r"[-]~", r"(.'.)")

Это даст вам желаемый результат.Нет необходимости устанавливать значения по умолчанию prefix и suffix, так как мы не работаем с ними.

import spacy
from spacy.tokenizer import Tokenizer
from spacy.util import compile_prefix_regex, compile_infix_regex, compile_suffix_regex
import re

nlp = spacy.load('en')

infixes = nlp.Defaults.prefixes + (r"[./]", r"[-]~", r"(.'.)")

infix_re = spacy.util.compile_infix_regex(infixes)

def custom_tokenizer(nlp):
    return Tokenizer(nlp.vocab, infix_finditer=infix_re.finditer)

nlp.tokenizer = custom_tokenizer(nlp)

s1 = "Marketing-Representative- won't die in car accident."
s2 = "Out-of-box implementation"

for s in s1,s2:
    doc = nlp("{}".format(s))
    print([token.text for token in doc])

Результат

$python3 /tmp/nlp.py  
['Marketing-Representative-', 'wo', "n't", 'die', 'in', 'car', 'accident', '.']  
['Out-of-box', 'implementation']  

Возможно, вы захотите исправить регулярное выражение аддона, чтобы сделать его более устойчивым для других типов токенов, близких к применяемому регулярному выражению.

...