Sua primeira análise de sentimentos com scikit-learn

Aplicando TF-IDF, Bag of Words e aprendizagem de máquina para criar um classificador de reviews com uma das principais libs do Python

Camilla Fonseca
Turing Talks
8 min readApr 4, 2021

--

Photo by Markus Winkler on Unsplash

Olá e bem-vindo a mais um Turing Talks de NLP!

Há algum tempo, fizemos um texto de Introdução a Bag of Words e TF-IDF, explicando como funcionam essas técnicas e mostrando como programá-las do 0. Hoje, vou mostrar como aplicar essas técnicas usando a biblioteca scikit-learn, mas não só! Vou mostrar como treinar um modelo de análise de sentimentos de reviews de produtos, desde a limpeza do dataset até a avaliação do modelo.

Sugiro fortemente ler o texto acima antes de seguir, mas irei retomar os conceitos ao longo do texto de hoje conforme necessário. Além disso, o notebook com o todo o código pode ser encontrado aqui.

E se você ainda não sabe o que é uma análise de sentimentos: é uma tarefa de NLP que visa classificar os sentimentos de um texto dividindo-os, por exemplo, em Positivo, Negativo ou Neutro, ou Feliz, Triste, Nervoso ou Neutro, ou várias outras formas, vai depender do seu problema.

Isso tem várias aplicações interessantes, por exemplo, saber se o público está gostando ou não de um produto. Podemos automatizar esse trabalho extraindo comentários sobre o produto na internet e usando um desses modelos. E isso nos leva ao dataset de hoje…

Sobre o dataset

O Brazilian E-Commerce Public Dataset by Olist possui diversos dados sobre compras feitas no site Olist. Se você der uma conferida no link, verá que há vários arquivos, porém aqui estaremos usando apenas o ‘olist_order_reviews_dataset.csv’, que contém as reviews feitas pelos usuários dessas compras.

Uma observação é que os dados foram anonimizados e por isso no texto aparecem nomes de casas de Game of Thrones no lugar do nome das lojas.

Pré-processamento dos dados

Primeiro, vamos importar as bibliotecas necessárias:

Agora, vamos ler e dar uma olhada no dataset com a bilbioteca pandas:

Deixei aqui apenas as 10 primeiras linhas do output, você pode ver o resto no notebook do kaggle.

Limpando o dataset

Como nosso foco é a análise de sentimentos, não precisamos das colunas order_id, review_creation_date e review_answer_timestamp, podemos então removê-las:

Agora, vamos verificar os tipos de dados das colunas e quantos dados nulos há em cada uma:

‘object’ sinaliza que os dados na coluna são strings e ‘int64’, inteiros.

Temos pouco menos de 100000 datapoints, todos possuindo um score de review, mas nem todos possuem review escrita. Vamos então verificar se há dados duplicados baseado no id e removê-los:

Como estamos interessados justamente no texto, vamos juntar as colunas review_comment_title e review_comment_message em uma só (coluna nova review) e tirar entradas que não possuem texto.

Após isso, ficamos com 43152 datapoints.

Review scores

Na coluna review_scores, há 5 valores de score diferentes (indo de 1-pior até 5-melhor), porém, para facilitar nossa tarefa, vamos classificar as reviews apenas como positiva ou negativa. Se o score for menor ou igual a 3, consideraremos negativa (0) e caso contrário, positiva (1). Essas serão as labels que usaremos para treinar o modelo e vamos armazená-las em uma nova coluna:

É sempre bom conferir o quão balanceada é a distribuição dos dados nas labels:

Vemos que há bem mais reviews positivas do que negativas, mas não é uma disparidade tão grande a ponto de precisarmos tratá-la em um primeiro momento.

Pré-processamento do texto

Os pré-processamentos são etapas de preparação do texto com o objetivo de reduzir o tamanho do vocabulário (conjunto de palavras que ocorrem em todos os textos do dataset) e simplificar algumas formas lexicais para que o nosso algoritmo consiga extrair informações relevantes e tenha um desempenho melhor. No entanto, não vou explicar a fundo cada etapa aqui. Para isso, você pode conferir o seguinte Turing Talk:

Os pré-processamentos que irei fazer são:

  • Deixar tudo em minúsculo (para que o computador não considere ‘brasil’ e ‘Brasil’ como palavras diferentes)
  • Filtrar apenas letras (removendo pontuações, símbolos, etc)
  • Remover stopwords (palavras que se repetem muito no texto mas adicionam pouca informação, como ‘de’)
  • Lematizar (simplificação lexical, por exemplo, passando os verbos para o infinitivo e passando substantivos e adjetivos para o masculino singular)

Para remoção de stopwords, vamos usar a lista disponível na biblioteca nltk. Nessa lista constam as palvras ‘não’ e ‘nem’, que se removidas podem mudar a interpretação do sentimento de uma frase e por isso resolvi remover da lista de stopwords:

Além disso, usaremos o lematizador da biblioteca spacy. Para isso, precisamos fazer o download de um modelo de português da lib. Se você estiver usando o Jupyter ou o Google Colab, rode a seguinte célula:

Se estiver usando um Kaggle Notebook, precisará habilitar internet no kernel (vá em Settings -> Internet e selecione Internet connected) e então rode a seguinte célula:

Após o download, podemos importar o modelo:

Agora, estamos prontos para criar uma função que realiza os pré-processamentos e aplicá-la no dataset!

Como tinham reviews com apenas números ou emojis, ainda há dados faltantes na coluna review, vamos removê-los:

Obs: Também poderíamos ter usado a spacy para tirar as stopwords, o que faria mais sentido já que iríamos usar o lematizador dela depois de qualquer forma. No entanto, nesse caso, usar a lista da nltk deu melhores resultados. Um possível motivo é que a lista de stopwords da spacy é maior e pode ter tirado palavras importantes para a análise de sentimentos.

Feature extraction

Essa etapa consiste em transformar o texto em uma informação numérica, mais precisamente um vetor, para que seja possível utilizá-lo para alimentar um modelo.

Aqui, vou mostrar como usar a scikit-learn (a.k.a. sklearn) para realizar as duas técnicas de feature extraction citadas no início: Bag of Words e TF-IDF.

Bag of Words (BoW)

Essa primeira representa o texto como um vetor em que cada elemento corresponde a uma palavra do vocabulário e seu valor é quantidade de vezes em que tal palavra aparece nesse texto, ou então simplesmente 0 se a palavra não aparece nele e 1 se não.

A função CountVectorizer da sklearn faz isso pra gente! O parâmetro binary indica se será usada a contagem total das palavras ou apenas 0 e 1 (eu usei essa última opção). Já o parâmetro max_features define o tamanho do vocabulário, assim max_features = 5000 constrói o vocabulário com as 5000 palavras que mais ocorrem no total dos textos.

TF-IDF

Já essa técnica vetoriza o texto atribuindo para cada palavra uma pontuação que mede a importância dela nesse texto. Também há uma função na sklearn que já faz isso para a gente: TfidfVectorizer!

Lembrando que se quiser uma explicação mais a fundo das duas técnicas e suas vantagens e desvantagens, basta ler esse texto.

Modelo

Aqui, vou comparar o desempenho do modelo com os dados vetorizados tanto com BoW como com Tf-idf.

Mas primeiro, é preciso dividir os dados em base de treino (70%) e teste (30%):

Vamos também importar as métricas que serão usadas para avaliação de cada modelo e definir uma função para mostrá-las:

Se quiser entender melhor alguma das métricas usadas acima, pode conferir no Turing Talk abaixo:

O modelo que mostrarei aqui é uma regressão logística, que apresentou as melhores métricas, porém também foram testados outros, se quiser ver é só checar no notebook do kaggle!

Texto vetorizado com Bag of Words

Vamos agora ver as métricas:

Texto vetorizado com tf-idf

Resultados

Analisando as métricas, vemos que a diferença entre usar Bag of Words ou TF-IDF foi bem pequena, apesar de o modelo treinado com os dados com TF-IDF ter ido melhor, com acurácia e F1 de 90% e AUROC de 89% (arredondando).

Vamos agora ̶b̶r̶i̶n̶c̶a̶r̶ testar com novas predições!

Conclusão

O principal objetivo desse texto era mostrar as etapas básicas para o treinamento de um modelo de análise de sentimentos, o que espero que tenha sido atingido com sucesso!

É claro que ainda há espaço para testar outras coisas e quem sabe melhorar o modelo! Poderíamos fazer pré-processamentos diferentes, por exemplo: já que havia emojis em algumas reviews e esse é um dos principais meios das pessoas expressarem seus sentimentos, talvez fosse interessantes incluí-los na análise.

Poderíamos também explorar outras ferramentas de NLP, como as apresentadas no texto abaixo:

Esses testes é algo que vou deixar como lição de casa para você e se achar algo legal, pode contar aí nos comentários ;)

Por fim, para mais textos como esse, continue acompanhando o Turing Talks! E se quiser saber mais sobre o Grupo Turing siga a gente nas redes sociais: Facebook, Linkedin, Instagram e servidor no Discord!

--

--

Camilla Fonseca
Turing Talks

Statistics student at USP, pure and applied maths enthusiast and undergrad researcher interested in machine learning.