Spacy Matcher / PhraseMatcher Span, как расширить span до текущего предложения? - PullRequest
0 голосов
/ 10 марта 2019

У меня есть текст: «Алфавит - это компания. Также она стоит за Google. Но это не одно и то же».
На основе примененного совпадения пространств возвращает метку, начало и конец совпадений.
Теперь, основываясь на начале и конце, есть ли способ расширить диапазон до целого предложения (слово, которое заканчивается точкой)?

{

    matches = self.matcher(doc)
            spans = []
            for label, start, end in matches:
                span = Span(doc, start, end, label=label)

}

Итак, ожидаемый результат приведен ниже ....

Фактический

Entities[('Alphabet','myORG'),('Google','myORG')] 

Ожидая

Entities[('Alphabet is a company','myORG'),('Also it is behind Google','myORG')] 

Код, который я использовал:

{

    from __future__ import unicode_literals, print_function
    import plac
    from spacy.lang.en import English
    from spacy.matcher import PhraseMatcher
    from spacy.tokens import Doc, Span, Token
    def main(text="Alphabet is a company. Also it is behind Google. But these are not the same", *companies):
        nlp = English()
        if not companies: 
            companies = ['Alphabet', 'Google', 'Netflix', 'Apple']
        component = myFindingsMatcher(nlp, companies)
        nlp.add_pipe(component, last=True)
        doc = nlp(text)
        print('Entities', [(e.text, e.label_) for e in doc.ents])  # all orgs are entities
    class myFindingsMatcher(object):
        name = 'myFindings_matcher'
        def __init__(self, nlp, companies=tuple(), label='myORG'):
            patterns = [nlp(finding_type) for finding_type in companies]
            self.matcher = PhraseMatcher(nlp.vocab)
            self.matcher.add(label, None, *patterns)
        def __call__(self, doc):
            matches = self.matcher(doc)
            spans = []
            for label, start, end in matches:
                span = Span(doc, start, end, label=label)
                spans.append(span)
            doc.ents = spans
            return doc
    if __name__ == '__main__':
        plac.call(main)

}

Спасибо.

1 Ответ

0 голосов
/ 11 марта 2019

Атрибут e.sent используется для ссылки на предложение, содержащее сущность e.

Минимальный рабочий пример с предварительно скомпилированной моделью en_core_web_sm и встроенным Matcher:

my_text = "Alphabet is a company. Also it is behind Google. But these are not the same"
nlp = spacy.load('en_core_web_sm')
doc = nlp(my_text)
print('Entities', [(e.text, e.label_, e.sent) for e in doc.ents])  

Это производит

Сущности [(«Алфавит», «ORG», «Алфавит» - это компания.), («Google», «ORG», также за Google.)]

Если вы хотите реализовать свой собственный механизм сопоставления, используя nlp = English(), вам нужно будет добавить модуль для распознавания предложений:

nlp.add_pipe(nlp.create_pipe('sentencizer'))

И вам нужно будет убедиться, что e.sent установлен правильно при определении диапазонов сущностей. Обратите внимание, что вы можете легко определить правильный диапазон, взглянув на смещения предложений (считая токены):

print('Sentences', [(s.start, s.end, s.text) for s in doc.sents])
print('Entities', [(e.start, e.end, e.text, e.label_) for e in doc.ents]) 

будет печатать

Предложения [(0, 5, «Алфавит - это компания.»), (5, 11, «И это отстает от Google.»), (11, 17, «Но это не одно и то же»)]

Объекты [(0, 1, «Алфавит», «ORG»), (9, 10, «Google», «ORG»)]

...