spaCy — добавление расширенной функции в конвейер вызывает переполнение стека

#python #spacy

#python #spacy

Вопрос:

Я пытаюсь добавить функцию сопоставления на основе правил в свой конвейер spaCy. Однако добавление ее в конвейер вызывает ошибку StackOverflow. Высокая вероятность, что это ошибка пользователя. Любые предложения или мысли будут с благодарностью приняты.

Запуск функции без добавления ее в конвейер работает нормально.

Пример кода:

 import spacy
from spacy.matcher import PhraseMatcher
from spacy.tokens import Span

nlp = spacy.load("en_core_web_sm")

def extend_matcher_entities(doc):
    matcher = PhraseMatcher(nlp.vocab, attr="SHAPE")
    matcher.add("TIME", None, nlp("0305Z"), nlp("1315z"),nlp("0830Z"),nlp("0422z"))

    new_ents = []
    for match_id, start, end in matcher(doc):
        new_ent = Span(doc, start, end, label=nlp.vocab.strings[match_id])
        new_ents.append(new_ent)
    
    doc.ents = new_ents
    return doc

# Add the component after the named entity recognizer
nlp.add_pipe(extend_matcher_entities, after='ner')

doc = nlp("At 0560z, I walked over to my car and got in to go to the grocery store.")

# extend_matcher_entities(doc)
print([(ent.text, ent.label_) for ent in doc.ents])
 

Этот пример из spacy code examples работает нормально:

 import spacy
from spacy.tokens import Span

nlp = spacy.load("en_core_web_sm")

def expand_person_entities(doc):
    new_ents = []
    for ent in doc.ents:
        if ent.label_ == "PERSON" and ent.start != 0:
            prev_token = doc[ent.start - 1]
            if prev_token.text in ("Dr", "Dr.", "Mr", "Mr.", "Ms", "Ms."):
                new_ent = Span(doc, ent.start - 1, ent.end, label=ent.label)
                print(new_ent)
                new_ents.append(new_ent)
        else:
            new_ents.append(ent)
    doc.ents = new_ents
    print(new_ents)
    return doc

# Add the component after the named entity recognizer
nlp.add_pipe(expand_person_entities, after='ner')

doc = nlp("Dr. Alex Smith chaired first board meeting of Acme Corp Inc.")
print([(ent.text, ent.label_) for ent in doc.ents])
 

Чего мне не хватает?

Ответ №1:

Нарушающая строка, из-за которой у вас есть циклическая ссылка, — это эта:

 matcher.add("TIME", None, nlp("0305Z"), nlp("1315z"),nlp("0830Z"),nlp("0422z"))
 

Уберите это из определения вашей функции, и все в порядке:

 import spacy
from spacy.matcher import PhraseMatcher
from spacy.tokens import Span

nlp = spacy.load("en_core_web_sm")
pattern = [nlp(t) for t in ("0305Z","1315z","0830Z","0422z")]


def extend_matcher_entities(doc):
    matcher = PhraseMatcher(nlp.vocab, attr="SHAPE")
    matcher.add("TIME", None, *pattern)

    new_ents = []
    for match_id, start, end in matcher(doc):
        new_ent = Span(doc, start, end, label=nlp.vocab.strings[match_id])
        new_ents.append(new_ent)
    
    doc.ents = new_ents
    # doc.ents = list(doc.ents)   new_ents
    return doc

# Add the component after the named entity recognizer
nlp.add_pipe(extend_matcher_entities, after='ner')

doc = nlp("At 0560z, I walked over to my car and got in to go to the grocery store.")

# extend_matcher_entities(doc)
print([(ent.text, ent.label_) for ent in doc.ents])
[('0560z', 'TIME')]
 

Также обратите внимание, doc.ents = new_ents что вы перезаписываете все объекты, извлеченные ранее