Skip to content

Repository files navigation

Classificador de Categorias de Notícias

Classifica a categoria de uma notícia brasileira a partir do título (e, opcionalmente, do texto), servido por uma API.

Os dois modelos ficam no Hugging Face Hub e são baixados automaticamente — não é preciso treinar nada para rodar a API.


Como rodar

Com Docker (recomendado — sem pré-requisito)

docker compose up -d     # sobe a API (build na 1a vez: ~5 min, baixa os modelos)
docker compose down      # desliga

Acesse http://127.0.0.1:8000/docs.

Local (Python 3.12)

python -m venv .venv
.venv\Scripts\activate            # Windows  (Linux/Mac: source .venv/bin/activate)
pip install -r requirements.txt

uvicorn src.api:app               # http://127.0.0.1:8000/docs

Os modelos são baixados do Hugging Face na primeira execução.

  • Para usar o bert localmente: pip install torch transformers (o svc roda sem).
  • Para reproduzir o treino do svc do zero: python src/train.py — ele gera models/model.joblib, e a API passa a usar essa cópia local (que tem prioridade sobre o Hub).

Como usar a API

  • GET /health — status do serviço.
  • POST /predict — classifica uma notícia.
  • Documentação interativa (Swagger): http://127.0.0.1:8000/docs

Entrada: title (obrigatório), text (opcional), modelo (svc (default) ou bert), explicar (opcional, só svc).

# svc (rápido) + explicação
curl -X POST http://127.0.0.1:8000/predict \
  -H "Content-Type: application/json" \
  -d '{"title": "Palmeiras vence o clássico e assume a liderança", "explicar": true}'

# BERTimbau (mais preciso, mais lento)
curl -X POST http://127.0.0.1:8000/predict \
  -H "Content-Type: application/json" \
  -d '{"title": "Irã fecha o Estreito de Ormuz", "text": "...", "modelo": "bert"}'

Saída:

{
  "categoria": "Esporte",
  "confianca": 0.32,
  "top3": [
    {"categoria": "Esporte", "confianca": 0.32},
    {"categoria": "Cultura e Entretenimento", "confianca": 0.09},
    {"categoria": "Opinião", "confianca": 0.09}
  ],
  "palavras_influentes": [
    {"palavra": "vence", "peso": 0.74},
    {"palavra": "palmeiras", "peso": 0.31}
  ]
}

explicar: true retorna as palavras que mais pesaram na decisão. Como o modelo é linear, a contribuição é exata (tfidf × coeficiente), sem LIME/SHAP.


Estrutura

Text-classification/
├── data/                    # dataset (não versionado; baixado via kagglehub)
├── references/
│   └── category_map.json    # mapa 48 categorias → 12 macrocategorias
├── notebooks/
│   ├── 01_eda.ipynb                              # análise exploratória
│   ├── 02_modeling_baseline.ipynb                # TF-IDF, título
│   ├── 02_modeling_baseline_title_text.ipynb     # TF-IDF, título+texto (produção)
│   └── 03_modeling_bert_kaggle.ipynb             # BERTimbau (benchmark)
├── src/
│   ├── preprocessing.py     # limpeza + montar_entrada (treino ↔ API)
│   ├── train.py             # treina e salva models/model.joblib
│   └── api.py               # FastAPI
├── Dockerfile · docker-compose.yml
└── requirements.txt

Metodologia (resumo)

1. EDA. As 48 categorias originais são muito desbalanceadas (a maior tem 22 mil notícias, a menor tem 1) e várias são editorias, não temas (ex.: colunas, opiniao). Isso inviabiliza usá-las diretamente como alvo.

2. Taxonomia. Consolidamos as 48 categorias em 12 macrocategorias temáticas (references/category_map.json) — decisão derivada da EDA, não arbitrária: o alvo continua sendo a categoria da notícia, apenas normalizada numa taxonomia coerente. O desbalanceamento cai de ~22.000× para ~28×.

3. Entrada. título (obrigatório) + texto (opcional), concatenados. A limpeza (URLs, créditos de tradução, auto-referências da marca Folha) é compartilhada entre treino e API (src/preprocessing.py), evitando train/serve skew.

4. Modelos. Mesmo split e métrica (F1-macro):

Modelo F1-macro Tamanho Latência/req (CPU)
TF-IDF + LinearSVC (produção) 0,80 132 MB ~0,7 ms
BERTimbau (benchmark) 0,86 ~440 MB ~100–300 ms

5. Decisão de produção. O SVC (TF-IDF + LinearSVC) é o padrão da API (modelo: svc, ~0,7 ms/req): para o cenário de "API simples", ele entrega quase a mesma qualidade a uma fração do custo. O BERTimbau fica disponível sob demanda (modelo: bert) para quem prioriza acurácia — ambos no mesmo contêiner. Assim a API mostra o critério de engenharia (qualidade → latência → tamanho) na prática: escolha certa por padrão, sem abrir mão de servir o modelo mais forte quando faz sentido.

Avaliação. Além do F1-macro, os notebooks trazem matriz de confusão, relatório por classe e análise qualitativa dos erros (as maiores confusões — Opinião ↔ Política — vêm justamente das editorias, confirmando o achado da EDA).

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages