Поиск по сайту:

Как выполнить анализ настроений в Python 3 с помощью набора инструментов естественного языка (NLTK)


Автор выбрал программу Write for DOnations.

Введение

Большой объем данных, которые генерируются сегодня, — это набор средств естественного языка (NLTK), широко используемая библиотека НЛП в Python для анализа текстовых данных.

В этом руководстве вы подготовите набор примеров твитов из пакета NLTK для НЛП с различными методами очистки данных. Как только набор данных будет готов к обработке, вы обучите модель предварительно классифицированным твитам и используете модель для классификации твитов-образцов на негативные и позитивные настроения.

В этой статье предполагается, что вы знакомы с основами серии How To Code in Python 3), в первую очередь с использованием структур данных, классов и методов. В руководстве предполагается, что у вас нет опыта работы с НЛП и nltk, хотя некоторое знание этого является дополнительным преимуществом.

Предпосылки

  • Это руководство основано на Python версии 3.6.5. Если у вас не установлен Python 3, вот руководство по установке и настройке локальной среды программирования для Python 3.
  • Рекомендуется уметь работать с языковыми данными. Если вы новичок в использовании NLTK, ознакомьтесь с руководством Как работать с языковыми данными в Python 3 с помощью набора инструментов для работы с естественным языком (NLTK).

Шаг 1 — Установка NLTK и загрузка данных

Вы будете использовать пакет NLTK в Python для всех задач NLP в этом руководстве. На этом этапе вы установите NLTK и загрузите образцы твитов, которые будете использовать для обучения и тестирования своей модели.

Сначала установите пакет NLTK с помощью менеджера пакетов pip:

  1. pip install nltk==3.3

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

  1. python3

Затем импортируйте модуль nltk в интерпретатор Python.

  1. import nltk

Загрузите образцы твитов из пакета NLTK:

  1. nltk.download('twitter_samples')

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

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

Если вы хотите использовать свой собственный набор данных, вы можете собирать твиты за определенный период времени, пользователя или хэштег с помощью Twitter API.

Теперь, когда вы импортировали NLTK и загрузили примеры твитов, выйдите из интерактивного сеанса, введя exit(). Вы готовы импортировать твиты и начать обработку данных.

Шаг 2 — Токенизация данных

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

Маркер — это последовательность символов в тексте, которая служит единицей. В зависимости от того, как вы создаете токены, они могут состоять из слов, смайликов, хэштегов, ссылок или даже отдельных символов. Основной способ разбить язык на токены — разделить текст на основе пробелов и знаков препинания.

Для начала создайте новый файл .py для хранения вашего скрипта. В этом руководстве будет использоваться nlp_test.py:

  1. nano nlp_test.py

В этом файле вы сначала импортируете twitter_samples, чтобы иметь возможность работать с этими данными:

from nltk.corpus import twitter_samples

Это позволит импортировать три набора данных из NLTK, содержащих различные твиты, для обучения и тестирования модели:

  • negative_tweets.json: 5000 твитов с негативными эмоциями
  • positive_tweets.json: 5000 твитов с положительными эмоциями
  • tweets.20150430-223406.json: 20 000 твитов без эмоций

Затем создайте переменные для positive_tweets, negative_tweets и text:

from nltk.corpus import twitter_samples

positive_tweets = twitter_samples.strings('positive_tweets.json')
negative_tweets = twitter_samples.strings('negative_tweets.json')
text = twitter_samples.strings('tweets.20150430-223406.json')

Метод strings() в twitter_samples распечатает все твиты в наборе данных в виде строк. Установка различных коллекций твитов в качестве переменной упростит обработку и тестирование.

Перед использованием токенизатора в NLTK необходимо загрузить дополнительный ресурс punkt. Модуль punkt — это предварительно обученная модель, которая помогает вам размечать слова и предложения. Например, эта модель знает, что имя может содержать точку (например, \S. Daityari), и наличие этой точки в предложении не обязательно завершает его. Сначала запустите интерактивный сеанс Python:

  1. python3

Выполните в сеансе следующие команды, чтобы загрузить ресурс punkt:

  1. import nltk
  2. nltk.download('punkt')

После завершения загрузки вы готовы использовать токенизаторы NLTK. NLTK предоставляет токенизатор по умолчанию для твитов с помощью метода .tokenized(). Добавьте строку для создания объекта, который токенизирует набор данных positive_tweets.json:

from nltk.corpus import twitter_samples

positive_tweets = twitter_samples.strings('positive_tweets.json')
negative_tweets = twitter_samples.strings('negative_tweets.json')
text = twitter_samples.strings('tweets.20150430-223406.json')
tweet_tokens = twitter_samples.tokenized('positive_tweets.json')

Если вы хотите протестировать скрипт, чтобы увидеть метод .tokenized в действии, добавьте выделенное содержимое в свой скрипт nlp_test.py. Это будет токенизировать один твит из набора данных positive_tweets.json:

from nltk.corpus import twitter_samples

positive_tweets = twitter_samples.strings('positive_tweets.json')
negative_tweets = twitter_samples.strings('negative_tweets.json')
text = twitter_samples.strings('tweets.20150430-223406.json')
tweet_tokens = twitter_samples.tokenized('positive_tweets.json')[0]

print(tweet_tokens[0])

Сохраните и закройте файл и запустите скрипт:

  1. python3 nlp_test.py

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

Output
['#FollowFriday', '@France_Inte', '@PKuchly57', '@Milipol_Paris', 'for', 'being', 'top', 'engaged', 'members', 'in', 'my', 'community', 'this', 'week', ':)']

Здесь метод .tokenized() возвращает специальные символы, такие как @ и _. Эти символы будут удалены с помощью регулярных выражений позже в этом руководстве.

Теперь, когда вы увидели, как работает метод .tokenized(), не забудьте закомментировать или удалить последнюю строку, чтобы напечатать токенизированный твит из скрипта, добавив # до начала строки:

from nltk.corpus import twitter_samples

positive_tweets = twitter_samples.strings('positive_tweets.json')
negative_tweets = twitter_samples.strings('negative_tweets.json')
text = twitter_samples.strings('tweets.20150430-223406.json')
tweet_tokens = twitter_samples.tokenized('positive_tweets.json')[0]

#print(tweet_tokens[0])

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

Шаг 3 — Нормализация данных

У слов разные формы — например, «бег», «бег» и «бег» — это разные формы одного и того же глагола «бежать». В зависимости от требований вашего анализа, все эти версии, возможно, потребуется преобразовать в одну и ту же форму, \выполнить. Нормализация в НЛП — это процесс преобразования слова в его каноническую форму.

Нормализация помогает группировать слова с одинаковым значением, но разными формами. Без нормализации \run, \runs и \running будут рассматриваться как разные слова, даже если вы можете захотеть, чтобы они рассматривались как одно и то же слово. В этом разделе вы исследуете основы и лемматизация — два популярных метода нормализации.

Стемминг — это процесс удаления аффиксов из слова. Stemming, работающий только с простыми формами глаголов, представляет собой эвристический процесс, удаляющий окончания слов.

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

Прежде чем приступить к использованию лемматизации, загрузите необходимые ресурсы, введя следующее в интерактивном сеансе Python:

  1. python3

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

  1. import nltk
  2. nltk.download('wordnet')
  3. nltk.download('averaged_perceptron_tagger')

wordnet — это лексическая база данных для английского языка, которая помогает скрипту определить базовое слово. Вам нужен ресурс averaged_perceptron_tagger, чтобы определить контекст слова в предложении.

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

  1. from nltk.tag import pos_tag
  2. from nltk.corpus import twitter_samples
  3. tweet_tokens = twitter_samples.tokenized('positive_tweets.json')
  4. print(pos_tag(tweet_tokens[0]))

Вот результат работы функции pos_tag.

Output
[('#FollowFriday', 'JJ'), ('@France_Inte', 'NNP'), ('@PKuchly57', 'NNP'), ('@Milipol_Paris', 'NNP'), ('for', 'IN'), ('being', 'VBG'), ('top', 'JJ'), ('engaged', 'VBN'), ('members', 'NNS'), ('in', 'IN'), ('my', 'PRP$'), ('community', 'NN'), ('this', 'DT'), ('week', 'NN'), (':)', 'NN')]

Из списка тегов, вот список наиболее распространенных элементов и их значение:

  • NNP: существительное, собственное, единственное число
  • NN: существительное, общее, единственное число или масса.
  • IN: предлог или союз, подчиненный
  • VBG: глагол, герундий или причастие настоящего времени
  • VBN: глагол, причастие прошедшего времени

Вот полный список набора данных.

В общем, если тег начинается с NN, слово является существительным, а если оно начинается с VB, слово является глаголом. После просмотра тегов выйдите из сеанса Python, введя exit().

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

Обновите файл nlp_test.py, добавив в него следующую функцию, которая лемматизирует предложение:

...

from nltk.tag import pos_tag
from nltk.stem.wordnet import WordNetLemmatizer

def lemmatize_sentence(tokens):
    lemmatizer = WordNetLemmatizer()
    lemmatized_sentence = []
    for word, tag in pos_tag(tokens):
        if tag.startswith('NN'):
            pos = 'n'
        elif tag.startswith('VB'):
            pos = 'v'
        else:
            pos = 'a'
        lemmatized_sentence.append(lemmatizer.lemmatize(word, pos))
    return lemmatized_sentence

print(lemmatize_sentence(tweet_tokens[0]))

Этот код импортирует класс WordNetLemmatizer и инициализирует его переменной lemmatizer.

Функция lemmatize_sentence сначала получает тег позиции каждого токена твита. В операторе if, если тег начинается с NN, токен назначается как существительное. Точно так же, если тег начинается с VB, токен назначается как глагол.

Сохраните и закройте файл и запустите скрипт:

  1. python3 nlp_test.py

Вот результат:

Output
['#FollowFriday', '@France_Inte', '@PKuchly57', '@Milipol_Paris', 'for', 'be', 'top', 'engage', 'member', 'in', 'my', 'community', 'this', 'week', ':)']

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

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

Шаг 4 — Удаление шума из данных

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

Шум специфичен для каждого проекта, поэтому то, что представляет собой шум в одном проекте, может не быть шумом в другом проекте. Например, самые распространенные слова в языке называются стоп-слова. Некоторыми примерами стоп-слов являются \is, \the и \a. Обычно они не имеют значения при обработке языка, если только конкретный вариант использования не требует их включения.

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

  • Гиперссылки. Все гиперссылки в Твиттере преобразуются в средство сокращения URL-адресов t.co. Поэтому сохранение их в текстовой обработке не добавит анализу никакой ценности.
  • Обработчики Твиттера в ответах. Этим именам пользователей Твиттера предшествует символ @, который не несет никакой смысловой нагрузки.
  • Пунктуация и специальные символы. Хотя они часто обеспечивают контекст для текстовых данных, этот контекст часто трудно обработать. Для простоты вы удалите все знаки препинания и специальные символы из твитов.

Чтобы удалить гиперссылки, вам нужно сначала найти подстроку, которая соответствует URL-адресу, начинающемуся с http:// или https://, за которым следуют буквы, цифры или специальные персонажи. После сопоставления шаблона метод .sub() заменяет его пустой строкой.

Так как мы нормализуем словоформы в функции remove_noise(), вы можете закомментировать функцию lemmatize_sentence() из скрипта.

Добавьте следующий код в файл nlp_test.py, чтобы удалить шум из набора данных:

...

import re, string

def remove_noise(tweet_tokens, stop_words = ()):

    cleaned_tokens = []

    for token, tag in pos_tag(tweet_tokens):
        token = re.sub('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+#]|[!*\(\),]|'\
                       '(?:%[0-9a-fA-F][0-9a-fA-F]))+','', token)
        token = re.sub("(@[A-Za-z0-9_]+)","", token)

        if tag.startswith("NN"):
            pos = 'n'
        elif tag.startswith('VB'):
            pos = 'v'
        else:
            pos = 'a'

        lemmatizer = WordNetLemmatizer()
        token = lemmatizer.lemmatize(token, pos)

        if len(token) > 0 and token not in string.punctuation and token.lower() not in stop_words:
            cleaned_tokens.append(token.lower())
    return cleaned_tokens

Этот код создает функцию remove_noise(), которая удаляет шум и включает нормализацию и лемматизацию, упомянутые в предыдущем разделе. Код принимает два аргумента: токены твита и кортеж стоп-слов.

Затем код использует цикл для удаления шума из набора данных. Чтобы удалить гиперссылки, код сначала ищет подстроку, которая соответствует URL-адресу, начинающемуся с http:// или https://, за которым следуют буквы, цифры или специальные символы. . После сопоставления шаблона метод .sub() заменяет его пустой строкой или .

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

Наконец, вы можете удалить знаки препинания с помощью библиотеки string.

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

Выполните следующую команду из интерактивного сеанса Python, чтобы загрузить этот ресурс:

  1. nltk.download('stopwords')

После загрузки ресурса выйдите из интерактивного сеанса.

Вы можете использовать метод .words(), чтобы получить список стоп-слов на английском языке. Чтобы протестировать функцию, давайте запустим ее на нашем образце твита. Добавьте следующие строки в конец файла nlp_test.py:

...
from nltk.corpus import stopwords
stop_words = stopwords.words('english')

print(remove_noise(tweet_tokens[0], stop_words))

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

Output
['#followfriday', 'top', 'engage', 'member', 'community', 'week', ':)']

Обратите внимание, что функция удаляет все упоминания @, стоп-слова и переводит слова в нижний регистр.

Прежде чем приступить к моделированию на следующем шаге, используйте функцию remove_noise() для очистки положительных и отрицательных твитов. Закомментируйте строку, чтобы напечатать вывод remove_noise() в образце твита, и добавьте следующее в скрипт nlp_test.py:

...
from nltk.corpus import stopwords
stop_words = stopwords.words('english')

#print(remove_noise(tweet_tokens[0], stop_words))

positive_tweet_tokens = twitter_samples.tokenized('positive_tweets.json')
negative_tweet_tokens = twitter_samples.tokenized('negative_tweets.json')

positive_cleaned_tokens_list = []
negative_cleaned_tokens_list = []

for tokens in positive_tweet_tokens:
    positive_cleaned_tokens_list.append(remove_noise(tokens, stop_words))

for tokens in negative_tweet_tokens:
    negative_cleaned_tokens_list.append(remove_noise(tokens, stop_words))

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

...
print(positive_tweet_tokens[500])
print(positive_cleaned_tokens_list[500])

Сохраните и закройте файл и запустите скрипт. Из вывода вы увидите, что знаки препинания и ссылки были удалены, а слова переведены в нижний регистр.

Output
['Dang', 'that', 'is', 'some', 'rad', '@AbzuGame', '#fanart', '!', ':D', 'https://t.co/bI8k8tb9ht'] ['dang', 'rad', '#fanart', ':d']

Существуют определенные проблемы, которые могут возникнуть во время предварительной обработки текста. Например, слова без пробелов (\iLoveYou) будут рассматриваться как одно и разделить такие слова может быть сложно. Кроме того, \Hi, \Hii и \Hiiiiii будут обрабатываться по-разному script, если вы не напишите что-то конкретное для решения проблемы. Обычно процесс удаления шума подстраивается под ваши конкретные данные.

Теперь, когда вы увидели функцию remove_noise() в действии, не забудьте закомментировать или удалить последние две строки из скрипта, чтобы вы могли добавить в него больше:

...
#print(positive_tweet_tokens[500])
#print(positive_cleaned_tokens_list[500])

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

Шаг 5 — Определение плотности слов

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

В следующем фрагменте определяется функция-генератор с именем get_all_words, которая принимает список твитов в качестве аргумента для предоставления списка слов во всех присоединенных токенах твитов. Добавьте следующий код в файл nlp_test.py:

...

def get_all_words(cleaned_tokens_list):
    for tokens in cleaned_tokens_list:
        for token in tokens:
            yield token

all_pos_words = get_all_words(positive_cleaned_tokens_list)

Теперь, когда вы скомпилировали все слова в выборке твитов, вы можете узнать, какие слова являются наиболее распространенными, используя класс FreqDist NLTK. Добавление следующего кода в файл nlp_test.py:

from nltk import FreqDist

freq_dist_pos = FreqDist(all_pos_words)
print(freq_dist_pos.most_common(10))

Метод .most_common() выводит список слов, наиболее часто встречающихся в данных. Сохраните и закройте файл после внесения этих изменений.

Когда вы запустите файл сейчас, вы найдете наиболее распространенные термины в данных:

Output
[(':)', 3691), (':-)', 701), (':d', 658), ('thanks', 388), ('follow', 357), ('love', 333), ('...', 290), ('good', 283), ('get', 263), ('thank', 253)]

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

Подводя итог, вы извлекли твиты из nltk, токенизировали, нормализовали и очистили твиты для использования в модели. Наконец, вы также посмотрели частоты токенов в данных и проверили частоты первых десяти токенов.

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

Шаг 6 — Подготовка данных для модели

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

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

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

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

Преобразование токенов в словарь

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

Добавьте следующий код, чтобы преобразовать твиты из списка очищенных токенов в словари с ключами в качестве токенов и True в качестве значений. Соответствующие словари хранятся в positive_tokens_for_model и negative_tokens_for_model.

...
def get_tweets_for_model(cleaned_tokens_list):
    for tweet_tokens in cleaned_tokens_list:
        yield dict([token, True] for token in tweet_tokens)

positive_tokens_for_model = get_tweets_for_model(positive_cleaned_tokens_list)
negative_tokens_for_model = get_tweets_for_model(negative_cleaned_tokens_list)

Разделение набора данных для обучения и тестирования модели

Далее необходимо подготовить данные для обучения класса NaiveBayesClassifier. Добавьте в файл следующий код для подготовки данных:

...
import random

positive_dataset = [(tweet_dict, "Positive")
                     for tweet_dict in positive_tokens_for_model]

negative_dataset = [(tweet_dict, "Negative")
                     for tweet_dict in negative_tokens_for_model]

dataset = positive_dataset + negative_dataset

random.shuffle(dataset)

train_data = dataset[:7000]
test_data = dataset[7000:]

Этот код добавляет метку Положительно или Отрицательно к каждому сообщению. Затем он создает набор данных, объединяя положительные и отрицательные твиты.

По умолчанию данные содержат все положительные твиты, за которыми следуют все негативные твиты по порядку. При обучении модели вы должны предоставить выборку своих данных, которая не содержит систематической ошибки. Чтобы избежать предвзятости, вы добавили код для случайного расположения данных с помощью метода .shuffle() random.

Наконец, код разбивает перетасованные данные в соотношении 70:30 для обучения и тестирования соответственно. Поскольку количество твитов равно 10000, вы можете использовать первые 7000 твитов из перетасованного набора данных для обучения модели, а последние 3000 — для тестирования модели.

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

Шаг 7 — Создание и тестирование модели

Наконец, вы можете использовать класс NaiveBayesClassifier для построения модели. Используйте метод .train() для обучения модели и метод .accuracy() для проверки модели на тестовых данных.

...
from nltk import classify
from nltk import NaiveBayesClassifier
classifier = NaiveBayesClassifier.train(train_data)

print("Accuracy is:", classify.accuracy(classifier, test_data))

print(classifier.show_most_informative_features(10))

Сохраните, закройте и выполните файл после добавления кода. Вывод кода будет следующим:

Output
Accuracy is: 0.9956666666666667 Most Informative Features :( = True Negati : Positi = 2085.6 : 1.0 :) = True Positi : Negati = 986.0 : 1.0 welcome = True Positi : Negati = 37.2 : 1.0 arrive = True Positi : Negati = 31.3 : 1.0 sad = True Negati : Positi = 25.9 : 1.0 follower = True Positi : Negati = 21.1 : 1.0 bam = True Positi : Negati = 20.7 : 1.0 glad = True Positi : Negati = 18.1 : 1.0 x15 = True Negati : Positi = 15.9 : 1.0 community = True Positi : Negati = 14.1 : 1.0

Точность определяется как процент твитов в тестовом наборе данных, для которых модель смогла правильно предсказать настроение. Точность 99,5% на тестовом наборе довольно хороша.

В таблице, которая показывает наиболее информативные функции, каждая строка в выходных данных показывает соотношение появления токена в твитах с положительными и отрицательными тегами в наборе обучающих данных. Первая строка в данных означает, что во всех твитах, содержащих токен :(, соотношение отрицательных и положительных твитов было 2085,6 к 1. Интересно, что в положительных наборах данных был один токен с :(. Вы можете видеть, что два первых отличительных элемента в тексте — это смайлики. Кроме того, такие слова, как sad вызывают негативные эмоции, а добро пожаловать и рад — вызывают положительные эмоции.

Затем вы можете проверить, как модель работает со случайными твитами из Twitter. Добавьте этот код в файл:

...
from nltk.tokenize import word_tokenize

custom_tweet = "I ordered just once from TerribleCo, they screwed up, never used the app again."

custom_tokens = remove_noise(word_tokenize(custom_tweet))

print(classifier.classify(dict([token, True] for token in custom_tokens)))

Этот код позволит вам протестировать пользовательские твиты, обновив строку, связанную с переменной custom_tweet. Сохраните и закройте файл после внесения этих изменений.

Запустите скрипт для анализа пользовательского текста. Вот вывод пользовательского текста в примере:

Output
'Negative'

Вы также можете проверить, правильно ли он характеризует положительные твиты:

...
custom_tweet = 'Congrats #SportStar on your 7th best goal from last season winning goal of the year :) #Baller #Topbin #oneofmanyworldies'

Вот результат:

Output
'Positive'

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

...
custom_tweet = 'Thank you for sending my baggage to CityX and flying me to CityY at the same time. Brilliant service. #thanksGenericAirline'

Вот результат:

Output
'Positive'

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

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

Шаг 8 — Очистка кода (необязательно)

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

  • Все импортируемые данные должны находиться в верхней части файла. Импорт из одной и той же библиотеки следует сгруппировать в одном операторе.
  • Все функции должны быть определены после импорта.
  • Все операторы в файле должны содержаться в условии if __name__ == __main__:. Это гарантирует, что операторы не будут выполнены, если вы импортируете функции файла в другой файл.

Мы также удалим код, который был закомментирован в соответствии с руководством, вместе с функцией lemmatize_sentence, так как лемматизация завершается новой функцией remove_noise.

Вот очищенная версия nlp_test.py:

from nltk.stem.wordnet import WordNetLemmatizer
from nltk.corpus import twitter_samples, stopwords
from nltk.tag import pos_tag
from nltk.tokenize import word_tokenize
from nltk import FreqDist, classify, NaiveBayesClassifier

import re, string, random

def remove_noise(tweet_tokens, stop_words = ()):

    cleaned_tokens = []

    for token, tag in pos_tag(tweet_tokens):
        token = re.sub('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+#]|[!*\(\),]|'\
                       '(?:%[0-9a-fA-F][0-9a-fA-F]))+','', token)
        token = re.sub("(@[A-Za-z0-9_]+)","", token)

        if tag.startswith("NN"):
            pos = 'n'
        elif tag.startswith('VB'):
            pos = 'v'
        else:
            pos = 'a'

        lemmatizer = WordNetLemmatizer()
        token = lemmatizer.lemmatize(token, pos)

        if len(token) > 0 and token not in string.punctuation and token.lower() not in stop_words:
            cleaned_tokens.append(token.lower())
    return cleaned_tokens

def get_all_words(cleaned_tokens_list):
    for tokens in cleaned_tokens_list:
        for token in tokens:
            yield token

def get_tweets_for_model(cleaned_tokens_list):
    for tweet_tokens in cleaned_tokens_list:
        yield dict([token, True] for token in tweet_tokens)

if __name__ == "__main__":

    positive_tweets = twitter_samples.strings('positive_tweets.json')
    negative_tweets = twitter_samples.strings('negative_tweets.json')
    text = twitter_samples.strings('tweets.20150430-223406.json')
    tweet_tokens = twitter_samples.tokenized('positive_tweets.json')[0]

    stop_words = stopwords.words('english')

    positive_tweet_tokens = twitter_samples.tokenized('positive_tweets.json')
    negative_tweet_tokens = twitter_samples.tokenized('negative_tweets.json')

    positive_cleaned_tokens_list = []
    negative_cleaned_tokens_list = []

    for tokens in positive_tweet_tokens:
        positive_cleaned_tokens_list.append(remove_noise(tokens, stop_words))

    for tokens in negative_tweet_tokens:
        negative_cleaned_tokens_list.append(remove_noise(tokens, stop_words))

    all_pos_words = get_all_words(positive_cleaned_tokens_list)

    freq_dist_pos = FreqDist(all_pos_words)
    print(freq_dist_pos.most_common(10))

    positive_tokens_for_model = get_tweets_for_model(positive_cleaned_tokens_list)
    negative_tokens_for_model = get_tweets_for_model(negative_cleaned_tokens_list)

    positive_dataset = [(tweet_dict, "Positive")
                         for tweet_dict in positive_tokens_for_model]

    negative_dataset = [(tweet_dict, "Negative")
                         for tweet_dict in negative_tokens_for_model]

    dataset = positive_dataset + negative_dataset

    random.shuffle(dataset)

    train_data = dataset[:7000]
    test_data = dataset[7000:]

    classifier = NaiveBayesClassifier.train(train_data)

    print("Accuracy is:", classify.accuracy(classifier, test_data))

    print(classifier.show_most_informative_features(10))

    custom_tweet = "I ordered just once from TerribleCo, they screwed up, never used the app again."

    custom_tokens = remove_noise(word_tokenize(custom_tweet))

    print(custom_tweet, classifier.classify(dict([token, True] for token in custom_tokens)))

Заключение

В этом руководстве вы познакомились с базовой моделью анализа тональности с использованием библиотеки nltk в Python 3. Сначала вы выполнили предварительную обработку твитов, разметив твит, нормализовав слова и удалив шум. Затем вы визуализировали часто встречающиеся элементы в данных. Наконец, вы создали модель, связывающую твиты с определенным настроением.

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