Как избежать двойного извлечения перекрывающихся паттернов в SpaCy с Matcher?

Мне нужно извлечь комбинацию элементов из 2 списков с помощью python Spacy Matcher. Проблема следующая: у нас есть 2 списка:

colors=['red','bright red','black','brown','dark brown']
animals=['fox','bear','hare','squirrel','wolf']

Я сопоставляю последовательности по следующему коду:

first_color=[]
last_color=[]
only_first_color=[]
for color in colors:
    if ' ' in color:
        first_color.append(color.split(' ')[0])
        last_color.append(color.split(' ')[1])
    else:
        only_first_color.append(color)
matcher = Matcher(nlp.vocab)

pattern1 = [{"TEXT": {"IN": only_first_color}},{"TEXT":{"IN": animals}}]
pattern2 = [{"TEXT": {"IN": first_color}},{"TEXT": {"IN": last_color}},{"TEXT":{"IN": animals}}]

matcher.add("ANIMALS", None, pattern1,pattern2)

doc = nlp('bright red fox met black wolf')

matches = matcher(doc)

for match_id, start, end in matches:
    string_id = nlp.vocab.strings[match_id]  # Get string representation
    span = doc[start:end]  # The matched span
    print(start, end, span.text)

Это дает результат:

0 3 bright red fox
1 3 red fox
4 6 black wolf

Как я могу извлечь только «ярко-рыжую лисицу» и «черный волк»? Следует ли мне изменить правила шаблонов или обработать совпадения?

Любые мысли ценю!


person Victoria    schedule 07.08.2020    source источник
comment
Что такое title?   -  person Wiktor Stribiżew    schedule 07.08.2020
comment
Извините, это была старая версия кода. Сейчас отредактировал.   -  person Victoria    schedule 07.08.2020


Ответы (1)


Вы можете использовать spacy.util.filter_spans:

Отфильтруйте последовательность объектов Span и удалите дубликаты или перекрытия. Полезно для создания именованных сущностей (где один токен может быть только частью одной сущности) или при объединении промежутков с помощью Retokenizer.merge . Когда пролеты перекрываются, (первый) самый длинный пролет предпочтительнее более коротких.

Код Python:

matches = matcher(doc)
spans = [doc[start:end] for _, start, end in matches]
for span in spacy.util.filter_spans(spans):
    print(span.start, span.end, span.text)

Выход:

0 3 bright red fox
4 6 black wolf
person Wiktor Stribiżew    schedule 07.08.2020
comment
большое спасибо! Это действительно элегантное решение. Я новичок в spacy и не знал о возможностях spacy.util.filter_spans. У меня это сработало очень хорошо. - person Victoria; 08.08.2020