spaCy: конец токена не соответствует тому, что я ожидаю - PullRequest
0 голосов
/ 28 июня 2018

С помощью spaCy (2.0.11 в соответствии с spacy.info()) я пытаюсь определить шаблоны токенов с помощью Matcher, но не получаю ожидаемых результатов. Смещения токенов в объектах сопоставления не соответствуют смещениям токенов, которым должно соответствовать в тексте.

Вот упрощенный фрагмент кода, чтобы показать, что я делаю:

import spacy
from spacy.matcher import Matcher

nlp = spacy.load('en')

text = "This has not gone far. The end."
doc = nlp(text)

pattern1 = [{'POS': 'VERB'}, {'LEMMA': 'not'}, {'POS': 'VERB'}] # match has not gone
pattern2 = [{'POS': 'DET'}, {'POS': 'NOUN'}] # match The end

matcher = Matcher(nlp.vocab)

matcher.add('rule1', None, pattern1)
matcher.add('rule2', None, pattern2)

matches = matcher(doc)

for match in matches:
    print(doc[match[1]], doc[match[2]], match)

Вывод, который я получаю:

has far (15137773209560627690, 1, 4)
The . (16952143625379849586, 6, 8)

Вывод, который я ожидаю:

has gone (15137773209560627690, 1, 3)
The end (16952143625379849586, 6, 7)

Таким образом, конечное смещение токена совпадения совпадает с токеном после последнего токена, соответствующего шаблону. Это ожидаемое поведение?

В более общем смысле, я пытаюсь создать поведение в стиле TokensRegex, заключающееся в возможности добавления пользовательских аннотаций к отдельным токенам в пределах определенного соответствия (например, добавление аннотации с отрицанием = TRUE к "has" и "шел "и отрицанию). = ИСТИННАЯ аннотация на наречие "не" в том же совпадении). Добавление единственной аннотации к совпадению с помощью функции обратного вызова возможно, но это не совсем то, что мне нужно. Возможно ли это (пока)?

1 Ответ

0 голосов
/ 28 июня 2018

Мне кажется, проблема в том, что вы смотрите только начальный и конечный токен , а не соответствующий диапазон. Индекс end диапазона всегда является эксклюзивным, поэтому doc[2:4] будет токеном от 2 до токена 4. Я только что попробовал ваш пример и напечатал текст каждого сопоставленного диапазона, и я вижу следующее выход:

for match_id, start, end in matches:
    span = doc[start:end]
    print(span.text)

# has not gone
# The end

Чтобы ответить на ваш второй вопрос: вы можете использовать настраиваемые атрибуты расширения , такие как token._.negated и token._.negation, чтобы достичь чего-то очень похожего. Если ваше правило отрицания совпадает, вы можете создать Span для совпадения, перебрать токены и установить соответствующие атрибуты. Чтобы сделать это более элегантным, вы можете также обернуть эту логику в конвейерный компонент , поэтому она запускается автоматически при вызове nlp для текста.

...