Распознавание именованных сущностей при извлечении аспектного мнения с использованием сопоставления правил зависимостей - PullRequest
7 голосов
/ 01 апреля 2020

Используя Spacy, я извлекаю пары аспект-мнение из текста на основе определенных мной правил грамматики. Правила основаны на POS-тегах и тегах зависимостей, которые получают с помощью token.pos_ и token.dep_. Ниже приведен пример одного из правил грамматики. Если я пропущу предложение Japan is cool,, оно вернет [('Japan', 'cool', 0.3182)], где значение представляет полярность cool.

Однако я не знаю, как заставить его распознавать Именованные объекты. Например, если я передаю Air France is cool, я хочу получить [('Air France', 'cool', 0.3182)], но в настоящее время я получаю [('France', 'cool', 0.3182)].

Я проверил онлайн-документацию Spacy и знаю, как извлечь NE (doc.ents). Но я хочу знать, какой возможный обходной путь должен заставить мой экстрактор работать. Обратите внимание, что я не хочу принудительных мер, таких как объединение строк AirFrance, Air_France и c.

Спасибо!

import spacy

nlp = spacy.load("en_core_web_lg-2.2.5")
review_body = "Air France is cool."
doc=nlp(review_body)

rule3_pairs = []

for token in doc:

    children = token.children
    A = "999999"
    M = "999999"
    add_neg_pfx = False

    for child in children :
        if(child.dep_ == "nsubj" and not child.is_stop): # nsubj is nominal subject
            A = child.text

        if(child.dep_ == "acomp" and not child.is_stop): # acomp is adjectival complement
            M = child.text

        # example - 'this could have been better' -> (this, not better)
        if(child.dep_ == "aux" and child.tag_ == "MD"): # MD is modal auxiliary
            neg_prefix = "not"
            add_neg_pfx = True

        if(child.dep_ == "neg"): # neg is negation
            neg_prefix = child.text
            add_neg_pfx = True

    if (add_neg_pfx and M != "999999"):
        M = neg_prefix + " " + M

    if(A != "999999" and M != "999999"):
        rule3_pairs.append((A, M, sid.polarity_scores(M)['compound']))

Результат

rule3_pairs
>>> [('France', 'cool', 0.3182)]

желаемый выход

rule3_pairs
>>> [('Air France', 'cool', 0.3182)]

1 Ответ

7 голосов
/ 05 апреля 2020

Очень легко интегрировать сущности в ваш экстрактор. Для каждой пары дочерних элементов вы должны проверить, является ли дочерний элемент «A» главой некоторой именованной сущности, и если это правда, вы используете всю сущность в качестве своего объекта.

Здесь я предоставляю весь код

!python -m spacy download en_core_web_lg
import nltk
nltk.download('vader_lexicon')

import spacy
nlp = spacy.load("en_core_web_lg")

from nltk.sentiment.vader import SentimentIntensityAnalyzer
sid = SentimentIntensityAnalyzer()


def find_sentiment(doc):
    # find roots of all entities in the text
    ner_heads = {ent.root.idx: ent for ent in doc.ents}
    rule3_pairs = []
    for token in doc:
        children = token.children
        A = "999999"
        M = "999999"
        add_neg_pfx = False
        for child in children:
            if(child.dep_ == "nsubj" and not child.is_stop): # nsubj is nominal subject
                if child.idx in ner_heads:
                    A = ner_heads[child.idx].text
                else:
                    A = child.text
            if(child.dep_ == "acomp" and not child.is_stop): # acomp is adjectival complement
                M = child.text
            # example - 'this could have been better' -> (this, not better)
            if(child.dep_ == "aux" and child.tag_ == "MD"): # MD is modal auxiliary
                neg_prefix = "not"
                add_neg_pfx = True
            if(child.dep_ == "neg"): # neg is negation
                neg_prefix = child.text
                add_neg_pfx = True
        if (add_neg_pfx and M != "999999"):
            M = neg_prefix + " " + M
        if(A != "999999" and M != "999999"):
            rule3_pairs.append((A, M, sid.polarity_scores(M)['compound']))
    return rule3_pairs

print(find_sentiment(nlp("Air France is cool.")))
print(find_sentiment(nlp("I think Gabriel García Márquez is not boring.")))
print(find_sentiment(nlp("They say Central African Republic is really great. ")))

Вывод этого кода будет тем, что вам нужно:

[('Air France', 'cool', 0.3182)]
[('Gabriel García Márquez', 'not boring', 0.2411)]
[('Central African Republic', 'great', 0.6249)]

Наслаждайтесь!

...