Уберите токен отрицания и верните отрицательное предложение в Spacy - PullRequest
0 голосов
/ 03 марта 2019

Я хочу использовать анализатор зависимостей spaCy, чтобы определить область отрицания в моих документах.См. здесь визуализатор зависимостей, примененный к следующей строке:

RT @trader $AAPL 2012 is ooopen to Talk about patents with GOOG definitely not the treatment Samsung got heh someURL

Я могу обнаружить сигналы отрицания с

 negation_tokens = [tok for tok in doc if tok.dep_ == 'neg']

В результате я вижу, что not - это модификатор отрицания got в моей строке.Теперь я хочу определить сферу отрицания следующим образом:

negation_head_tokens = [token.head for token in negation_tokens]   
for token in negation_head_tokens:
    end = token.i
    start = token.head.i + 1
    negated_tokens = doc[start:end]
    print(negated_tokens)

Это дает следующий вывод:

 ooopen to Talk about patents with GOOG definitely not the treatment Samsung

Теперь я определил сферу, я хочу добавить "not" для определенных слов, зависящих от их POS-тега

list = ['ADJ', 'ADV', 'AUX', 'VERB']
for token in negated_tokens:
    for i in list:
        if token.pos_ == i:
            print('not'+token.text)

Это дает следующее:

 notooopen, notTalk, notdefinitely, notnot

Я хочу исключить notnot из моего вывода и возврата

RT @trader $AAPL 2012 is notooopen to notTalk about patents with GOOG notdefinitely the treatment Samsung got heh someurl

Как мне этого добиться?И видите ли вы улучшения в моем сценарии с точки зрения скорости?

Полный сценарий:

import spacy

nlp = spacy.load("en_core_web_sm")
doc = nlp(u'RT @trader $AAPL 2012 is ooopen to Talk about patents with GOOG definitely not the treatment Samsung got heh someURL)
list = ['ADJ', 'ADV', 'AUX', 'VERB']

negation_tokens = [tok for tok in doc if tok.dep_ == 'neg']
negation_head_tokens = [token.head for token in negation_tokens]

for token in negation_head_tokens:
   end = token.i
   start = token.head.i + 1
   negated_tokens = doc[start:end]
   for token in negated_tokens:
      for i in list:
         if token.pos_ == i:
            print('not'+token.text)

1 Ответ

0 голосов
/ 03 марта 2019
  1. Плохо было бы переопределять встроенные модули Python, такие как list - я переименовал его pos_list.

  2. Поскольку "not" - это просто обычноеНаречие, кажется, самый простой способ избежать этого было бы с явным черным списком.Возможно, есть более «лингвистический» способ сделать это.

  3. Я немного ускорил ваш внутренний цикл.

Код:

doc = nlp(u'RT @trader $AAPL 2012 is ooopen to Talk about patents with GOOG definitely not the treatment Samsung got heh someURL')

pos_list = ['ADJ', 'ADV', 'AUX', 'VERB']
negation_tokens = [tok for tok in doc if tok.dep_ == 'neg']
blacklist = [token.text for token in negation_tokens]
negation_head_tokens = [token.head for token in negation_tokens]
new_doc = []

for token in negation_head_tokens:
    end = token.i
    start = token.head.i + 1
    left, right = doc[:start], doc[:end] 
    negated_tokens = doc[start:end]
for token in doc:
    if token in negated_tokens:
        if token.pos_ in pos_list and token.text not in blacklist:

        # or you can leave out the blacklist and put it here directly
        # if token.pos_ in pos_list and token.text not in [token.text for token in negation_tokens]:
            new_doc.append('not'+token.text)
            continue
        else:
            pass
    new_doc.append(token.text)
print(' '.join(new_doc))

> RT @trader $ AAPL 2012 is notooopen to notTalk about patents with GOOG notdefinitely not the treatment Samsung got heh someURL
...