Como criar um modelo de classificação por texto em Machine Learning
Este tutorial mostra como transformar texto em características e treinar um modelo de classificação em Machine Learning para categorizar mensagens ou avaliações. É útil para automatizar triagem de suporte, análise de sentimento ou classificação de conteúdos com um exemplo prático em Python e scikit-learn. Vou explicar o porquê de cada passo e dar dicas práticas para melhorar resultados reais.
Pré-requisitos
- Python 3.8+ instalado
- Pacotes: scikit-learn, pandas, numpy (pip install scikit-learn pandas numpy)
- Noções básicas de Python e pandas
Recomendo trabalhar num ambiente virtual (venv) para evitar conflitos de versões. Para conjuntos de dados reais, idealmente tens algumas centenas a milhares de exemplos para obter modelos robustos — com apenas 50-100 amostras os resultados são muito instáveis.
Passo 1: Preparar um conjunto de dados simples
Começamos com um pequeno conjunto de exemplos rotulados (por exemplo, mensagens de treino). Mantém texto e etiqueta num pandas DataFrame. Estruturar bem os dados facilita expansão posterior para CSV ou bases de dados.
import pandas as pd
data = [
("Adorei o produto, chegou rápido e funciona bem", "positivo"),
("Produto avariado, quero reembolso", "negativo"),
("Entrega atrasada, má experiência", "negativo"),
("Muito satisfeito com a qualidade", "positivo"),
("Suporte lento e pouco útil", "negativo"),
("Excelente, recomendo", "positivo")
]
df = pd.DataFrame(data, columns=["text", "label"])
print(df.head())
Este dataframe é apenas um exemplo didático. Em produção, guarda também um id, data e metadados (canal, produto) para análises posteriores.
Passo 2: Limpeza básica do texto
Normalizamos maiúsculas/minúsculas e removemos espaços supérfluos. Dependendo do caso podes remover pontuação, URLs ou telefones; no entanto, TF-IDF costuma ignorar palavras muito frequentes se configurado corretamente. Evita over-preprocessing: por vezes a remoção excessiva perde sinais importantes (ex.: "não gosto"). Aqui fazemos um pré-processamento simples e legível:
def clean_text(s):
return s.lower().strip()
df["text_clean"] = df["text"].apply(clean_text)
print(df[["text", "text_clean"]].head())
Se tiveres classes desequilibradas (ex.: 90% positivo), considera técnicas como reamostragem ou pesos de classe no classificador.
Passo 3: Dividir dados em treino e teste
Usa train_test_split para avaliar o modelo em dados novos. A estratificação é importante quando existem poucas amostras por classe. Em conjuntos de dados pequenos usa test_size=0.2-0.33; em conjuntos grandes podes reservar 10% apenas.
from sklearn.model_selection import train_test_split
X = df["text_clean"]
y = df["label"]
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.33, random_state=42, stratify=y
)
Com stratify=y garantimos que a proporção de classes em treino/teste se mantenha. Para validação mais robusta, usa Cross-Validation em vez de uma única divisão.
Passo 4: Transformar texto em vetores com TF-IDF
TF-IDF converte texto em vetores numéricos ponderando termos pela importância relativa. Aqui escolhemos ngram_range=(1,2) para captar uni- e bi-gramas (ex.: "muito bom", "não gostei") e usamos max_df/min_df para reduzir ruído.
from sklearn.feature_extraction.text import TfidfVectorizer
vect = TfidfVectorizer(ngram_range=(1,2), max_df=0.9, min_df=1)
X_train_tfidf = vect.fit_transform(X_train)
X_test_tfidf = vect.transform(X_test)
print("Número de features:", X_train_tfidf.shape[1])
Numa amostra pequena terás poucas features (10-100). Em conjuntos de dados médios (1000+ textos) normalmente tens milhares de features; nesse caso avalia redução dimensional (TruncatedSVD) ou limites maiores para min_df.
Passo 5: Treinar um classificador simples (Logistic Regression)
Logistic Regression funciona bem para texto e é rápido. O parâmetro max_iter=1000 evita não-convergência em casos com muitas features.
from sklearn.linear_model import LogisticRegression
model = LogisticRegression(max_iter=1000)
model.fit(X_train_tfidf, y_train)
y_pred = model.predict(X_test_tfidf)
Alternativas a experimentar: SVM (bom para dados esparsos e de alta dimensionalidade) ou RandomForest (mais lento, pode precisar de vetores densos).
Passo 6: Avaliar o modelo
Calcula métricas simples: precisão, recall e matriz de confusão para perceber erros comuns (falsos positivos/negativos). Em problemas desequilibrados, o f1-score é mais informativo do que a acurácia.
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
acc = accuracy_score(y_test, y_pred)
print("Acurácia:", acc)
print(classification_report(y_test, y_pred))
print("Matriz de confusão:\n", confusion_matrix(y_test, y_pred))
Numa toy dataset a acurácia pode variar muito — valores entre 50% e 90% são comuns dependendo da divisão. Em conjuntos de dados reais, almeja-se >70-80% para tarefas simples de sentimento; para tarefas mais complexas poderás precisar de modelos mais avançados ou mais dados.
Passo 7: Interpretar as features mais importantes
Verifica quais termos mais contribuem para cada classe usando os coeficientes do modelo. Isto ajuda a entender erros e a melhorar o pré-processamento (por exemplo, lidar com negações).
import numpy as np
feature_names = vect.get_feature_names_out()
coefs = model.coef_[0]
top_pos = np.argsort(coefs)[-10:][[::-1]][0]
top_neg = np.argsort(coefs)[:10]
print("Top termos positivos:")
for i in top_pos:
print(feature_names[i], round(coefs[i], 3))
print("Top termos negativos:")
for i in top_neg:
print(feature_names[i], round(coefs[i], 3))
Se encontrares termos ambíguos, considera ajustar ngram_range ou normalizar expressões (ex.: "não gostei" mantendo a negação).
Verificar o resultado
Confirma que tens uma acurácia coerente e inspeciona a matriz de confusão. Testa o modelo com frases novas para ver se as predições fazem sentido:
samples = [
"Quero devolução, chegou danificado",
"Produto excelente, muito bom",
"A entrega demorou mas o produto é bom"
]
samples_tfidf = vect.transform([s.lower().strip() for s in samples])
print(model.predict(samples_tfidf))
Faz também testes de esforço com 50-100 frases variadas para avaliar estabilidade. Se o modelo falhar sistematicamente em frases com negações, adiciona regras de pré-processamento ou features específicas.
Conclusão
Agora tens um pipeline completo: limpeza básica, TF-IDF, treino e avaliação com Logistic Regression para classificação de texto. Próximos passos práticos: aumentar o conjunto de dados para centenas de exemplos, experimentar modelos como RandomForest ou SVM, e adicionar limpeza avançada (remoção de stopwords, stemming, lematização). Usa Cross-Validation e GridSearchCV para escolher hiperparâmetros e reduzir overfitting. Observa quais termos estão a causar mais erros e itera no pré-processamento até obteres a robustez desejada.