ProxynetProxynet

Análise de sentimento em Python: VADER vs Hugging Face

Publicado:

15 min de leitura

Acar Diveroli
Autor: Acar Diveroli
Três cartões de avaliação inclinados com estrelas e barras sob um leque de feixes azuis que chegam a NEG, NEU e POS.

Sua equipe vende três produtos e tem alguns milhares de avaliações de cada um. A média de estrelas quase não muda de um mês para o outro, mas o suporte diz que as reclamações sobre um dos produtos dobraram. Ler todas as avaliações não é uma opção, então você quer um script que marque cada avaliação como positiva, neutra ou negativa e mostre onde o humor está mudando. O primeiro tutorial que você encontra usa o VADER, o segundo um modelo transformer, e os dois dão respostas diferentes para a mesma frase.

Este guia aplica os dois métodos ao mesmo pequeno conjunto de avaliações de produtos. Mostramos como cada um funciona, o código completo e testado (uma passada com léxico usando o NLTK, uma passada com modelo usando o pipeline do Hugging Face e um relatório que agrupa os resultados por produto e mês), quanto cada método concordou com as estrelas e quais avaliações enganaram os dois. Todos os scripts rodaram em 28 de setembro de 2026 com Python 3.13, nltk 3.10.3, pandas 3.0.6, transformers 5.17.0 e a versão para CPU do torch 2.14.

O que é análise de sentimento?

A análise de sentimento, também chamada de mineração de opinião, é a tarefa de decidir que atitude um texto expressa. Para avaliações de produtos, o resultado costuma ser um de três rótulos (positivo, neutro, negativo) ou uma nota em estrelas, muitas vezes com um nível de confiança. Ferramentas em nível de aspecto vão além e separam "som ótimo, bateria fraca" em duas opiniões; isso exige outro tipo de modelo e fica fora deste guia.

Assim como os métodos de Mineração de dados: técnicas, usos e como obter os dados, ela transforma texto não estruturado em uma coluna que você pode contar e colocar em um gráfico. O valor está na tendência, não em uma nota isolada: por exemplo, a proporção de avaliações negativas de um produto subindo depois de uma troca de fornecedor.

Como funciona a análise de sentimento em Python?

Existem duas famílias de ferramentas, e elas funcionam de formas bem diferentes.

Baseadas em léxico (VADER). O VADER, sigla de Valence Aware Dictionary and sEntiment Reasoner, é uma lista de cerca de 7.500 palavras, emoticons e gírias em inglês que avaliadores humanos pontuaram de muito negativo a muito positivo, mais um conjunto de regras. As regras aumentam a pontuação com !!! e com LETRAS MAIÚSCULAS, dão mais peso às palavras depois de "but" do que às anteriores e invertem a pontuação quando uma negação como "not" ou "never" aparece até três palavras antes de uma palavra com carga emocional. O README do vaderSentiment descreve essas regras e os limiares. O NLTK traz o mesmo analisador como nltk.sentiment.vader, documentado no guia de sentimento do NLTK.

Baseadas em modelo (transformers). Um transformer como o BERT foi primeiro treinado com uma grande quantidade de texto e depois ajustado (fine-tuning) com exemplos rotulados por sentimento. Ele transforma a frase inteira em números e lê cada palavra à luz das outras, então "not bad" e "killer" podem ser julgados pelo contexto, e não por um valor fixo. O Hugging Face hospeda milhares de modelos desse tipo, e a função pipeline carrega um deles com uma única linha.

Nos dois casos, a pontuação segue cinco etapas:

  1. Carregar o texto. Uma linha por avaliação, com o produto, a data e, se você tiver, a nota em estrelas.
  2. Dividir ou tokenizar. O VADER trabalha com palavras e pontuação. Um transformer usa o próprio tokenizador, que corta as palavras em pedaços menores e para em um comprimento máximo (512 tokens nos modelos baseados em BERT).
  3. Pontuar. O VADER soma os valores das palavras, aplica suas regras e comprime o total em um valor compound entre -1 e +1. Um modelo retorna uma probabilidade para cada rótulo.
  4. Mapear para um rótulo. No VADER, você escolhe limiares. Com um modelo, você pega o rótulo de maior probabilidade e guarda a pontuação como confiança.
  5. Agregar. Conte os rótulos por produto, semana ou mês, e coloque os resultados ao lado dos números que você já acompanha.

VADER e um modelo transformer comparados

VADER (NLTK)Transformer (Hugging Face)
Como decideLista de palavras pontuadas mais regrasRede neural ajustada com texto rotulado
Tamanho da instalaçãonltk mais um léxico de 90 KBtransformers, torch (cerca de 500 MB na versão para CPU) e um modelo (670 MB o modelo abaixo)
Velocidade no nosso teste (CPU de notebook, avaliações curtas)Cerca de 14.000 avaliações por segundoCerca de 90 avaliações por segundo, mais em uma GPU
IdiomasInglêsDepende do modelo; o modelo abaixo cobre seis
Contexto e negaçãoPor regras, janela de três palavrasAprendidos com exemplos
SaídaProporções neg / neu / pos e uma pontuação compoundRótulo e probabilidade, ou nota em estrelas
Explicar um resultadoFácil: basta consultar as palavrasDifícil: exige ferramentas extras
Nosso teste com 24 avaliações14 de 24 bateram com as estrelas (58%)19 de 24 bateram (79%)

A última linha vem de um conjunto de dados minúsculo e escrito à mão. Ela mostra o tipo de erro que cada método comete, não como eles vão se sair nos seus dados.

Como escolher um modelo do Hugging Face para avaliações de produtos

Muitos modelos de sentimento do hub do Hugging Face foram treinados com tweets ou críticas de filmes. Para avaliações de produtos, três coisas importam:

  • Dados de treinamento. Um modelo treinado com tweets conhece gírias; um treinado com avaliações de produtos conhece o vocabulário de produto.
  • Rótulos. Três rótulos, cinco rótulos ou estrelas. Converta-os para os seus próprios rótulos em um único lugar do código.
  • Licença. Alguns modelos populares têm licença não comercial. Leia o cartão do modelo.

Testamos três modelos multilíngues pequenos com as mesmas 24 avaliações e usamos o nlptown/bert-base-multilingual-uncased-sentiment no código abaixo. Ele foi ajustado com avaliações de produtos em inglês, holandês, alemão, francês, espanhol e italiano, prevê de uma a cinco estrelas e tem licença MIT. O cartão do modelo informa 67% de acerto exato de estrelas e 95% com margem de uma estrela em inglês. O turco não está entre os idiomas dele, então uma avaliação em turco recebe um palpite, não uma resposta aprendida.

Os outros dois foram o lxyuan/distilbert-base-multilingual-cased-sentiments-student (três rótulos, Apache 2.0), que concordou com as nossas estrelas em 13 de 24 avaliações, e o tabularisai/multilingual-sentiment-analysis (cinco rótulos, 16 de 24), que tem licença CC BY-NC 4.0 e, portanto, não é livre para uso comercial.

Os dados de teste: 24 avaliações de produtos

Não usamos avaliações coletadas por scraping. O arquivo abaixo contém 24 avaliações que nós mesmos escrevemos para três produtos inventados, cada uma com data e nota em estrelas, para que os dois métodos possam ser conferidos contra a nota. Incluímos os casos que dão problema em dados reais: sarcasmo, gíria, negação, sentimentos misturados e uma avaliação em alemão, outra em espanhol e outra em turco. Salve como reviews.csv:

text
review_id,product,date,rating,lang,text
1,kettle,2026-07-02,5,en,"Boils a full litre in under three minutes and the lid never drips. Love it."
2,kettle,2026-07-05,4,en,"Solid kettle, a bit loud but it does the job."
3,kettle,2026-07-11,1,en,"Stopped working after two weeks. Support never answered my emails."
4,kettle,2026-07-19,2,en,"The handle gets hot. Not great, not terrible."
5,kettle,2026-08-03,5,en,"Best purchase this year!!! Fast, quiet and it looks good on the counter :)"
6,kettle,2026-08-14,1,en,"Oh great, another kettle that leaks all over the counter. Just what I needed."
7,kettle,2026-08-21,3,en,"It is a kettle. It boils water."
8,kettle,2026-08-30,4,de,"Kocht schnell und ist leise. Gutes Preis-Leistungs-Verhältnis."
9,headphones,2026-07-03,5,en,"The noise cancelling is superb and the battery lasts all week."
10,headphones,2026-07-09,2,en,"Sound is fine but the ear cushions started peeling after a month."
11,headphones,2026-07-15,4,en,"Comfortable for long flights. The app is clunky though."
12,headphones,2026-07-28,1,en,"Right ear cut out on day three. Returned them."
13,headphones,2026-08-06,5,es,"Suenan de maravilla y la batería dura muchísimo."
14,headphones,2026-08-12,3,en,"Bass is heavy. Some people will like it, I am not sure I do."
15,headphones,2026-08-24,2,en,"I wanted to love these, but the Bluetooth keeps dropping."
16,headphones,2026-08-29,4,en,"Not bad at all for the price."
17,backpack,2026-07-01,5,en,"Survived a rainy week in the mountains and everything inside stayed dry."
18,backpack,2026-07-13,4,en,"Lots of pockets. The laptop sleeve is a little tight for a 16 inch model."
19,backpack,2026-07-22,1,en,"The zipper broke on the first trip. Cheap material."
20,backpack,2026-08-02,3,tr,"Fiyatına göre idare eder ama askılar biraz ince."
21,backpack,2026-08-09,5,en,"Killer design, this bag is sick!"
22,backpack,2026-08-17,2,en,"Looks nice in the photos, feels flimsy in real life."
23,backpack,2026-08-26,4,en,"Carries my camera gear without any back pain."
24,backpack,2026-08-31,1,en,"Terrible stitching. The strap tore off after a week."

Avaliações reais precisam de uma limpeza antes da pontuação: duplicatas, restos de HTML no texto, caracteres quebrados. Como limpar dados de scraping com pandas em Python cobre essa etapa.

Etapa 1: pontuar as avaliações com o VADER

Instale as duas bibliotecas em um ambiente virtual:

bash
python -m venv .venv
.venv\Scripts\activate          # macOS/Linux: source .venv/bin/activate
pip install nltk pandas

O script pontua cada frase separadamente e tira a média dos resultados. Acrescentamos isso depois da primeira execução: pontuada como uma única string, a avaliação 1 ("…the lid never drips. Love it.") deu -0,52, porque a janela de negação de três palavras do VADER atravessou o ponto final e inverteu "love". Pontuada frase a frase, deu +0,32.

python
import re

import nltk
import pandas as pd
from nltk.sentiment.vader import SentimentIntensityAnalyzer

nltk.download("vader_lexicon", quiet=True)  # léxico de 90 KB, baixado uma única vez

analyzer = SentimentIntensityAnalyzer()
SENTENCE_END = re.compile(r"(?<=[.!?])\s+")


def vader_compound(text: str) -> float:
    """Pontua cada frase separadamente e tira a média das pontuações compound."""
    sentences = [s for s in SENTENCE_END.split(text) if s.strip()]
    scores = [analyzer.polarity_scores(s)["compound"] for s in sentences]
    return round(sum(scores) / len(scores), 4)


def vader_label(compound: float) -> str:
    # limiares recomendados pelos autores do VADER
    if compound >= 0.05:
        return "positive"
    if compound <= -0.05:
        return "negative"
    return "neutral"


df = pd.read_csv("reviews.csv", parse_dates=["date"])
df["compound"] = df["text"].apply(vader_compound)
df["vader"] = df["compound"].apply(vader_label)

print(df[["review_id", "lang", "compound", "vader"]].to_string(index=False))
df.to_csv("reviews_vader.csv", index=False)

Parte da saída:

text
 review_id lang  compound    vader
         1   en    0.3185 positive
         3   en    0.0878 positive
         6   en    0.3125 positive
         8   de    0.0000  neutral
        17   en    0.4588 positive
        21   en   -0.8356 negative

A avaliação 3 é uma reclamação de uma estrela, mas "support" é uma palavra positiva no léxico e nada negativo pesa mais do que ela. A avaliação 6 é sarcasmo ("Oh great … Just what I needed") e o VADER toma "great" ao pé da letra. A avaliação em alemão tem pontuação exatamente zero, porque nenhuma de suas palavras está no léxico em inglês. A avaliação 21 usa "killer" e "sick" como elogio; o VADER só conhece as duas palavras no sentido negativo.

Etapa 2: pontuar as mesmas avaliações com um modelo do Hugging Face

A passada com modelo precisa do transformers e de um backend de deep learning. Se você não tem GPU, instale primeiro a versão do torch para CPU; ela é bem menor que a versão padrão com CUDA:

bash
pip install torch --index-url https://download.pytorch.org/whl/cpu
pip install transformers

A primeira execução baixa o modelo (cerca de 670 MB) para o cache do Hugging Face. Defina a variável de ambiente HF_HOME se quiser esse cache em outro disco. O nome de tarefa sentiment-analysis é um alias de text-classification; batch_size, truncation e device estão descritos na documentação de pipelines do Transformers.

python
import pandas as pd
from transformers import pipeline

MODEL = "nlptown/bert-base-multilingual-uncased-sentiment"

classifier = pipeline(
    "sentiment-analysis",  # alias de "text-classification"
    model=MODEL,
    device="cpu",          # device=0 para a primeira GPU
)

df = pd.read_csv("reviews_vader.csv", parse_dates=["date"])
results = classifier(
    df["text"].tolist(),
    batch_size=8,
    truncation=True,       # avaliações com mais de 512 tokens são cortadas, não rejeitadas
)


def stars_to_label(stars: int) -> str:
    if stars >= 4:
        return "positive"
    if stars == 3:
        return "neutral"
    return "negative"


df["hf_stars"] = [int(r["label"][0]) for r in results]  # "4 stars" -> 4
df["hf_score"] = [round(r["score"], 3) for r in results]
df["hf"] = df["hf_stars"].apply(stars_to_label)

print(df[["review_id", "rating", "hf_stars", "hf_score", "vader", "hf"]].to_string(index=False))
df.to_csv("reviews_scored.csv", index=False)

Com o modelo já no cache, o script rodou em cerca de sete segundos em uma CPU de notebook, carregamento incluído. Parte da saída:

text
 review_id  rating  hf_stars  hf_score    vader       hf
         3       1         1     0.736 positive negative
         6       1         1     0.230 positive negative
         8       4         5     0.526  neutral positive
        17       5         1     0.562 positive negative
        20       3         3     0.622  neutral  neutral
        21       5         1     0.816 negative negative

O modelo pegou a reclamação da avaliação 3, o sarcasmo da avaliação 6 (com confiança baixa, de 0,23) e a avaliação em alemão. Errou na avaliação 17, a mochila que "survived a rainy week", e leu a gíria da avaliação 21 como uma estrela com confiança alta. A avaliação 20 está em turco, idioma com o qual o modelo não foi treinado; as três estrelas bateram, mas não confiaríamos nisso.

Etapa 3: agregar por produto e mês

O relatório confere os dois métodos contra as estrelas, calcula uma pontuação de sentimento líquido (proporção de positivas menos proporção de negativas) por produto e mês e grava em um arquivo as avaliações em que os métodos discordam, para uma pessoa ler.

python
import pandas as pd

df = pd.read_csv("reviews_scored.csv", parse_dates=["date"])


def stars_to_label(rating: int) -> str:
    if rating >= 4:
        return "positive"
    if rating == 3:
        return "neutral"
    return "negative"


df["truth"] = df["rating"].apply(stars_to_label)
for method in ("vader", "hf"):
    hit = (df[method] == df["truth"]).mean()
    print(f"{method}: {hit:.0%} agree with the star rating")
off_by_one = ((df["hf_stars"] - df["rating"]).abs() <= 1).mean()
print(f"model stars within one star of the rating: {off_by_one:.0%}")

# Sentimento líquido: proporção de positivas menos proporção de negativas, de -1 a +1
NET = {"positive": 1, "neutral": 0, "negative": -1}
df["net"] = df["hf"].map(NET)
df["month"] = df["date"].dt.to_period("M")

by_product = (
    df.groupby("product")
    .agg(reviews=("review_id", "count"),
         net=("net", "mean"),
         negative_share=("hf", lambda s: (s == "negative").mean()),
         avg_rating=("rating", "mean"))
    .round(2)
    .sort_values("net")
)
print(by_product.to_string())

by_month = df.pivot_table(index="month", columns="product", values="net", aggfunc="mean").round(2)
print(by_month.to_string())

# Linhas em que os dois métodos discordam vão para revisão humana
disagree = df[df["vader"] != df["hf"]]
print(f"{len(disagree)} of {len(df)} reviews need a human look")
disagree[["review_id", "rating", "vader", "hf", "text"]].to_csv("review_queue.csv", index=False)
text
vader: 58% agree with the star rating
hf: 79% agree with the star rating
model stars within one star of the rating: 92%
            reviews   net  negative_share  avg_rating
product
backpack          8 -0.25            0.50        3.12
headphones        8  0.12            0.25        3.25
kettle            8  0.12            0.38        3.12
product  backpack  headphones  kettle
month
2026-07     -0.33       -0.25    0.00
2026-08     -0.20        0.50    0.25
11 of 24 reviews need a human look

A mochila e a chaleira têm a mesma média de 3,12 estrelas, mas metade das avaliações da mochila é lida como negativa, contra 38% da chaleira, uma diferença que a média de estrelas esconde. Com oito avaliações por produto, uma única avaliação move o sentimento líquido em 0,25, então defina um número mínimo por grupo antes de colocar os dados em um gráfico. Como guardar as linhas pontuadas para a próxima execução está em Como salvar dados de scraping em CSV, JSON e SQLite.

De onde vêm as avaliações?

O código não se importa com a origem do texto, mas a fonte decide o que você pode fazer com ele:

  • Sua própria loja, o console da loja de aplicativos ou a ferramenta de suporte. É a fonte mais limpa, e traz a nota em estrelas de que você precisa para conferir o modelo.
  • Plataformas de avaliação e marketplaces. Muitos oferecem uma API oficial ou uma exportação para vendedores. Use essa opção antes de pensar em scraping.
  • Páginas públicas. Siga o robots.txt e os termos de serviço, mantenha a taxa de requisições baixa e deixe de fora os nomes dos autores e os links de perfil. Web scraping é legal? Um panorama e Como tratar dados pessoais (PII) em dados de scraping explicam as regras.

Quando um marketplace mostra avaliações ou preços diferentes por país, um Proxies residenciais com segmentação por país permite ver a página que um comprador local vê.

Casos de uso

  • Pesquisa de produtos e categorias: comparar como os compradores falam dos seus produtos e dos de um concorrente, como parte da pesquisa de mercado.
  • Monitoramento de e-commerce: acompanhar o sentimento das avaliações ao lado de dados de preço e estoque em vários marketplaces; veja proxies para e-commerce e Como monitorar preços da concorrência no e-commerce.
  • Proteção de marca: identificar uma sequência repentina de avaliações negativas que mencionam falsificações ou vendedores não autorizados; veja proteção de marca.
  • Pesquisa de investimentos: o sentimento de avaliações e redes sociais é uma das entradas dos conjuntos de dados alternativos.
  • Triagem no suporte: encaminhar primeiro para uma pessoa as avaliações de uma estrela e as de baixa confiança.

Erros comuns e armadilhas

  • Pontuar um parágrafo inteiro de uma vez com o VADER. As regras de negação e de "but" podem atravessar frases, como mostrou a avaliação 1. Pontue frase a frase e combine os resultados.
  • Usar o VADER em outros idiomas. Palavras desconhecidas valem zero, então avaliações em alemão e espanhol saem neutras. Use um modelo multilíngue, ou agrupe as avaliações por idioma e escolha um modelo para cada um.
  • Confiar sarcasmo e gíria a qualquer um dos métodos. Os dois leem "Killer design, this bag is sick!" como uma avaliação de uma estrela.
  • Ignorar o domínio. "Imprevisível" é bom para o enredo de um filme e ruim para os freios de um carro. Confira uma amostra da sua própria categoria.
  • Tratar concordância como verdade. A avaliação 21 não apareceu na fila de divergências porque os dois métodos erraram do mesmo jeito. Mantenha uma pequena amostra rotulada à mão e meça contra ela.
  • Descartar a confiança. Um rótulo com pontuação de 0,23, como o da avaliação 6, é pouco melhor que um palpite. Encaminhe as pontuações baixas para uma pessoa.
  • Esquecer o truncamento. Sem truncation=True, uma avaliação maior que o limite do modelo gera um erro e interrompe o lote.
  • Colocar grupos minúsculos em gráfico. Um sentimento líquido calculado com cinco avaliações oscila demais. Defina um tamanho mínimo de grupo.
  • Codificação de texto quebrada. Avaliações com é no lugar de é confundem os dois métodos; veja Erros de codificação no Python: acentos e UnicodeDecodeError.

Guia de decisão

NecessidadeRecomendação
Uma primeira olhada rápida em avaliações em inglêsVADER, pontuando frase a frase
Avaliações em vários idiomasUm modelo multilíngue cujo cartão inclua os seus idiomas
Uma nota em estrelas em vez de três rótulosUm modelo treinado com notas em estrelas, como o da nlptown
Sem GPU e com milhões de linhasVADER, ou um modelo pequeno com processamento em lotes e uma verificação por amostra
Uso comercialConfira a licença do modelo; descarte modelos não comerciais
Números que você vai apresentar à diretoriaRotule à mão de 200 a 500 das suas avaliações e meça a precisão antes
Texto com muito sarcasmo e gíriaUm modelo treinado com texto de redes sociais, mais revisão humana das pontuações baixas

Perguntas frequentes

Ainda vale a pena usar o VADER?

Sim, como ponto de partida para textos curtos em inglês quando você precisa de velocidade e de resultados que possa explicar palavra por palavra. Quando o contexto ou outros idiomas importam, um modelo transformer se saiu claramente melhor no nosso teste.

O que significam os limiares da pontuação compound do VADER?

A pontuação compound vai de -1 a +1. Os autores do VADER sugerem positivo a partir de 0,05, negativo de -0,05 para baixo e neutro entre esses valores. Você pode mudar os limiares, mas ajuste-os com exemplos rotulados, não no olho.

Preciso de uma GPU para o pipeline do Hugging Face?

Não. A versão do torch para CPU pontuou as nossas 24 avaliações em segundos. Para centenas de milhares de avaliações, uma GPU economiza horas; passe device=0 para usá-la.

Qual modelo funciona para avaliações em turco?

O modelo da nlptown usado aqui não foi treinado com turco. Procure no hub do Hugging Face modelos cujo cartão inclua o turco e dados de produtos ou avaliações, e teste os melhores candidatos com uma amostra rotulada em turco.

Como meço a precisão nos meus próprios dados?

Rotule você mesmo uma amostra aleatória de algumas centenas de avaliações e compare. As notas em estrelas servem como rótulos aproximados, como neste guia, mas uma avaliação de três estrelas muitas vezes é lida como negativa.

Posso aplicar análise de sentimento a avaliações coletadas por scraping?

A questão legal não está na pontuação, e sim na coleta. Prefira uma API oficial, confira os termos do site e o robots.txt, e deixe os dados pessoais de fora.

Em resumo

A análise de sentimento em Python se resume a duas escolhas. O VADER do NLTK é pequeno, rápido e fácil de explicar, mas interpreta mal sarcasmo, gíria, vocabulário de domínio e qualquer idioma que não seja o inglês. Um modelo do Hugging Face lê o contexto e lida com vários idiomas ao custo de um download grande e mais processamento; nas nossas 24 avaliações, ele bateu com as estrelas em 19, contra 14 do VADER. Seja qual for a escolha, pontue sempre do mesmo jeito (por frase ou por avaliação), guarde a confiança, encaminhe as divergências para uma pessoa e meça contra a sua própria amostra rotulada. Se as suas avaliações vêm de páginas públicas em vários países, veja os proxies da Proxynet para coletá-las em um ritmo respeitoso.