Classificação de Texto
Visão geral
A classificação de texto (text classification) é uma tarefa central em Processamento de Linguagem Natural (Natural Language Processing, NLP) na qual o objetivo é atribuir um ou mais rótulos (labels) a um trecho de texto. A unidade de texto pode ser:
- um documento (ex.: artigo de notícia → tópico)
- uma frase ou enunciado (utterance) (ex.: mensagem de chatbot → intenção)
- uma mensagem curta (ex.: email/SMS → spam vs. não spam)
- às vezes até mesmo uma decisão no nível de token (token-level decision) (embora a rotulagem no nível de token seja mais comumente tratada como Rotulagem de Sequência, e a rotulagem de entidades como Reconhecimento de Entidades Nomeadas)
A classificação de texto é amplamente usada na indústria porque converte linguagem não estruturada em sinais estruturados para roteamento, análises, personalização, moderação e tomada de decisão.
Exemplos típicos:
- Análise de sentimento: positivo / neutro / negativo
- Classificação por tópico: esportes / política / tecnologia / …
- Detecção de intenção: “reset_password”, “cancel_subscription”, …
- Detecção de spam: spam / não spam
- Moderação de toxicidade / políticas: ódio, assédio, autoagressão, etc.
- Urgência / triagem: chamados de suporte urgentes / não urgentes
Em alto nível, um sistema de classificação de texto aprende uma função:
[ f(x) \rightarrow y ]
em que (x) é o texto e (y) é um rótulo (ou conjunto de rótulos). Sistemas modernos vão de saco de palavras (bag-of-words) + modelos lineares (linear models) a modelos Transformer ajustados finamente (fine-tuned transformer models), como codificadores no estilo BERT.
Variantes do problema
Classificação binária
Dois rótulos, muitas vezes com uma classe “positiva” de interesse:
- spam vs. não spam
- fraude vs. não fraude
- tóxico vs. não tóxico
Os modelos frequentemente produzem uma probabilidade (p(y=1 \mid x)) e você escolhe um limiar de decisão (comumente 0,5, mas muitas vezes ajustado).
Classificação multiclasse
Exatamente um rótulo dentre (K) classes:
- tópico ∈ {esportes, negócios, tecnologia, …}
- identificação de idioma ∈ {en, fr, de, …}
A saída típica é uma distribuição softmax (softmax) sobre as classes.
Classificação multilabel
Zero ou mais rótulos podem se aplicar simultaneamente:
- um artigo de notícia pode ser {política, economia}
- um chamado de suporte pode ser {cobrança, urgente}
Em vez de softmax, normalmente você prevê probabilidades independentes por rótulo usando saídas sigmoides (sigmoid) e, em seguida, aplica limiares por rótulo.
Classificação hierárquica
Os rótulos são organizados em uma taxonomia:
- Produto → Eletrônicos → Celulares
- Domínio de política → Ódio → Grupo protegido
Abordagens comuns:
- Classificação plana (flat classification): prever rótulos folha diretamente (mais simples; ignora a hierarquia)
- Classificação top-down (top-down classification): prever pai → depois filho (erros podem se propagar)
- Perda/restrições hierárquicas (hierarchical loss / constraints): penalizar previsões inconsistentes (ex.: prever um filho sem seu pai)
“Classificação de tokens” vs. classificação de texto
Se você precisa de um rótulo por token (ex.: tags BIO), isso geralmente é formulado como Rotulagem de Sequência. Muitas das mesmas famílias de modelos se aplicam, mas a estrutura de saída e a avaliação diferem.
Aplicações comuns e enquadramento prático
Uma forma útil de especificar uma tarefa de classificação de texto é:
- Entrada: que texto está disponível (texto bruto, título+corpo, contexto de conversa, metadados)?
- Rótulos de saída: definições, exemplos, casos de borda, coocorrência permitida
- Granularidade: documento/frase/mensagem
- Restrições de latência: em lote vs. em tempo real
- Custo dos erros: falsos positivos vs. falsos negativos (raramente simétricos)
- Expectativas de deriva (drift): o domínio muda ao longo do tempo?
Exemplo: filtragem de spam
- Entradas: assunto + corpo + domínio do remetente
- Saída: spam/não spam
- Custos-chave: falsos positivos são altamente danosos (perda de emails)
- Deriva: spammers se adaptam rapidamente → retreinamento e monitoramento frequentes
Fundamentos clássicos: representando texto
Saco de palavras e TF-IDF
Pipelines clássicos convertem texto em um vetor esparso com base em contagens de tokens.
- Saco de palavras (BoW, bag-of-words): contagens de palavras/n-gramas
- TF-IDF (term frequency–inverse document frequency): reduz o peso de palavras frequentes e aumenta o de palavras discriminativas
Essas representações são surpreendentemente fortes para muitas tarefas de classificação, especialmente quando:
- o conjunto de dados não é enorme,
- o sinal é lexical (palavras-chave importam),
- interpretabilidade importa.
Em scikit-learn, uma linha de base comum é TF-IDF + classificador linear:
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
model = Pipeline([
("tfidf", TfidfVectorizer(ngram_range=(1, 2), min_df=2)),
("clf", LogisticRegression(max_iter=2000, class_weight="balanced"))
])
model.fit(train_texts, train_labels)
pred = model.predict(test_texts)
Notas:
- n-gramas (n-grams) (ex.: 1–2 gramas) frequentemente ajudam a capturar frases (“not good”).
class_weight="balanced"é uma forma simples de lidar com desbalanceamento em muitos modelos lineares.
Engenharia de atributos (ainda relevante)
Mesmo com Transformers, adicionar atributos estruturados pode ajudar em alguns domínios:
- comprimento da mensagem, contagens de pontuação, proporção de CAIXA ALTA
- presença de URLs, números de telefone
- atributos de reputação do remetente/domínio (para spam)
- horário do dia, localidade, metadados de plataforma
Se você combina codificadores neurais de texto com atributos estruturados, você está efetivamente fazendo classificação multimodal (multimodal).
Abordagens de modelagem
Modelos lineares e linhas de base probabilísticas
Modelos clássicos comuns:
- Bayes ingênuo (Naive Bayes) (Multinomial/Bernoulli): rápido, linha de base forte para contagens de palavras
- Regressão Logística (Logistic Regression): robusta, probabilidades mais ou menos calibradas, coeficientes interpretáveis
- SVM linear (Linear SVM): classificador forte baseado em margem, frequentemente excelente para TF-IDF
Esses modelos são treinados com variantes de Descida do Gradiente e regularização (L1/L2). Em geral, exigem menos computação e são fáceis de depurar.
Quando preferi-los:
- conjuntos de dados pequenos a médios
- implantação apenas em CPU
- necessidade de explicabilidade (atributos com maiores pesos)
- iteração rápida
Modelos neurais antes dos Transformers (CNN/RNN)
Antes de codificadores Transformer dominarem, escolhas comuns incluíam:
- CNNs para texto: capturam padrões locais de n-gramas com filtros convolucionais
- RNNs/LSTMs/GRUs: modelam sequências de palavras; podem ser eficazes, mas são mais lentas e mais difíceis de paralelizar
Ainda são usados em cenários com restrições, mas a maioria dos sistemas novos usa Transformers.
Codificadores Transformer e ajuste fino
Codificadores Transformer (ex.: BERT, RoBERTa, no estilo DeBERTa) produzem embeddings contextuais. Para classificação, normalmente você:
- tokeniza o texto (tokenização em subpalavras (subword tokenization))
- alimenta o codificador
- obtém uma representação agregada (pooled representation) (ex.: embedding do token
[CLS]ou média) - aplica uma cabeça de classificação (classification head) (camada linear)
- faz ajuste fino (fine-tuning) de ponta a ponta (de ponta a ponta (end-to-end))
Isso se baseia na Arquitetura Transformer e no treinamento via Retropropagação.
Um exemplo mínimo com Hugging Face:
from transformers import AutoTokenizer, AutoModelForSequenceClassification
from transformers import TrainingArguments, Trainer
import numpy as np
from datasets import Dataset
checkpoint = "distilbert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
def tokenize(batch):
return tokenizer(batch["text"], truncation=True, padding="max_length", max_length=256)
train_ds = Dataset.from_dict({"text": train_texts, "label": train_labels}).map(tokenize, batched=True)
test_ds = Dataset.from_dict({"text": test_texts, "label": test_labels}).map(tokenize, batched=True)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=3)
args = TrainingArguments(
output_dir="out",
learning_rate=2e-5,
per_device_train_batch_size=16,
num_train_epochs=3,
weight_decay=0.01,
evaluation_strategy="epoch"
)
trainer = Trainer(model=model, args=args, train_dataset=train_ds, eval_dataset=test_ds)
trainer.train()
Notas práticas:
- O ajuste fino é sensível à taxa de aprendizado (learning rate), ao tamanho de lote (batch size) e ao número de épocas (number of epochs).
- Sempre mantenha um conjunto de validação e use parada antecipada quando possível.
Ajuste fino eficiente em parâmetros (PEFT)
Se você não pode arcar com ajuste fino completo (computação/memória), pode adaptar modelos grandes com:
- LoRA (adaptadores de baixa ordem/rank)
- módulos adaptadores
- ajuste por prompt/prefixo
Essas técnicas podem atingir desempenho próximo ao do ajuste fino completo com menos parâmetros treináveis.
Classificação zero-shot e supervisionada de forma fraca
Às vezes, você não tem dados rotulados (ou não o suficiente). Opções:
- Classificação zero-shot (zero-shot classification) usando modelos no estilo inferência de linguagem natural (natural language inference, NLI) (“This text is about sports.”)
- criação de prompts (prompting) com modelos de linguagem grandes (large language models, LLMs) ajustados por instruções
- supervisão fraca (weak supervision): heurísticas, regras, funções de rótulo, rótulos distantes
Cuidado: esses métodos podem ser fortes para prototipagem, mas podem ser frágeis e exigem avaliação cuidadosa para uso em produção.
Considerações sobre dados e rotulagem
Qualidade dos rótulos e diretrizes
Muitas falhas vêm de rotulagem ambígua ou inconsistente. Boas práticas:
- definir cada rótulo com exemplos positivos e negativos
- especificar como lidar com casos limítrofes
- medir a concordância entre anotadores (inter-annotator agreement) quando viável
- auditar periodicamente os rótulos (especialmente quando os modelos “discordam” com confiança)
Divisões e vazamento
A divisão de dados precisa refletir a realidade de implantação.
Padrões comuns de vazamento (leakage):
- duplicatas ou quase duplicatas entre treino/teste
- mesmo usuário/cliente aparecendo em ambos os conjuntos (vazamento de estilo específico do usuário)
- vazamento temporal (treinar com dados do futuro)
Para domínios em evolução (spam, redes sociais), considere divisões baseadas no tempo (time-based splits).
Desbalanceamento de classes
O desbalanceamento é a norma (ex.: 1% spam, 0,1% violações de política).
Mitigações:
- escolher métricas além de acurácia (veja abaixo)
- usar pesos por classe ou perda focal (focal loss)
- superamostrar a classe minoritária (com cuidado) ou subamostrar a classe majoritária
- ajustar limiares de decisão com base no custo do negócio
Métricas de avaliação e como escolhê-las
Métricas da matriz de confusão
Para classificação binária:
- Precisão (Precision): dentre os positivos previstos, quantos estão corretos?
- Revocação (Recall): dentre os positivos reais, quantos encontramos?
- F1: média harmônica de precisão e revocação
Elas dependem de um limiar escolhido.
Acurácia (use com cuidado)
Acurácia pode ser enganosa sob desbalanceamento. Se 99% dos emails não são spam, um modelo que sempre prevê “não spam” tem 99% de acurácia e é inútil.
AUC-ROC e AUC-PR
- AUC-ROC (ROC-AUC) resume a qualidade do ranqueamento ao longo de limiares; pode parecer otimista demais com desbalanceamento pesado.
- AUC-PR (PR-AUC) (área sob a curva precisão–revocação) costuma ser mais informativa quando positivos são raros.
Métricas multiclasse
Normalmente você reporta:
- F1 macro (macro-F1): média de F1 entre classes (trata classes igualmente; bom sob desbalanceamento)
- F1 micro (micro-F1): agrega contribuições (dominado por classes frequentes)
- precisão/revocação/F1 por classe para ver onde o modelo falha
Métricas multilabel
Escolhas comuns:
- F1 micro/macro entre rótulos
- perda de Hamming (Hamming loss) (fração de decisões de rótulo incorretas)
- acurácia por subconjunto (subset accuracy) (correspondência exata do conjunto; muito rígida)
- AUC-PR por rótulo se as saídas forem probabilísticas
Calibração e limiares de decisão
Muitas aplicações precisam de boas probabilidades, não apenas ranqueamentos. Um modelo pode ter bom F1, mas probabilidades mal calibradas.
- Verifique diagramas de confiabilidade (reliability diagrams) / erro esperado de calibração (expected calibration error, ECE)
- Considere métodos de calibração (ex.: escalonamento de temperatura (temperature scaling)) se necessário
- Ajuste limiares por classe/rótulo com base no custo e na precisão/revocação desejadas
Escolhas típicas de modelagem (o que importa na prática)
Pré-processamento de texto
Com modelos TF-IDF:
- escolhas de tokenização (n-gramas de palavras vs. de caracteres)
- normalização para minúsculas, tratamento de pontuação
- remoção de stopwords (stopword removal) (às vezes prejudica; depende da tarefa)
Com Transformers:
- recomenda-se pré-processamento mínimo (deixe o tokenizador lidar com isso)
- lidar com comprimento máximo (truncar vs. janela deslizante (sliding window) para documentos longos)
Documentos longos
Transformers têm limites de contexto. Opções:
- truncar para a parte mais informativa (ex.: título + primeiros N tokens)
- dividir o documento em blocos e agregar previsões (pooling por média/máximo)
- usar modelos de contexto longo (no estilo Longformer/BigBird) quando apropriado
Sistemas sensíveis a custo e de alta precisão
Para moderação/spam, você pode querer:
- um limiar de alta precisão (high-precision) para “ação automática”
- uma faixa de revisão (review band) encaminhada a humanos
- um limiar de alta revocação (high-recall) para monitoramento por amostragem e investigação
Isso costuma ser melhor do que um único limiar.
Interpretabilidade
Necessidades de interpretabilidade variam por domínio (conformidade vs. analytics de produto).
Opções:
- coeficientes de modelos lineares (altamente interpretáveis com TF-IDF)
- métodos de atribuição de atributos para modelos neurais (ex.: gradientes integrados (integrated gradients))
- explicações locais (local explanations) (LIME/SHAP), com a ressalva de que explicações podem ser instáveis
Armadilhas comuns
Mudança de domínio e deriva de dados
Um modelo treinado em uma distribuição frequentemente piora em outra:
- novas gírias, novos tópicos, novas táticas de spam
- segmento de cliente ou geografia diferentes
- mudanças de UI que alteram o comportamento do usuário
Mitigações:
- monitorar desempenho ao longo do tempo e por recortes (slices)
- retreinar regularmente com rótulos recentes
- manter conjuntos de avaliação “canário” (recentes, tráfego de alto risco)
- considerar técnicas de adaptação de domínio quando as mudanças forem grandes
Correlações espúrias
Modelos podem aprender atalhos:
- “contém a palavra ‘refund’ → sentimento negativo”
- “menciona um grupo protegido → tóxico” (viés prejudicial)
Mitigações:
- avaliação direcionada em contraexemplos
- conjuntos de dados balanceados/curados
- aumento de dados
- auditorias de justiça e viés (especialmente em aplicações sensíveis)
Overfitting a artefatos de anotação
Se anotadores seguem padrões (ex.: sempre sinalizar mensagens curtas como spam), o modelo pode aprender essa heurística em vez de pistas semânticas reais.
Mitigações:
- diversificar anotadores e diretrizes
- conjuntos adversariais ou de desafio
- análise de erros e re-rotulagem
Métricas desalinhadas
Otimizar para acurácia quando você precisa de revocação, ou otimizar F1 quando você precisa de probabilidades calibradas, leva a modelos que “parecem bons”, mas falham operacionalmente.
Sempre conecte a avaliação ao processo de decisão:
- o que acontece em falso positivo vs. falso negativo?
- qual é a capacidade de revisão?
- qual é o risco aceitável?
Exemplo trabalhado: classificação de sentimento
Suponha que você queira classificar avaliações de produtos em {negativo, neutro, positivo}.
- Comece com uma linha de base (baseline): TF-IDF + regressão logística
- iteração rápida, palavras interpretáveis conduzindo previsões
- Meça: F1 macro + revocação por classe
- a classe neutra costuma ser ambígua; inspecione a matriz de confusão
- Evolua: Transformer ajustado finamente
- melhor com negação (“not bad”), sarcasmo (ainda difícil) e contexto
- Operacionalize:
- monitore deriva após lançamentos de produto
- lide com avaliações em múltiplos idiomas (modelo separado ou codificador multilíngue)
- calibre probabilidades se usadas para dashboards
Padrões de implantação
Arquiteturas comuns de implantação:
- Pontuação em lote (batch scoring): classificar documentos à noite (analytics, marcação)
- Inferência online (online inference): classificar por requisição (intenção em chat, moderação)
- Cascatas híbridas (hybrid cascades):
- modelo barato primeiro (linear/Transformer compacto)
- modelo caro apenas quando houver incerteza
- revisão humana para casos de borda
Preste atenção a:
- latência e vazão (throughput)
- tamanho do modelo e hardware (CPU vs GPU)
- restrições de privacidade (PII (personally identifiable information), inferência no dispositivo)
- monitoramento (deriva de dados, desempenho, valores atípicos)
Resumo
A classificação de texto transforma texto bruto em rótulos acionáveis e é uma das capacidades de PLN mais amplamente implantadas. Sistemas eficazes combinam:
- uma definição clara da semântica dos rótulos e dos custos
- linhas de base fortes (TF-IDF + modelos lineares) para velocidade e interpretabilidade
- ajuste fino de Transformers (ou PEFT) para acurácia de ponta
- avaliação robusta além de acurácia (F1 macro, AUC-PR, calibração)
- salvaguardas práticas contra desbalanceamento de classes, vazamento, correlações espúrias e mudança de domínio
Para tarefas que exigem rotular cada token em vez do texto inteiro, veja Rotulagem de Sequência. Para rotulagem centrada em entidades, veja Reconhecimento de Entidades Nomeadas.