Análise de sentimento do Twitter | Implementar o modelo de análise de sentimento do Twitter

Conteúdo

Este artigo foi publicado como parte do Data Science Blogathon

Introdução

A análise de sentimentos refere-se a identificar e classificar os sentimentos expressos no texto fonte.. Os tweets geralmente são úteis para gerar muitos dados de sentimento após a análise. Esses dados são úteis para entender a opinião das pessoas sobre diversos tópicos..

Portanto, precisamos desenvolver um Modelo automatizado de análise de sentimentos de aprendizado de máquina para calcular a percepção do cliente. Devido à presença de caracteres não úteis (coletivamente referido como ruído) juntamente com dados úteis, é difícil implementar modelos neles.

Neste artigo, nosso objetivo é analisar o sentimento dos tweets fornecidos pelo Conjunto de dados Sentiment140 desenvolvendo um pipeline de aprendizado de máquina envolvendo o uso de três classificadores (Regressão logística, Bernoulli Naive Bayes e SVM) junto com o uso Frequência do Termo – Frequência de documentos reversos (TF-IDF). O desempenho desses classificadores é então avaliado usando precisão e Pontuações da F1.

1p3ste5r_ijzi5icsmfkmtg-1037624

Fonte da imagem: Imagens do google

Exposição do problema

Neste projeto, Tentamos implementar um Modelo de análise de sentimento do Twitter que ajuda a superar os desafios de identificar os sentimentos dos tweets. Os detalhes necessários sobre o conjunto de dados são:

O conjunto de dados fornecido é Conjunto de dados Sentiment140 que consiste em 1,600,000 tweets que foram extraídos usando a API do Twitter. As várias colunas presentes no conjunto de dados são:

  • objetivo: a polaridade do tweet (positiva o negativa)
  • identificadores: Identificação única do tweet
  • encontro: a data do tweet
  • bandeira: Refere-se à consulta. Se não existe tal consulta, então não é consulta.
  • Nome do usuário: Refere-se ao nome do usuário que tuitou.
  • texto: Refere-se ao texto do tweet.

Canalização do projeto

Os vários passos envolvidos no Pipeline de Aprendizagem de Máquina estão :

  • Importação de dependências necessárias
  • Leia e carregue o conjunto de dados
  • Análise exploratória de dados
  • Visualização de dados variáveis de destino
  • Pré-processamento de dados
  • Dividir nuestros datos en subconjuntos de Treinamento e teste
  • Transforme o conjunto de dados usando o Vetorizador TF-IDF
  • Papel para avaliação de modelos
  • Construção do modelo
  • conclusão

Comecemos,

Paso 1: importar as dependências necessárias

# utilidades
import re
import numpy as np
import pandas as pd
# plotting
import seaborn as sns
from wordcloud import WordCloud
import matplotlib.pyplot as plt
# nltk
from nltk.stem import WordNetLemmatizer
# sklearn
from sklearn.svm import LinearSVC
from sklearn.naive_bayes import BernoulliNB
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics import confusion_matrix, classificação_report

Paso 2: leia e carregue o conjunto de dados

# Importing the dataset
DATASET_COLUMNS=['target','ids','date','flag','user','text']
DATASET_ENCODING = "ISO-8859-1"
df = pd.read_csv('Project_Data.csv', codificação=DATASET_ENCODING, nomes=DATASET_COLUMNS)
df.sample(5)

Produção:

67014captura de tela202021-06-1020at208-10-5720pm-9458935

Paso 3: Análise exploratória de dados

3.1: Cinco registros principales de datos

df.head()

Produção:

57381captura de tela202021-06-1020at208-11-1520pm-1044621

3.2: Colunas / características en los datos

df.columns

Produção:

Índice(['target', 'ids', 'date', 'flag', 'user', 'text'], dtype ="objeto")

3.3: Longitud del conjunto de datos

imprimir('comprimento dos dados é', len(df))

Produção:

comprimento de dados é 1048576

3.4: Forma de los datos

df. forma

Produção:

(1048576, 6)

3.5: Información de datos

df.info()

Produção:

25332captura de tela202021-06-1020at208-12-0720pm-7008683

3.6: Tipos de datos de todas as colunas

df.dtypes

Produção:

target     int64
ids        int64
date      object
flag      object
user      object
text      object
dtype: objeto

3.7: Comprobación de valores nulos

np.sum(df.isnull().qualquer(eixo = 1))

Produção:

0

3.8: Filas y columnas en el conjunto de datos

imprimir('Contagem de colunas nos dados é:  ', len(df.columns))
imprimir('Contagem de linhas nos dados é:  ', len(df))

Produção:

Contagem de colunas nos dados é:   6
Contagem de linhas nos dados é:   1048576

3.9: Verifique valores objetivo únicos

df['target'].exclusivo()

Produção:

variedade([0, 4], dtype=int64)

3.10: Verifique el número de valores objetivo

df['target'].agora()

Produção:

2

Paso 4: Visualização de datos de variáveis de destino

# Plotando a distribuição para conjunto de dados.
ax = df.groupby('target').contar().enredo(kind='bar', título ="Distribuição de dados",legend=False)
ax.set_xticklabels(['Negativo','Positivo'], rotação = 0)
# Armazenamento de dados em listas.
texto, sentimento = lista(df['text']), Lista(df['target'])

Produção:

29360captura de tela202021-06-1020at208-12-2420pm-2060372
importado do mar como sns
sns.countplot(x='target', data = df)

Produção:

92032captura de tela202021-06-1020at208-12-3420pm-5349849

Paso 5: pré-processamento de dados

En la declaración del problema anterior antes de entrenar el modelo, executamos várias etapas de pré-processamento no conjunto de dados que se preocupavam principalmente com a remoção de palavras irrelevantes, excluir emoji. Mais tarde, o documento de texto é convertido em minúsculas para melhor generalização.

Subseqüentemente, pontuações foram limpas e removidas, reduzindo assim o ruído desnecessário do conjunto de dados. Depois disso, também removemos caracteres repetidos de palavras junto com a remoção de URLs, uma vez que não têm importância significativa.

Finalmente, Executamos Derivação (reduzindo as palavras às suas raízes derivadas) e Lematización (reduzindo palavras derivadas à sua forma raiz conhecida como lema) para melhores resultados.

5.1: Selecione o texto de destino e a coluna para nossa análise posterior

data = df[['text','target']]

5.2: Substituição de valores para facilitar o entendimento. (atribuindo 1 ao sentimento positivo 4)

dados['target'] = dados['target'].substituir(4,1)

5.3: Imprima valores exclusivos de variáveis ​​de destino

dados['target'].exclusivo()

Produção:

variedade([0, 1], dtype=int64)

5.4: Separação de tweets positivos e negativos

data_pos = dados[dados['target'] == 1]
dados_neg = dados[dados['target'] == 0]

5.5: pegando um quarto dos dados para que possamos rodar em nossa máquina facilmente

data_pos = data_pos.iloc[:int(20000)]
data_neg = data_neg.iloc[:int(20000)]

5.6: Combinando tweets positivos e negativos

conjunto de dados = pd.concat([data_pos, data_neg])

5.7: Deixe o texto da declaração em letras minúsculas

conjunto de dados['text']=conjunto de dados['text'].str.lower()
conjunto de dados['text'].cauda()

Produção:

53934captura de tela202021-06-1020at208-12-5020pm-2788415

5.8: Conjunto de definições contendo todas as palavras de parada em inglês.

lista de palavras irrelevantes = ['a', 'about', 'above', 'after', 'again', 'ain', 'all', 'am', 'an',
             'and','any','are', 'as', 'at', 'be', 'because', 'been', 'before',
             'being', 'below', 'between','both', 'by', 'can', 'd', 'did', 'do',
             'does', 'doing', 'down', 'during', 'each','few', 'for', 'from',
             'further', 'had', 'has', 'have', 'having', 'he', 'her', 'here',
             'hers', 'herself', 'him', 'himself', 'his', 'how', 'i', 'if', 'em',
             'into','é', 'isso', 'its', 'itself', 'just', 'll', 'm', 'ma',
             'me', 'more', 'most','my', 'myself', 'now', 'o', 'de', 'on', 'once',
             'only', 'or', 'other', 'our', 'ours','ourselves', 'out', 'own', 're','s', 'same', 'she', "Shes", 'should', "deveve",'so', 'some', 'such',
             't', 'than', 'que', "Thatll", 'o', 'their', 'theirs', 'them',
             'themselves', 'then', 'there', 'these', 'they', 'isto', 'those',
             'through', 'para', 'too','under', 'until', 'up', 've', 'very', 'foi',
             'we', 'were', 'what', 'when', 'where','which','while', 'quem', 'whom',
             'why', 'will', 'com', 'won', 'y', 'you', "youd","você vai", "Youre",
             "você tem", 'your', 'yours', 'yourself', 'yourselves']

5.9: Limpiar y eliminar la lista de palabras vacías anterior del texto del tweet

STOPWORDS = conjunto(stopwordlist)
def cleaning_stopwords(texto):
    Retorna " ".Junte([palavra por palavra em str(texto).dividir() se a palavra não em STOPWORDS])
conjunto de dados['text'] = conjunto de dados['text'].Aplique(texto lambda: cleaning_stopwords(texto))
conjunto de dados['text'].cabeça()

Produção:

91584captura de tela202021-06-1020at208-13-0220pm-3791656

5.10: Limpieza y eliminación de puntuaciones

import string
english_punctuations = string.punctuation
punctuations_list = english_punctuations
def cleaning_punctuations(texto):
    tradutor = str.maketrans('', '', punctuations_list)
    texto de retorno.traduzir(Translator)
conjunto de dados['text']= conjunto de dados['text'].Aplique(lambda x: cleaning_punctuations(x))
conjunto de dados['text'].cauda()

Produção:

85465captura de tela202021-06-1020at208-13-1320pm-5481281

5.11: Limpieza y eliminación de caracteres repetidos

cleaning_repeating_char def(texto):
    retorno re.sub(r'(.)1+', r'1', texto)
conjunto de dados['text'] = conjunto de dados['text'].Aplique(lambda x: cleaning_repeating_char(x))
conjunto de dados['text'].cauda()

Produção:

25435captura de tela202021-06-1020at208-13-2320pm-9343495

5.12: Limpieza y eliminación de URL

def cleaning_URLs(dados):
    retorno re.sub('((www.[^s]+)|(https?://[^s]+))',' ',dados)
conjunto de dados['text'] = conjunto de dados['text'].Aplique(lambda x: cleaning_URLs(x))
conjunto de dados['text'].cauda()

Produção:

85220captura de tela202021-06-1020at208-13-2320pm-3419546

5.13: Limpieza y eliminación de números numéricos

def cleaning_numbers(dados):
    retorno re.sub('[0-9]+', '', dados)
conjunto de dados['text'] = conjunto de dados['text'].Aplique(lambda x: cleaning_numbers(x))
conjunto de dados['text'].cauda()

Produção:

63689captura de tela202021-06-1020at208-13-3220pm-3961824

5.14: Obtención de tokenización del texto del tweet

from nltk.tokenize import RegexpTokenizer
tokenizer = RegexpTokenizer(r'w+')
conjunto de dados['text'] = conjunto de dados['text'].Aplique(tokenizer.tokenize)
conjunto de dados['text'].cabeça()

Produção:

23569captura de tela202021-06-1020at208-13-5320pm-4926217

5.15: Aplicación de la derivación

import nltk
st = nltk.PorterStemmer()
def stemming_on_text(dados):
    text = [st.stem(palavra) para palavra em dados]
    return data
dataset['text']= conjunto de dados['text'].Aplique(lambda x: stemming_on_text(x))
conjunto de dados['text'].cabeça()

Produção:

18755captura de tela202021-06-1020at208-14-0220pm-3113940

5.16: Aplicación de Lemmatizer

im = nltk. WordNetLemmatizer()
def lemmatizer_on_text(dados):
    text = [lm.lemmatize(palavra) para palavra em dados]
    return data
dataset['text'] = conjunto de dados['text'].Aplique(lambda x: lemmatizer_on_text(x))
conjunto de dados['text'].cabeça()

Produção:

62766captura de tela202021-06-1020at208-14-2120pm-4989573

5.17: Separação da função de entrada e do rótulo

X=data.text
y=data.target

5.18: traçar uma nuvem de palavras para tweets negativos

dados_neg = dados['text'][:800000]
plt.figure(figsize = (20,20))
wc = WordCloud(max_words = 1000 , largura = 1600 , altura = 800,
               colloations=Falso).gerar(" ".Junte(data_neg))
plt.imshow(BANHEIRO)

Produção:

15150captura de tela202021-06-1020at208-14-4420pm-4073164

5.19: traçar uma nuvem de palavras para tweets positivos

data_pos = dados['text'][800000:]
wc = WordCloud(max_words = 1000 , largura = 1600 , altura = 800,
              colloations=Falso).gerar(" ".Junte(data_pos))
plt.figure(figsize = (20,20))
plt.imshow(BANHEIRO)

Produção:

89129captura de tela202021-06-1020at208-14-5720pm-6546986

Paso 6: Quebre nossos dados em subconjuntos de treinamento e teste

# Separando o 95% dados para dados de treinamento e 5% for testing data
X_train, X_test, y_train, y_test = train_test_split(X,e,test_size = 0.05, random_state =26105111)

Paso 7: Transforme o conjunto de dados usando o Vetorizador TF-IDF

7.1: Instale o vetorizador TF-IDF

vetoriser = TfidfVectorizer(ngram_range=(1,2), max_features=5000000)
vectoriser.fit(X_train)
imprimir('No. de feature_words: ', len(vectoriser.get_feature_names()))

Produção:

Não. de feature_words:  500000

7.2: Transforme dados usando o Vetorizador TF-IDF

X_train = vectoriser.transform(X_train)
X_test = vectoriser.transform(X_test)

Paso 8: Papel para avaliação de modelos

Depois de treinar o modelo, aplicamos as medidas de avaliação para verificar o desempenho do modelo. Em consequência, utilizamos los siguientes parametros de evaluación para verificar el rendimiento de los modelos respectivamente:

  • Puntuación de precisión
  • Matriz de confusão con trama
  • Curva ROC-AUC
def model_Evaluate(modelo):
# Predict values for Test dataset
y_pred = model.predict(X_test)
# Imprima as métricas de avaliação para o conjunto de dados.
imprimir(classificação_report(y_test, y_pred))
# Compute and plot the Confusion matrix
cf_matrix = confusion_matrix(y_test, y_pred)
categorias = ['Negativo','Positivo']
group_names = ['True Neg','False Pos', 'False Neg','True Pos']
group_percentages = ['{0:.2%}'.format(valor) para o valor em cf_matrix.achatar() / np.sum(cf_matrix)]
a primeira coisa que fazemos é identificar se os dados são estacionários ou não estacionários [f'{v1}n{v2}' for v1, v2 no zip(group_names,group_percentages)]
rótulos = np.asarray(rótulos).remodelar(2,2)
sns.heatmap(cf_matrix, ano = rótulos, cmap = 'Blues',fmt="",
xticklabels = categorias, yticklabels = categorias)
plt.xlabel("Valores previstos", fontdict = {'size':14}, labelpad = 10)
plt.ylabel("Valores reais" , fontdict = {'size':14}, labelpad = 10)
plt.title ("Matriz de Confusão", fontdict = {'size':18}, pad = 20)

Paso 9: Construção de maquete

En el planteamiento del problema hemos utilizado tres modelos diferentes respectivamente:

  • Bernoulli Bayes ingênuo
  • SVM (máquina vetorial de suporte)
  • Regressão logística

A ideia por trás da escolha desses modelos é que queremos testar todos os classificadores no conjunto de dados., de modelos simples a complexos, e, em seguida, tentar encontrar o que oferece o melhor desempenho entre eles.

8.1: Modelo-1

BNBmodel = BernoulliNB()
BNBmodel.fit(X_train, y_train)
model_Evaluate(Modelo BNB)
y_pred1 = BNBmodel.predict(X_test)

Produção:

75541captura de tela202021-06-1020at208-15-1520pm-3206593

8.2: Plote a curva ROC-AUC para o modelo 1

de sklearn.metrics importação roc_curve, auc
fpr, Tpr, limiares = roc_curve(y_test, y_pred1)
roc_auc = auc(fpr, Tpr)
plt.figure()
plt.plot(fpr, Tpr, color ="darkorange", lw=1, rótulo ="Curva ROC (área = %0,2f)" % roc_auc)
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC CURVE')
plt.legend(loc ="inferior direito")
plt.show()

Produção:

73781captura de tela202021-06-1020at208-15-2920pm-8920880

8.3: Modelo-2:

Modelo SVC = LinearSVC()
SVCmodel.fit(X_train, y_train)
model_Evaluate(Modelo SVC)
y_pred2 = SVCmodel.predict(X_test)

Produção:

61122captura de tela202021-06-1020at208-15-5520pm-3211030

8.4: Plote a curva ROC-AUC para o modelo 2

de sklearn.metrics importação roc_curve, auc
fpr, Tpr, limiares = roc_curve(y_test, y_pred2)
roc_auc = auc(fpr, Tpr)
plt.figure()
plt.plot(fpr, Tpr, color ="darkorange", lw=1, rótulo ="Curva ROC (área = %0,2f)" % roc_auc)
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC CURVE')
plt.legend(loc ="inferior direito")
plt.show()

Produção:

32227captura de tela202021-06-1020at208-15-2920pm-9998358

8.5: Modelo-3

LRmodel = LogisticRegression(C = 2, max_iter = 1000, n_jobs = -1)
LRmodel.fit(X_train, y_train)
model_Evaluate(Modelo LR)
y_pred3 = LRmodel.predict(X_test)

Produção:

41202captura de tela202021-06-1020at208-16-1320pm-8188251

8.6: Plote a curva ROC-AUC para o modelo 3

de sklearn.metrics importação roc_curve, auc
fpr, Tpr, limiares = roc_curve(y_test, y_pred3)
roc_auc = auc(fpr, Tpr)
plt.figure()
plt.plot(fpr, Tpr, color ="darkorange", lw=1, rótulo ="Curva ROC (área = %0,2f)" % roc_auc)
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC CURVE')
plt.legend(loc ="inferior direito")
plt.show()

Produção:

40872captura de tela202021-06-1020at208-15-2920pm-5687366

Paso 10: conclusão

Ao avaliar todos os modelos, podemos concluir os seguintes detalhes, ou seja,

Precisão: Sobre a precisão do modelo, regressão logística tem melhor desempenho do que SVM, que por sua vez funciona melhor do que Bernoulli Naive Bayes.

Pontuação F1: As pontuações da F1 para a classe 0 e a classe 1 filho:
(uma) Aqui x é considerado como a variável dependente e y é considerado como a variável independente 0: Bernoulli Naive Bayes (precisão = 0,90) <SVM (precisão = 0,91) <Regressão logística (precisão = 0,92)
(b) Aqui x é considerado como a variável dependente e y é considerado como a variável independente 1: Bernoulli Naive Bayes (precisão = 0,66) <SVM (precisão = 0,68) <Regressão logística (precisão = 0,69)

Pontuação AUC: Todos os três modelos têm a mesma pontuação ROC-AUC.

Portanto, concluímos que a regressão logística é o melhor modelo para o conjunto de dados acima.

Em nossa declaração de problema, Regressão logística está seguindo o princípio de navalha de Occam que define isso para uma declaração de problema em particular, se os dados não tiverem suposições, então o modelo mais simples funciona melhor. Como nosso conjunto de dados não possui suposições e a Regressão Logística é um modelo simples, o conceito é válido para o conjunto de dados mencionado acima.

Notas finais

Espero que tenha gostado do artigo.

Se você quiser se conectar comigo, Não duvide em manter contato comigo. sobre Correio eletrônico

Suas sugestões e dúvidas são bem-vindas aqui na seção de comentários. Obrigado por ler o meu artigo!

A mídia mostrada neste artigo não é propriedade da Analytics Vidhya e é usada a critério do autor.

Assine a nossa newsletter

Nós não enviaremos SPAM para você. Nós odiamos isso tanto quanto você.

Datapeaker