Проверка настроения твита с помощью машинного обучения

Давайте посмотрим несколько твитов и классифицируем их как положительные или отрицательные.

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

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

Короче говоря, если вы любитель, обновления в Twitter - это новости.

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

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

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

На графике ниже видно, что все содержимое твитов в мире Twitter подразделяется на различные категории.

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

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

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

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

Полный код для этого можно найти в моем репозитории GitHub.

Итак, приступим.

Мы разделим коды на 3 категории.

  1. EDA (исследовательский анализ данных): некоторый исследовательский анализ поездов и тестовых данных в целом путем их объединения.
  2. Разработка функций: использование функций для более точного прогнозирования настроений.
  3. Моделирование: часть, в которой машинное обучение выходит на первый план, и мы видим результаты прогнозов.

Хватит разговоров. Покажи мне код .. !!

# importing the libraries for data processing and analysis
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
%matplotlib inline
plt.style.use('fivethirtyeight')
warnings.filterwarnings('ignore')

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

train = pd.read_csv('train_sentiment.csv')
test = pd.read_csv('test_sentiment.csv')
  1. EDA (исследовательский анализ данных)

Мы можем проверить распределение количества твитов в поезде и тестовых данных.

# checking the distribution of label of tweets in the dataset
train[train['label'] == 0].head(10)
train[train['label'] == 1].head(10)

Затем мы переходим к векторизации подсчета данных твита. Счетная векторизация - это процесс подсчета количества вхождений каждого слова, которое появляется в документе (т. Е. Отдельном тексте, таком как статья, книга или даже абзац!).

# count vectorization for the text
from sklearn.feature_extraction.text import CountVectorizer

cv = CountVectorizer(stop_words = 'english')
words = cv.fit_transform(train.tweet)

sum_words = words.sum(axis=0)

words_freq = [(word, sum_words[0, i]) for word, i in cv.vocabulary_.items()]
words_freq = sorted(words_freq, key = lambda x: x[1], reverse = True)

frequency = pd.DataFrame(words_freq, columns=['word', 'freq'])

frequency.head(30).plot(x='word', y='freq', kind='bar', figsize=(15, 7), color = 'brown')
plt.title("Most Frequently Occuring Words - Top 30")

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

# generating word cloud for the most common occuring words in the train data
from wordcloud import WordCloud

wordcloud = WordCloud(background_color = 'white', width = 1000, height = 1000).generate_from_frequencies(dict(words_freq))

plt.figure(figsize=(10,8))
plt.imshow(wordcloud)
plt.title("WordCloud - Vocabulary from Reviews", fontsize = 22)

Давайте также проверим наличие нейтральных слов в данных твита.

# wordcloud for words that are neutral
normal_words =' '.join([text for text in train['tweet'][train['label'] == 0]])

wordcloud = WordCloud(width=800, height=500, random_state = 0, max_font_size = 110).generate(normal_words)
plt.figure(figsize=(10, 7))
plt.imshow(wordcloud, interpolation="bilinear")
plt.axis('off')
plt.title('The Neutral Words')
plt.show()

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

  1. Мы также можем видеть самые важные хэштеги, присутствующие в данных твита.
  2. Мы также можем проверить тип твитов и сохранить их в списке.
# defining a function to collect the hashtags from the train data
def hashtags_extract(x):
    hashtags = []
    for i in x:
        ht = re.findall(r"#(\w+)", i)
        hashtags.append(ht)
    
    return hashtags
#extracting hashtags from racist/sexist tweet
ht_normal = hashtags_extract(train['tweet'][train['label'] == 0])

#extracting hashtags from normal tweet
ht_negetive = hashtags_extract(train['tweet'][train['label'] == 1])

#unnesting list

ht_normal = sum(ht_normal , [])
ht_negetive = sum(ht_negetive , [])

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

После токенизации мы создаем слово-векторную модель, используя популярную библиотеку Gensim, сохраняя размер контекстного окна 5 и размер окна 1 для модели skip-gram.

#tokenizing the words present in the training set
tokenized_tweet = train['tweet'].apply(lambda x: x.split()) 

# importing gensim
import gensim

# creating a word to vector model
model_w2v = gensim.models.Word2Vec(
            tokenized_tweet,
            size=200, # desired no. of features/independent variables 
            window=5, # context window size
            min_count=2,
            sg = 1, # 1 for skip-gram model
            hs = 0,
            negative = 10, # for negative sampling
            workers= 2, # no.of cores
            seed = 34)

model_w2v.train(tokenized_tweet, total_examples= len(train['tweet']), epochs=20)

Как только это будет сделано, мы сможем увидеть слова, которые; имеют значение, подобное словам, присутствующим в наборе данных. Например: - Sony ».

from tqdm import tqdm
tqdm.pandas(desc="progress-bar")
from gensim.models.doc2vec import LabeledSentence
# Adding a label to the tweets
def add_label(twt):
    output = []
    for i, s in zip(twt.index, twt):
        output.append(LabeledSentence(s, ["tweet_" + str(i)]))
    return output

# label all the tweets
labeled_tweets = add_label(tokenized_tweet)

labeled_tweets[:6]

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

# removing unwanted patterns from the data

import re
import nltk

nltk.download('stopwords')
from nltk.corpus import stopwords
from nltk.stem.porter import PorterStemmer
# collecting the train data and forming a corpus
train_corpus = []

for i in range(0, 7920):
  review = re.sub('[^a-zA-Z]', ' ', train['tweet'][i])
  review = review.lower()
  review = review.split()
  
  ps = PorterStemmer()
   # stemming
  review = [ps.stem(word) for word in review if not word in set(stopwords.words('english'))]
  
  # joining them back with space
  review = ' '.join(review)
  train_corpus.append(review)

from sklearn.feature_extraction.text import CountVectorizer

cv = CountVectorizer(max_features = 1500)
x = cv.fit_transform(train_corpus).toarray()
y = train.iloc[:, 1]

print(x.shape)
print(y.shape)
# creating bag of words for test

from sklearn.feature_extraction.text import CountVectorizer

cv = CountVectorizer(max_features = 1500)
x_test = cv.fit_transform(test_corpus).toarray()
y = train.iloc[:, 1]

print(x_test.shape)

Теперь проделаем то же самое с тестовыми данными.

test_corpus = []

for i in range(0, 1953):
  review = re.sub('[^a-zA-Z]', ' ', test['tweet'][i])
  review = review.lower()
  review = review.split()
  
  ps = PorterStemmer()
  
  # stemming
  review = [ps.stem(word) for word in review if not word in set(stopwords.words('english'))]
  
  # joining them back with space
  review = ' '.join(review)
  test_corpus.append(review) 

Удаление стоп-слов и лемматизация (Лемматизация, в отличие от Stemming, сокращает изменяемые слова должным образом, гарантируя, что корневое слово принадлежит языку. В лемматизации корневое слово называется леммой. Лемма (леммы множественного числа) - это лемма каноническая форма, словарная форма или форма цитирования набора слов.) также является важным шагом, когда дело доходит до обработки Естественного языка.

# removing unwanted patterns from the data

import re
import nltk

nltk.download('stopwords')
from nltk.corpus import stopwords
from nltk.stem.porter import PorterStemmer
# for train data
train_corpus = []

for i in range(0, 7920):
  review = re.sub('[^a-zA-Z]', ' ', train['tweet'][i])
  review = review.lower()
  review = review.split()
  
  ps = PorterStemmer()
   # stemming
  review = [ps.stem(word) for word in review if not word in set(stopwords.words('english'))]
  
  # joining them back with space
  review = ' '.join(review)
  train_corpus.append(review)
# for test data
test_corpus = []

for i in range(0, 1953):
  review = re.sub('[^a-zA-Z]', ' ', test['tweet'][i])
  review = review.lower()
  review = review.split()
  
  ps = PorterStemmer()
  
  # stemming
  review = [ps.stem(word) for word in review if not word in set(stopwords.words('english'))]
  
  # joining them back with space
  review = ' '.join(review)
  test_corpus.append(review)

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

# creating bag of words for train
# creating bag of words

from sklearn.feature_extraction.text import CountVectorizer

cv = CountVectorizer(max_features = 1500)
x = cv.fit_transform(train_corpus).toarray()
y = train.iloc[:, 1]

print(x.shape)
print(y.shape)
-------
(7920, 1500)
(7920,)
# creating bag of words for test

from sklearn.feature_extraction.text import CountVectorizer

cv = CountVectorizer(max_features = 1500)
x_test = cv.fit_transform(test_corpus).toarray()
y = train.iloc[:, 1]

print(x_test.shape)
-------
(1953, 1500)
# standardization

from sklearn.preprocessing import StandardScaler

sc = StandardScaler()

x_train = sc.fit_transform(x_train)
x_valid = sc.transform(x_valid)

Стандартизация также является важным шагом перед тем, как мы продолжим процесс моделирования.

После стандартизации мы разделяем данные для обучающих и тестовых целей.

from sklearn.model_selection import train_test_split

x_train, x_valid, y_train, y_valid = train_test_split(x, y, test_size = 0.25, random_state = 42)

print(x_train.shape)
print(x_valid.shape)
print(y_train.shape)
print(y_valid.shape)
---------------
(5940, 1500)
(1980, 1500)
(5940,)
(1980,)

Метрика оценки, используемая для этого соревнования, - это оценка F1, которая формулируется как 2 * ((точность * отзыв) / (точность + отзыв)).

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

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

  1. Случайный лес
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import confusion_matrix
from sklearn.metrics import f1_score

model = RandomForestClassifier()
model.fit(x_train, y_train)

y_pred = model.predict(x_valid)

print("Training Accuracy :", model.score(x_train, y_train))
print("Validation Accuracy :", model.score(x_valid, y_valid))

# calculating the f1 score for the validation set
print("F1 score :", f1_score(y_valid, y_pred))
---------------
Training Accuracy : 0.9994949494949495
Validation Accuracy : 0.8853535353535353
F1 score : 0.7926940639269406
---------------

# confusion matrix 
cm = confusion_matrix(y_valid, y_pred) 
print(cm)
---------------
[[1319  120]
 [ 107  434]]

2. Классификатор дерева решений

from sklearn.tree import DecisionTreeClassifier

model = DecisionTreeClassifier()
model.fit(x_train, y_train)

y_pred = model.predict(x_valid)

print("Training Accuracy :", model.score(x_train, y_train))
print("Validation Accuracy :", model.score(x_valid, y_valid))

# calculating the f1 score for the validation set
print("f1 score :", f1_score(y_valid, y_pred))

# confusion matrix
cm = confusion_matrix(y_valid, y_pred)
print(cm)
----------------
Training Accuracy : 0.9994949494949495
Validation Accuracy : 0.8378787878787879
f1 score : 0.700280112044818
[[1284  155]
 [ 166  375]]

3. Моделирование SVM

# trying SVC algorithm on the data
from sklearn.svm import SVC

model = SVC()
model.fit(x_train, y_train)

y_pred = model.predict(x_valid)

print("Training Accuracy :", model.score(x_train, y_train))
print("Validation Accuracy :", model.score(x_valid, y_valid))

# calculating the f1 score for the validation set
print("f1 score :", f1_score(y_valid, y_pred))

# confusion matrix
cm = confusion_matrix(y_valid, y_pred)
print(cm)
----------------
Training Accuracy : 0.9644781144781145
Validation Accuracy : 0.8621212121212121
f1 score : 0.7222787385554426
[[1352   87]
 [ 186  355]]

4. Классификатор XG Boost

# trying xgboost classifier on the data
from xgboost import XGBClassifier

model = XGBClassifier()
model.fit(x_train, y_train)

y_pred = model.predict(x_valid)

print("Training Accuracy :", model.score(x_train, y_train))
print("Validation Accuracy :", model.score(x_valid, y_valid))

# calculating the f1 score for the validation set
print("f1 score :", f1_score(y_valid, y_pred))

# confusion matrix
cm = confusion_matrix(y_valid, y_pred)
print(cm)
-------------------
Training Accuracy : 0.8882154882154882
Validation Accuracy : 0.8792929292929293
f1 score : 0.7912663755458514
[[1288  151]
 [  88  453]]

5. Логистическая регрессия

from sklearn.linear_model import LogisticRegression

model = LogisticRegression()
model.fit(x_train, y_train)

y_pred = model.predict(x_valid)

print("Training Accuracy :", model.score(x_train, y_train))
print("Validation Accuracy :", model.score(x_valid, y_valid))

# calculating the f1 score for the validation set
print("f1 score :", f1_score(y_valid, y_pred))

# confusion matrix
cm = confusion_matrix(y_valid, y_pred)
print(cm)
----------------
Training Accuracy : 0.9757575757575757
Validation Accuracy : 0.8323232323232324
f1 score : 0.6897196261682242
[[1279  160]
 [ 172  369]]

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

Заключение

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

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

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

Итак, вот и все в этом. До скорого. Чао..!!!