(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Como criar um modelo de classificação por texto em Machine Learning

João Barros 05 de September de 2026 6 min de leitura

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.