Análise de Sentimentos
A análise de sentimentos é uma técnica da Inteligência Artificial (IA). Mais especificamente, ela pertence ao processamento de linguagem natural, uma subárea da IA. A análise de sentimentos lida com a compreensão do tom emocional dos dados de texto. Geralmente, ela se concentra em classificar automaticamente se um texto expressa um sentimento positivo, negativo ou neutro, mas existem variações. De forma geral, a análise de sentimentos capacita as máquinas a entender as emoções subjacentes aos textos. Ao entender sentimentos, os sistemas de IA podem responder de forma mais adequada em chatbots, assistentes virtuais ou outros aplicativos interativos.
Neste post, iniciaremos o desenvolvimento de um modelo de análise de sentimentos. Nesta primeira parte, nos concentraremos na análise exploratória inicial e no pré-processamento dos dados. No post seguinte, usaremos regressão logística, uma técnica de machine learning, para treinar nosso classificador.
Os Dados
Usaremos um conjunto de dados contendo revisões de filmes coletadas no site IMDB. As revisões são em inglês.
O conjunto de dados do IMDB para análise de sentimentos é uma coleção amplamente usada. Ela consiste em revisões de filmes e seus rótulos de sentimento correspondentes. Esse conjunto é um benchmark popular para testar e avaliar algoritmos de análise de sentimentos. Ele contém 50.000 revisões de filmes disponíveis em formato de texto simples, igualmente divididas entre sentimentos positivos e negativos. Cada revisão é rotulada como “positiva” ou “negativa” com base em seu sentimento geral em relação ao filme. Embora o formato desse conjunto de dados seja simples, algumas etapas de pré-processamento, como remover palavras irrelevantes, pontuação e realizar lematização, podem ser necessárias antes de usar os dados para treinamento.
O conjunto de dados pode ser obtido aqui.
Análise Exploratória
Iniciaremos o modelo realizando a análise exploratória dos dados. Usaremos a biblioteca Pandas para essa etapa. Num código Python, importe a biblioteca e abra o conjunto de dados:
import pandas as pd
df = pd.read_csv('IMDB Dataset.csv')
Primeiramente, imprimiremos alguns exemplos dos dados:
print(df.head())
# resultados
# 0 One of the other reviewers has mentioned that ... positive
# 1 A wonderful little production.
The... positive
# 2 I thought this was a wonderful way to spend ti... positive
# 3 Basically there's a family where a little boy ... negative
# 4 Petter Mattei's "Love in the Time of Money" is... positive
Os dados consistem apenas em duas colunas. Uma contém revisões de filmes e a outra, os sentimentos correspondentes.
Usamos o método describe() para visualizar alguns detalhes sobre os dados.
print(df.describe())
# resultados
# review sentiment
# count 50000 50000
# unique 49582 2
# top Loved today's show!!! It was a variety and not... positive
# freq 5 25000
O conjunto de dados possui 50.000 exemplos, cada um com duas colunas. Existem 49.582 exemplos únicos.
O método value_count() do Pandas permite verificar o número de exemplos em cada classe de sentimento.
print(df['sentiment'].value_counts())
# resultados
# positive 25000
# negative 25000
Como mencionado, esse conjunto de dados contém um número igual de revisões positivas e negativas.
Em seguida, verificamos a presença de valores ausentes.
print(df.isnull().sum())
# resultados
# review 0
# sentiment 0
O conjunto de dados não possui nenhum valor ausente.
Também podemos verificar a presença de duplicatas. Essa etapa é opcional.
print(df.duplicated().sum())
# resultado
# 418
O conjunto de dados possui cerca de 400 duplicatas. Removê-las do conjunto é uma questão que varia de caso a caso. Para nosso exemplo, elas serão removidas:
df = df.drop_duplicates()
Idealmente, o mesmo modelo pode ser treinado com ou sem a remoção de duplicatas para verificar seu impacto para o treinamento.
Pré-Processamento
O pré-processamento é a etapa de limpeza e normalização dos dados. Iniciaremos essa etapa convertendo todas as letras das revisões para minúsculas.
df['review'] = df['review'].str.lower()
print(df.head())
# resultados:
# review sentiment
# 0 one of the other reviewers has mentioned that ... positive
# 1 a wonderful little production.
the... positive
# 2 i thought this was a wonderful way to spend ti... positive
# 3 basically there's a family where a little boy ... negative
# 4 petter mattei's "love in the time of money" is... positive
Remoção de Caracteres Especiais
Em seguida, com o auxílio do módulo re do Python, removemos pontuações e outros caracteres especiais:
import re
def remove_special_characters(text, remove_digits=True):
pattern=r'[^a-zA-z0-9\s]'
text=re.sub(pattern,'',text)
return text
df['review'] = df['review'].apply(remove_special_characters)
print(df.head())
# resultados
# review sentiment
# 0 one of the other reviewers has mentioned that ... positive
# 1 a wonderful little production br br the filmin... positive
# 2 i thought this was a wonderful way to spend ti... positive
# 3 basically theres a family where a little boy j... negative
# 4 petter matteis love in the time of money is a ... positive
Remoção de Stop Words
A próxima etapa é a remoção de stop words (palavras de parada). Elas são palavras que aparecem com muita frequência nos textos e acrescentam pouco valor à análise de sentimentos em si. Embora elas contribuam pouco para a análise de sentimentos, suas presenças tornam os dados mais ruidosos. Portanto, retirá-las costuma melhorar o resultado. Elas serão removidas como auxílio da biblioteca de processamento de linguagem natural NLTK:
import nltk
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
nltk.download('stopwords')
stopwords = stopwords.words('english')
df['review'] = df['review'].apply(lambda x: " ".join([x for x in word_tokenize(x) if x not in stopwords]))
Remoção de Palavras Raras
A remoção de palavras raras é uma etapa opcional. Ela consiste em identificar palavras com baixíssima ocorrência no corpus para removê-las. Faremos isso com a ajuda da biblioteca Pandas. Primeiro, calculamos as ocorrências de cada palavra:
# remove palavras raras
temp_df = pd.Series(' '.join(df['review']).split()).value_counts()
print(temp_df)
# resultados:
# br 200425
# movie 84391
# film 76379
# one 51441
# like 38860
# ...
# extricating 1
# noirean 1
# spoilsport 1
# longitude 1
# clatter 1
Depois, removemos as palavras de baixa frequência:
drops = temp_df[temp_df <= 1]
df['review'] = df['review'].apply(lambda x: " ".join([x for x in word_tokenize(x) if x not in drops]))
print(df.head())
# resultados:
# review sentiment
# 0 one reviewers mentioned watching 1 oz episode ... positive
# 1 wonderful little production br br filming tech... positive
# 2 thought wonderful way spend time hot summer we... positive
# 3 basically theres family little boy jake thinks... negative
# 4 matteis love time money visually stunning film... positive
Remoção de br
Verificando as ocorrências das palavras, podemos observar que br é uma palavra com alta ocorrência. Ela é, na verdade, um comando usado para indicar quebra de linha. Ou seja, ela não tem contribuição nenhuma para a análise de sentimentos. Portanto, ela será removida também.
df['review'] = df['review'].apply(lambda x: " ".join([x for x in word_tokenize(x) if x != 'br']))
print(df.head())
# resultados
# review sentiment
# 0 one reviewers mentioned watching 1 oz episode ... positive
# 1 wonderful little production filming technique ... positive
# 2 thought wonderful way spend time hot summer we... positive
# 3 basically theres family little boy jake thinks... negative
# 4 matteis love time money visually stunning film... positive
Lematização
Por fim, realizamos a lematização das palavras usando novamente a NLTK:
from nltk.tokenize import word_tokenize
from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
df['review'] = df['review'].apply(lambda x: " ".join([lemmatizer.lemmatize(x) for x in word_tokenize(x)]))
print(df.head())
# resultados
# review sentiment
# 0 one reviewer mentioned watching 1 oz episode y... positive
# 1 wonderful little production filming technique ... positive
# 2 thought wonderful way spend time hot summer we... positive
# 3 basically there family little boy jake think t... negative
# 4 matteis love time money visually stunning film... positive
Com essa etapa, encerramos a fase de pré-processamento dos dados. Após esse encerramento, podemos salvar os dados limpos num novo arquivo CSV para ser usado posteriormente no treinamento de um classificador. O salvamento pode ser feito como mostrado abaixo:
df.to_csv('data_clean.csv')
No próximo post, usaremos os dados pré-processados para criar um classificador de análise de sentimentos usando regressão logística, uma das técnicas mais simples de machine learning.