Анализ тональности и классификация текста с помощью Python

Вступление

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

  • NLTK: самый известный модуль Python для техник НЛП
  • Gensim: набор инструментов для тематического моделирования и моделирования векторных пространств

  • Scikit-learn: самая используемая библиотека машинного обучения на Python

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

Https://www.kaggle.com/jiashenliu/515k-hotel-reviews-data-in-europe

Для каждого текстового обзора мы хотим предсказать, соответствует ли он хорошему обзору (клиент доволен) или плохому (клиент не удовлетворен). Общий рейтинг обзоров может варьироваться от 2,5 / 10 до 10/10. Чтобы упростить задачу, мы разделим их на две категории:

  • плохие отзывы имеют общую оценку ‹5
  • хорошие отзывы имеют общие оценки ›= 5

Задача здесь состоит в том, чтобы иметь возможность предсказать эту информацию, используя только необработанные текстовые данные из обзора. Начнем!

Загрузить данные

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

Образец данных

Мы отбираем данные, чтобы ускорить вычисления.

Чистые данные

Если пользователь не оставит отрицательный комментарий, в наших данных он будет помечен как «Нет отрицательного». То же самое и для положительных комментариев со значением по умолчанию «Нет положительных». Мы должны удалить эти части из наших текстов.

Следующий шаг - очистка текстовых данных с помощью различных операций:

Чтобы очистить текстовые данные, мы вызываем нашу пользовательскую функцию «clean_text», которая выполняет несколько преобразований:

  • опустить текст
  • токенизировать текст (разбить текст на слова) и удалить знаки препинания
  • удалить бесполезные слова, содержащие числа
  • удалите ненужные стоп-слова, такие как "the", "a", "this" и т. д.
  • Тегирование части речи (POS): назначьте тег для каждого слова, чтобы определить, соответствует ли оно существительному, глаголу и т. Д., Используя лексическую базу данных WordNet.
  • лемматизировать текст: преобразовать каждое слово в его корневую форму (например, комнаты - ›комната, спал -› сон)

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

Функциональная инженерия

Сначала мы добавим функции анализа настроений, потому что мы можем предположить, что отзывы клиентов тесно связаны с тем, как они относились к своему пребыванию в отеле. Мы используем Vader, который является частью модуля NLTK, предназначенного для анализа настроений. Вейдер использует словарный запас, чтобы определить, какие из них являются положительными или отрицательными. Он также принимает во внимание контекст предложений для определения оценок тональности. Для каждого текста Вейдер возвращает 4 значения:

  • оценка нейтральности
  • оценка позитивности
  • оценка отрицательности
  • общий балл, суммирующий предыдущие баллы

Мы интегрируем эти 4 значения как функции в наш набор данных.

Затем мы добавляем несколько простых показателей для каждого текста:

  • количество символов в тексте
  • количество слов в тексте

Следующий шаг состоит в извлечении векторных представлений для каждого обзора. Модуль Gensim создает числовое векторное представление каждого слова в корпусе, используя контексты, в которых они появляются (Word2Vec). Это выполняется с помощью неглубоких нейронных сетей. Интересно то, что похожие слова будут иметь похожие векторы представления.

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

Сначала нам нужно обучить модель Doc2Vec, введя наши текстовые данные. Применяя эту модель к нашим обзорам, мы можем получить эти векторы представления.

Наконец, мы добавляем значения TF-IDF (Term Frequency - Inverse Document Frequency) для каждого слова и каждого документа.

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

Метрика TF-IDF решает эту проблему:

  • TF вычисляет классическое количество раз, когда слово встречается в тексте.
  • IDF вычисляет относительную важность этого слова, которая зависит от того, сколько текстов это слово может быть найдено.

Мы добавляем столбцы TF-IDF для каждого слова, которое встречается как минимум в 10 различных текстах, чтобы отфильтровать некоторые из них и уменьшить размер окончательного вывода.

Исследовательский анализ данных

Чтобы лучше понять наши данные, давайте немного их исследуем:

0    0.956761
1    0.043239
Name: is_bad_review, dtype: float64

Наш набор данных сильно несбалансирован, потому что менее 5% наших отзывов считаются отрицательными. Эта информация будет очень полезна при моделировании.

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

Большинство слов действительно относятся к отелям: номер, персонал, завтрак и т. Д. Некоторые слова больше связаны с впечатлением клиентов от пребывания в отеле: идеальный, любимый, дорогой, неприязнь и т. Д.

Самые положительные отзывы действительно соответствуют хорошим отзывам.

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

График выше показывает распределение настроений отзывов между хорошими и плохими. Мы видим, что хорошие отзывы о большинстве из них Вейдер считает очень положительными. Напротив, плохие отзывы обычно имеют более низкие оценки сложных настроений.

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

Моделирование is_bad_review

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

  • один для обучения нашей модели
  • один для оценки его производительности

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

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

Кривая ROC (рабочая характеристика приемника) обычно является хорошим графиком для обобщения качества нашего классификатора. Чем выше кривая выше диагональной базовой линии, тем лучше прогнозы. Хотя AUC ROC (Area Under the Curve ROC) очень хорош, мы не должны использовать здесь кривую ROC для оценки качества нашей модели.

Почему? Сначала напомним формулу ложноположительной скорости, которая соответствует оси x кривой ROC: FPR (False Positive Rate) = # False Positives / # Negatives.

Здесь # Negatives соответствует нашему количеству хороших отзывов, которое очень велико, потому что наш набор данных несбалансирован. Это означает, что даже с некоторыми ложными срабатываниями наш FPR будет оставаться очень низким. Наша модель сможет делать много ложных срабатываний прогнозов и по-прежнему иметь низкую частоту ложных срабатываний, увеличивая при этом истинно положительную скорость и, следовательно, искусственно увеличивая метрику AUC ROC.

Лучшим показателем в этой несбалансированной ситуации является AUC PR (Вызов области под кривой), также называемый AP (средняя точность).

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

Чтобы узнать, работает ли наша модель лучше, чем другой классификатор, мы можем просто использовать метрику AP. Чтобы оценить качество нашей модели, мы можем сравнить ее с простой базовой линией решения. Давайте возьмем здесь случайный классификатор в качестве основы, который будет предсказывать половину времени 1 и половину времени 0 для метки.

Такой классификатор имел бы точность 4,3%, что соответствует доле положительных наблюдений. Для каждого значения отзыва точность останется прежней, и это приведет нас к AP, равному 0,043. AP нашей модели составляет примерно 0,35, что более чем в 8 раз выше, чем AP случайного метода. Это означает, что наша модель обладает хорошей предсказательной силой.

Заключение

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

Вот ссылка на оригинальный блокнот Jupyter на Github:



Также на Kaggle:



Мой профиль в LinkedIn:

Https://www.linkedin.com/in/jonathanoheix/