Analise de Sentimentos — Naive Bayes




Analise de Sentimentos — Naive Bayes

Na próxima série de tópicos, vamos mergulhar em diferentes abordagens para resolver o problema do Olá Mundo da NLP, a análise de sentimentos.

O código esta disponível aqui.

O classificador Naive Bayes

O classificador Naive Bayes usa o Teorema de Bayes, que para o nosso problema diz que a probabilidade do rótulo (positivo ou negativo) para o texto dado é igual à probabilidade de encontrarmos esse texto dado o rótulo , vezes a probabilidade de um rótulo ocorrer, tudo dividido pela probabilidade de encontrarmos esse texto:

\[P(label|text) = \frac{P(text|label) * P(label)}{P(text)}\]

Como o texto é composto de palavras, podemos dizer:

\[P(label|word_1, word_2, ..., word_n) = \frac{P(word_1, word_2, ..., word_n|label) * P(label)}{P(word_1, word_2, ..., word_n)}\]

Queremos comparar as probabilidades dos rótulos e escolher aquele com maior probabilidade. Como o termo P(word_1, word_2, …, word_n) é igual para tudo, podemos removê-lo. Supondo que não haja dependência entre palavras no texto (o que pode causar alguns erros, pois algumas palavras só “funcionam” juntas com outras), temos:

\[P(label|word_1, word_2, ..., word_n) = P(word_1|label) * P(word_2|label) * ... * P(word_n|label) * P(label)\]

Então terminamos! Com um conjunto de treinamento, podemos encontrar cada termo da equação, por exemplo:

O código

Para esta tarefa usaremos uma famosa biblioteca de aprendizado de máquina de código aberto, a scikit-learn .

Nosso conjunto de dados é composto por resenhas de filmes e rótulos que informam se a crítica é negativa ou positiva. Vamos carregar o conjunto de dados:

O arquivo de reviews é um pouco grande, então está em formato zip. Vamos Extraí-lo:

import zipfile
with zipfile.ZipFile("reviews.zip", 'r') as zip_ref:
    zip_ref.extractall(".")

Agora que temos os arquivos reviews.txt e labels.txt, vamos carregá-los na memória:

with open("reviews.txt") as f:
    reviews = f.read().split("\n")
with open("labels.txt") as f:
    labels = f.read().split("\n")
    
reviews_tokens = [review.split() for review in reviews]

Em seguida, carregamos o módulo para transformar nossas entradas de revisão em vetores binários com a ajuda da classe MultiLabelBinarizer:

from sklearn.preprocessing import MultiLabelBinarizer
onehot_enc = MultiLabelBinarizer()
onehot_enc.fit(reviews_tokens)

Depois disso, dividimos os dados em conjunto de treinamento e teste com a train_test_split função:

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(reviews_tokens, labels, test_size=0.25, random_state=None)

Em seguida, criamos um classificador Naive Bayes e treinamos nossos dados. Usaremos um classificador Bernoulli Naive Bayes que é apropriado para vetores de características compostos de dados binários. Fazemos isso com a classe BernoulliNB:

from sklearn.naive_bayes import BernoulliNB

bnbc = BernoulliNB(binarize=None)
bnbc.fit(onehot_enc.transform(X_train), y_train)

Treinar o modelo levou apenas 1 segundo!

Após o treinamento, utilizamos a scorefunção para verificar o desempenho do classificador:

score = bnbc.score(onehot_enc.transform(X_test), y_test)

O cálculo da pontuação levou apenas 0,4 segundos!

Rodando o classificador algumas vezes, obtemos cerca de 85% de precisão. Nada mal para um classificador tão simples.