Рубрики
Без рубрики

Python for NLP: Анализ настроений с помощью Scikit-Learn

Автор оригинала: Usman Malik.

Python for NLP: Анализ настроений с помощью Scikit-Learn

Это пятая статья в серии статей по НЛП для Python. В своей предыдущей статье я объяснил , как космическая библиотека Python может использоваться для выполнения тегов частей речи и распознавания именованных сущностей. В этой статье я продемонстрирую, как проводить анализ настроений с использованием данных Twitter с помощью библиотеки Scikit-Learn.

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

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

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

Определение проблемы

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

Решение

Чтобы решить эту проблему, мы будем следовать типичному конвейеру машинного обучения. Сначала мы импортируем необходимые библиотеки и набор данных. Затем мы проведем исследовательский анализ данных, чтобы увидеть, сможем ли мы найти какие-либо тенденции в наборе данных. Далее мы выполним предварительную обработку текста для преобразования текстовых данных в числовые, которые могут быть использованы алгоритмом машинного обучения. Наконец, мы будем использовать алгоритмы машинного обучения для обучения и тестирования наших моделей анализа настроений.

Импорт необходимых библиотек

Первым шагом как всегда является импорт необходимых библиотек:

import numpy as np 
import pandas as pd 
import re
import nltk 
import matplotlib.pyplot as plt
%matplotlib inline

Примечание: Все сценарии в этой статье были запущены с помощью записной книжки Jupyter.

Импорт набора данных

Набор данных, который мы собираемся использовать для этой статьи, находится в свободном доступе по этой ссылке Github .

Для импорта набора данных мы будем использовать функцию Pandas read_csv , как показано ниже:

data_source_url = "https://raw.githubusercontent.com/kolaveridi/kaggle-Twitter-US-Airline-Sentiment-/master/Tweets.csv"
airline_tweets = pd.read_csv(data_source_url)

Давайте сначала посмотрим, как выглядит набор данных с помощью метода head() :

airline_tweets.head()

Вывод выглядит следующим образом:

Анализ данных

Давайте немного исследуем набор данных, чтобы увидеть, можем ли мы найти какие-либо тенденции. Но перед этим мы изменим размер участка по умолчанию, чтобы лучше видеть участки. Выполните следующий сценарий:

plot_size = plt.rcParams["figure.figsize"] 
print(plot_size[0]) 
print(plot_size[1])

plot_size[0] = 8
plot_size[1] = 6
plt.rcParams["figure.figsize"] = plot_size 

Давайте сначала посмотрим количество твитов для каждой авиакомпании. Для этого мы построим круговую диаграмму:

airline_tweets.airline.value_counts().plot(kind='pie', autopct='%1.0f%%')

В выходных данных вы можете увидеть процент публичных твитов для каждой авиакомпании. Наибольшее количество твитов приходится на United Airline-26%, за ней следует US Airways (20%).

Давайте теперь посмотрим на распределение настроений по всем твитам. Выполните следующий сценарий:

airline_tweets.airline_sentiment.value_counts().plot(kind='pie', autopct='%1.0f%%', colors=["red", "yellow", "green"])

Вывод скрипта выше выглядит примерно так:

Из выходных данных видно, что большинство твитов являются отрицательными (63%), за ними следуют нейтральные твиты (21%), а затем положительные твиты (16%).

Далее рассмотрим распределение настроений по каждой отдельной авиакомпании,

airline_sentiment = airline_tweets.groupby(['airline', 'airline_sentiment']).airline_sentiment.count().unstack()
airline_sentiment.plot(kind='bar')

Вывод выглядит следующим образом:

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

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

import seaborn as sns

sns.barplot(x='airline_sentiment', y='airline_sentiment_confidence' , data=airline_tweets)

Вывод приведенного выше скрипта выглядит следующим образом:

Из выходных данных вы можете видеть, что уровень доверия для отрицательных твитов выше по сравнению с положительными и нейтральными твитами.

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

Очистка данных

Твиты содержат много жаргонных слов и знаков препинания. Нам нужно очистить наши твиты, прежде чем их можно будет использовать для обучения модели машинного обучения. Однако, прежде чем очистить твиты, давайте разделим наш набор данных на наборы объектов и меток.

Наш набор функций будет состоять только из твитов. Если мы посмотрим на наш набор данных, то 11-я колонка содержит текст твита. Обратите внимание, что индекс столбца будет равен 10, так как столбцы pandas следуют нулевой схеме индексации, где первый столбец называется 0-м столбцом. Наш набор меток будет состоять из настроений твита, которые мы должны предсказать. Настроение твита находится во втором столбце (индекс 1). Чтобы создать объект и набор меток, мы можем использовать метод loc вне фрейма данных pandas.

Выполните следующий сценарий:

features = airline_tweets.iloc[:, 10].values
labels = airline_tweets.iloc[:, 1].values

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

processed_features = []

for sentence in range(0, len(features)):
    # Remove all the special characters
    processed_feature = re.sub(r'\W', ' ', str(features[sentence]))

    # remove all single characters
    processed_feature= re.sub(r'\s+[a-zA-Z]\s+', ' ', processed_feature)

    # Remove single characters from the start
    processed_feature = re.sub(r'\^[a-zA-Z]\s+', ' ', processed_feature) 

    # Substituting multiple spaces with single space
    processed_feature = re.sub(r'\s+', ' ', processed_feature, flags=re.I)

    # Removing prefixed 'b'
    processed_feature = re.sub(r'^b\s+', '', processed_feature)

    # Converting to Lowercase
    processed_feature = processed_feature.lower()

    processed_features.append(processed_feature)

В приведенном выше сценарии мы начинаем с удаления всех специальных символов из твитов. Регулярное выражение re.sub(r'\W', ' ', str(features[sentence])) делает это.

Далее мы удаляем все одиночные символы, оставшиеся в результате удаления специального символа с помощью регулярного выражения re.sub(r'\s+[a-zA-Z]\s+', ' ', processed_feature) . Например, если мы удалим специальный символ ' из Jack's и заменим его пробелом, то у нас останется Jack s . Здесь s не имеет никакого значения, поэтому мы удаляем его, заменяя все одиночные символы пробелом.

Однако, если мы заменим все одиночные символы пробелом, будет создано несколько пробелов. Поэтому мы заменяем все множественные пробелы одиночными пробелами, используя re.sub(r'\s+', ' ', processed_feature,.I) регулярное выражение. Кроме того, если ваша текстовая строка имеет формат байт, к ней добавляется символ b . Приведенный выше скрипт удаляет это с помощью регулярного выражения re.sub(r'^b\s+', ", processed_feature) .

Наконец, текст преобразуется в нижний регистр с помощью функции lower () .

Представление текста в числовой форме

Статистические алгоритмы используют математику для обучения моделей машинного обучения. Однако математика работает только с числами. Чтобы заставить статистические алгоритмы работать с текстом, мы сначала должны преобразовать текст в числа. Для этого существуют три основных подхода: Bag of Words, TF-IDF и Word2Vec. В этом разделе мы обсудим мешок слов и схему TF-IDF.

Мешок слов

Схема Bag of words – это самый простой способ преобразования текста в числа.

Например, у вас есть три документа:

  • Doc1
  • Doc2
  • Doc3

В подходе “мешок слов” первым шагом является создание словаря из всех уникальных слов. Для вышеприведенных трех документов наш словарь будет следующим::

Vocab = [I, like, to, play, football, it, is, a, good, game, prefer, over, rugby]

Следующим шагом является преобразование каждого документа в вектор объектов с помощью словаря. Длина каждого вектора признаков равна длине словаря. Частота слова в документе заменит фактическое слово в словаре. Если слово в словаре не найдено в соответствующем документе, вектор признаков документа будет иметь ноль в этом месте. Например, для Doc1 вектор признаков будет выглядеть следующим образом:

[1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]
TF-IDF

В “мешке слов” каждое слово имеет одинаковый вес. Идея подхода TF-IDF заключается в том, что слова, которые встречаются меньше во всех документах и больше в отдельных документах, вносят больший вклад в классификацию.

TF-IDF-это комбинация двух терминов. Частота термина и Обратная частота документа. Они могут быть рассчитаны как:

TF  = (Frequency of a word in the document)/(Total words in the document)

IDF = Log((Total number of docs)/(Number of docs containing the word))
TF-IDF с использованием библиотеки Scikit-Learn

К счастью для нас, библиотека Python Scikit-Learn содержит класс TfidfVectorizer , который можно использовать для преобразования текстовых объектов в векторы объектов TF-IDF. Следующий сценарий выполняет это:

from nltk.corpus import stopwords
from sklearn.feature_extraction.text import TfidfVectorizer

vectorizer = TfidfVectorizer (max_features=2500, min_df=7, max_df=0.8, stop_words=stopwords.words('english'))
processed_features = vectorizer.fit_transform(processed_features).toarray()

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

Аналогично, max_df указывает, что используются только те слова, которые встречаются максимум в 80% документов. Слова, встречающиеся во всех документах, слишком распространены и не очень полезны для классификации. Аналогично, min-df имеет значение 7, которое показывает, что включает слова, встречающиеся по крайней мере в 7 документах.

Разделение данных на Обучающие и Тестовые наборы

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

Выполните следующий код:

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(processed_features, labels, test_size=0.2, random_state=0)

В приведенном выше коде мы используем класс train_test_split из модуля sklearn.model_selection для разделения наших данных на обучающий и тестовый наборы. Метод принимает набор функций в качестве первого параметра, набор меток в качестве второго параметра и значение параметра test_size . Мы указали значение 0.2 для test_size , что означает, что наш набор данных будет разделен на два набора данных 80% и 20%. Мы будем использовать 80% – ный набор данных для обучения и 20% – ный набор данных для тестирования.

Обучение модели

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

Модуль sklearn.ensemble содержит класс Random Forest Classifier , который может быть использован для обучения модели машинного обучения с использованием алгоритма случайного леса. Для этого нам нужно вызвать метод fit в классе Random Forest Classifier и передать ему наши обучающие функции и метки в качестве параметров. Посмотрите на следующий сценарий:

from sklearn.ensemble import RandomForestClassifier

text_classifier = RandomForestClassifier(n_estimators=200, random_state=0)
text_classifier.fit(X_train, y_train)

Составление прогнозов и оценка модели

После того, как модель была обучена, последний шаг состоит в том, чтобы сделать прогнозы по модели. Для этого нам нужно вызвать метод predict на объекте класса Random Forest Classifier , который мы использовали для обучения. Посмотрите на следующий сценарий:

predictions = text_classifier.predict(X_test)

Наконец, для оценки производительности моделей машинного обучения мы можем использовать классификационные метрики, такие как a confusion metrix , F1 measure , accuracy и т. Д.

Чтобы найти значения этих метрик, мы можем использовать утилиты classification_report , confusion_matrix и accuracy_score из библиотеки sklearn.metrics . Посмотрите на следующий сценарий:

from sklearn.metrics import classification_report, confusion_matrix, accuracy_score

print(confusion_matrix(y_test,predictions))
print(classification_report(y_test,predictions))
print(accuracy_score(y_test, predictions))

Вывод приведенного выше скрипта выглядит следующим образом:

[[1724  101   45]
 [ 329  237   48]
 [ 142   58  244]]
              precision    recall  f1-score   support

    negative       0.79      0.92      0.85      1870
     neutral       0.60      0.39      0.47       614
    positive       0.72      0.55      0.62       444

   micro avg       0.75      0.75      0.75      2928
   macro avg       0.70      0.62      0.65      2928
weighted avg       0.74      0.75      0.73      2928

0.7530737704918032

Из выходных данных видно, что наш алгоритм достиг точности 75,30.

Вывод

Анализ настроений является одной из наиболее часто выполняемых задач НЛП, поскольку он помогает определить общее общественное мнение по определенной теме.

В этой статье мы увидели, как различные библиотеки Python способствуют проведению анализа настроений. Мы провели анализ публичных твитов, касающихся шести американских авиакомпаний, и достигли точности около 75%. Я бы порекомендовал вам попробовать использовать какой-нибудь другой алгоритм машинного обучения , такой как логистическая регрессия , SVM или KNN, и посмотреть, сможете ли вы получить лучшие результаты.

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