Анализ тональности, как мы объясняли ранее (см. Предыдущие статьи о типах и проблемах), исследует мнения, содержащиеся в письменной речи. Как специалист по данным, вы в большинстве случаев пытаетесь научить компьютер определять текст как положительный или отрицательный. Итак, когда вы анализируете какой-либо документ, вы следуете довольно простой процедуре: сначала вы разделяете документ на его компактные части (предложения, токены и части речи), затем вы определяете компоненты, несущие сантименты, и назначаете им оценка тональности. Окончательная оценка всего документа представляет собой взвешенную сумму оценок каждого компонента. На самом деле это не так сложно, но основная процедура довольно сложна.

Существует несколько методов реализации системы настроений, и мы классифицируем их как:

  1. Системы на основе правил полагаются на набор правил, определенных вручную.
  2. Автоматические системы используют методы машинного обучения, чтобы учиться на данных.
  3. Гибридные системы сочетают в себе как основанные на правилах, так и автоматические.

Анализ настроений на основе правил

Подходы, основанные на правилах, используют библиотеки настроений и ряд правил для определения полярности мнения по отношению к какому-либо предмету. Эти правила часто основываются на классических методах НЛП, таких как стемминг, токенизация, тегирование части речи и синтаксический анализ (подробнее о них читайте в нашей предыдущей статье). Сначала мы поговорим о библиотеках тональности, а после объясним основную процедуру и приведем вам пример.

Библиотеки настроений

Библиотеки тональности (или словари) - это большие коллекции прилагательных (например, красивый, великолепный, ужасный, ужасный и т. Д.), Наречий и фраз (например, очень со вкусом, отличный сервис, медленная зарядка и т. Д.), Которые были кем-то набраны вручную. . Эта ручная оценка может быть довольно сложной, потому что люди придают разные относительные веса одним и тем же словам, то есть ваш детектор настроений основан на вашем опыте и знаниях.

Например, я бы дал слову «неправильное» мнение -0,5, но кто-то другой поставил бы такую ​​же оценку слову «ужасно». Итак, наилучшим подходом было бы, чтобы несколько человек независимо оценивали все слова, а окончательная оценка для каждого слова - это среднее значение всех оценок. Я знаю, что это довольно утомительное время и ресурсы, но это окупается. Поскольку ваш мозг полагается на описательные слова, которые вы выучили в течение своей жизни, анализ настроений полагается на эти словари для выявления мнений. Лучшая библиотека - лучший детектор настроений. Обратной стороной является то, что эти библиотеки следует поддерживать регулярно: добавлять новые фразы и настраивать оценки.

Вот лексиконы настроений, которые могут вам помочь:

Базовая процедура анализатора настроений на основе правил

  1. Составьте списки поляризованных слов. Вы можете использовать только списки положительных и отрицательных слов или библиотеку настроений.
  2. Если вы используете только списки: подсчитайте количество положительных и отрицательных слов, которые встречаются в тексте. Если положительных слов больше, то текст положительный, иначе текст отрицательный. Если положительных и отрицательных слов одинаковое, то текст нейтральный.
  3. Если вы используете библиотеку тональности: тональность - это среднее значение тональности, полученное для всех слов в тексте.

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

Кроме того, в рамках предварительной обработки очень важно вырезать или лемматизировать все слова. В противном случае ваш алгоритм не распознает некоторые слова или ваши списки должны будут содержать все разные формы одного и того же слова (например, книга и книги).

Пример анализатора настроений на основе правил

В нашем примере мы будем использовать обзоры Amazon Fine Food, вы можете скачать набор данных здесь. Набор данных состоит из текстовых обзоров и их оценок (от 1 до 5). Мы воспользуемся случайной выборкой из 20 000 отзывов и сделаем их более простыми, обозначив их как положительные (1), нейтральные (0) и отрицательные (-1).

import pandas as pd 
data = pd.read_csv("./Reviews.csv") 
data = data.sample(frac=1)[:20000] 
data.columns = map(lambda x:x.lower(), list(data)) 
data["text"] = data["summary"] + " "+ data["text"] 
data = data[["text", "score"]] 
data.loc[data.score<3, "score"] = -1 
data.loc[data.score==3, "score"] = 0 
data.loc[data.score>3, "score"] = 1 
data.head(5)

Вывод:

          text                                               score
33608     Just like sugar Tastes just like white sugar, ...    1
361755    Ground control, Can you hear me? If you drink ...    1
470108    Superb!!! The Langnese Acacia Honey is magnifi...    1
301450    Fast, cheap, and perfect! Exactly what was adv...    1
188065    I love HappyBaby products, just not *this* one...    0

Теперь давайте разделим наш набор данных для обучения и тестирования:

import random

sentiment_data = zip(data["text"], data["score"])
random.shuffle(sentiment_data)

# 80% for training
train_X, train_y = zip(*sentiment_data[:16000])

# Keep 20% for testing
test_X, test_y = zip(*sentiment_data[16000:])

Увеличьте масштаб используемых функций:

Мы будем декодировать каждый отзыв с помощью функции decode (utf-8) и разделять его на предложения с sent_tokenize () от nltk, например:

from nltk import sent_tokenize

text = data.loc[176431, "text"]
text = text.decode("utf-8")
raw_sentences = sent_tokenize(text)

raw_sentences

Вывод:

[u'Wonderful!!', u'I love this cheese & herb bread!', u'My friends just gave me a bread machine and I am having a lot of fun with it.', u'I have ordered more Hodgson Mill flavors and am looking forward to trying them.']

Каждое предложение можно разделить на слова с помощью word_tokenize ():

from nltk import word_tokenize

sentence = raw_sentences[0]
words = word_tokenize(sentence)
words

Вывод:

[u'Wonderful', u'!', u'!']

А теги части речи будут выполняться с помощью функции с pos_tag ():

from nltk import pos_tag

tags = pos_tag(words)
tags

Вывод:

[(u'Wonderful', 'JJ'), (u'!', '.'), (u'!', '.')]

Возвращаемые теги имеют формат PennTreebank, и мы переведем их в простые теги Wordnet с помощью функции penn_to_wn (). Мы будем использовать только существительные, прилагательные и наречия. В этом примере мы выберем тег «замечательно» и лемматизируем его с помощью WordNetLemmatizer ():

from nltk.corpus import wordnet as wn
from nltk.stem import WordNetLemmatizer

def penn_to_wn(tag):
"""
Convert between the PennTreebank tags to simple Wordnet tags
"""
    if tag.startswith('J'):
        return wn.ADJ
    elif tag.startswith('N'):
        return wn.NOUN
    elif tag.startswith('R'):
        return wn.ADV
    elif tag.startswith('V'):
        return wn.VERB
    return None

wn_tag = penn_to_wn(tags[0][1])
word = tags[0][0]
lemmatizer = WordNetLemmatizer()
lemma = lemmatizer.lemmatize(word, pos=wn_tag)

lemma

Вывод:

u'Wonderful'

Наше слово теперь в отличном формате! Давайте поищем список синонимов с помощью wordnet.synsets () и возьмем первый из них, чтобы вычислить тональность.

synsets = wn.synsets(lemma, pos=wn_tag)
print(synsets)

Вывод:

[Synset('fantastic.s.02')]

Мы будем использовать SentiWordNet (описанную выше) для вычисления полярности. Настроение будет разницей между положительной и отрицательной оценкой. Это часть пакета nltk, и вы можете легко импортировать его с помощью из nltk.corpus import sentiwordnet и узнать мнение с помощью sentiwordnet.senti_synset (); положительная оценка настроения с помощью pos_score () и отрицательная оценка с помощью neg_score (). Вот пример:

from nltk.corpus import sentiwordnet as swn

synset = synsets[0]
swn_synset = swn.senti_synset(synset.name())

print("Positive score = "+ str(swn_synset.pos_score()))
print("Negative score = "+ str(swn_synset.neg_score()))

sentiment = swn_synset.pos_score() - swn_synset.neg_score()
print("Sentiment = "+ str(sentiment))

Вывод:

Positive score = 0.75 
Negative score = 0.0 
Sentiment = 0.75

Как видите, синоним нашего слова «замечательный» - «фантастический». Положительный результат - 0,75, отрицательный - 0,0, что означает, что общее настроение составляет 0,75! Мы будем использовать ту же процедуру для всех слов и всех отзывов.

Анализатор настроений на основе правил для всех отзывов

Итак, давайте все автоматизируем и получим точность для каждого обзора в данных тестирования. Тональность каждого отзыва - это среднее значение каждого слова!

from nltk.stem import WordNetLemmatizer
from nltk.corpus import wordnet as wn
from nltk.corpus import sentiwordnet as swn
from nltk import sent_tokenize, word_tokenize, pos_tag

lemmatizer = WordNetLemmatizer()

def sentiment_sentiwordnet(text):
    text = text.decode("utf-8")
    raw_sentences = sent_tokenize(text)
    sentiment = 0
    tokens_count = 0

    for raw_sentence in raw_sentences:
        tagged_sentence = pos_tag(word_tokenize(raw_sentence))

        for word, tag in tagged_sentence:
            wn_tag = penn_to_wn(tag)
            if wn_tag not in (wn.NOUN, wn.ADJ, wn.ADV):
                continue

            lemma = lemmatizer.lemmatize(word, pos=wn_tag)
            if not lemma:
                continue

            synsets = wn.synsets(lemma, pos=wn_tag)
            if not synsets:
                continue

            synset = synsets[0]
            swn_synset = swn.senti_synset(synset.name())
            word_sent = (swn_synset.pos_score() -
                         swn_synset.neg_score())

            if word_sent != 0:
                sentiment += word_sent
                tokens_count += 1

    if tokens_count == 0:
        return 0
    sentiment = sentiment/tokens_count
    if sentiment >= 0.01:
        return 1
    if sentiment <= -0.01:
        return -1
    return 0

Давайте посмотрим на точность нашего анализатора мнений, мы можем рассчитать ее с помощью precision_score () из scikt-learn:

from sklearn.metrics import accuracy_score
pred_y = [sentiment_sentiwordnet(text) for text in test_X] accuracy_score(test_y, pred_y)

Вывод:

0.646

Как видите, точность очень плохая - около 65%, что очень разочаровывает для всей этой работы. Мы могли бы определить больше правил или немного предварительно обработать текст и получить более высокую точность, но такие системы очень быстро становятся действительно сложными с десятками или сотнями различных правил, и это был всего лишь предварительный просмотр, чтобы вы начали.

Общее мнение:

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

В следующей статье мы расскажем об автоматических системах и постараемся поразить вас простотой машинного обучения.

Первоначально опубликовано на сайте krakensystems.co 6 марта 2019 г.