04_modeling__baseline_tfidf_logreg



NLP Triagem Inteligente Financeira - Data Science Project

Modeling Baseline | TF-IDF + Logistic Regression

Treinar e avaliar um baseline supervisionado para classificação textual utilizando TF-IDF
e Regressão Logística, estabelecendo uma referência técnica sólida
para comparação posterior com modelos mais avançados.


Roberto SSoares - LfLngLrnng

in/roberto-dos-santos-soares
Portifólio: roberto-ssoares

" [+] Faturamento [-] Custo [+] Qualidade de vida "
"Mestre Bruno Jardim"

📌 Objetivo:

  • Ações realizadas neste notebook
    • Leitura das bases gold de treino, validação e teste
    • Definição da variável textual e da variável-alvo
    • Construção de pipelines baseline com TF-IDF + Logistic Regression
    • Comparação entre configurações candidatas
    • Seleção do melhor modelo com base na validação
    • Reajuste do modelo final
    • Avaliação no conjunto de teste
    • Persistência do pipeline, métricas e previsões
  • Justificativa técnica
    • Em projetos de NLP aplicado, o baseline é essencial para estabelecer uma referência confiável antes do uso de modelos mais complexos.
    • Um baseline forte, bem avaliado e bem documentado permite medir ganho real quando avançarmos para transformers.
  • Resultados esperados
    • Baseline treinado e validado
    • Melhor configuração selecionada
    • Métricas registradas
    • Erros principais analisados
    • Artefatos persistidos para reuso

📌 Leitura executiva da etapa

  • Este notebook representa o primeiro modelo supervisionado operacional do projeto.
  • A proposta aqui não é apenas “treinar um algoritmo”, mas:
    • construir uma referência quantitativa confiável
    • comparar configurações de forma objetiva
    • documentar o comportamento do baseline
    • *preparar terreno para o **Notebook 05 — Transformer Text Classifier***
  • Nota metodológica
    • O modelo final será reajustado com treino + validação e avaliado apenas no teste, preservando o holdout final e evitando vazamento de dados.

✔️ Seção 1 — Setup do ambiente e leitura das bases

  • Objetivo da seção
    • Preparar o ambiente analítico, definir paths do projeto e carregar as bases gold produzidas no Notebook 03.
  • Ações realizadas
    • Importação das bibliotecas necessárias
    • Configuração de warnings e display
    • Definição de diretórios
    • Leitura das bases gold e do mapping de labels
  • Justificativa técnica
    • Um setup explícito melhora reprodutibilidade, legibilidade e rastreabilidade do pipeline.
  • Resultados esperados
    • Ambiente pronto para modelagem
    • Bases carregadas corretamente
    • Estrutura do notebook organizada para execução contínua

import warnings
from pathlib import Path
import json
import joblib

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from sklearn.exceptions import ConvergenceWarning
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import (
    accuracy_score,
    f1_score,
    precision_score,
    recall_score,
    classification_report,
    confusion_matrix,
    ConfusionMatrixDisplay,
)

warnings.filterwarnings("ignore", category=ConvergenceWarning)

📌 TfidfVectorizer

  • Como computadores não "leem" palavras como nós, eles precisam de uma representação numérica para processar dados em algoritmos de Machine Learning.
    • O TfidfVectorizer faz isso calculando a importância de cada palavra através de uma métrica chamada TF-IDF.
  • Como funciona o TF-IDF?
    • A sigla significa Term Frequency – Inverse Document Frequency e combina dois conceitos:
    • TF (Term Frequency):
      • Conta quantas vezes uma palavra aparece em um documento específico.
      • Quanto mais ela aparece, maior o peso.
    • IDF (Inverse Document Frequency):
      • Diminui o peso de palavras que aparecem em quase todos os documentos (como "o", "de", "que"), pois elas não ajudam a diferenciar um texto do outro.
      • Palavras mais raras e específicas ganham um peso maior.

pd.set_option("display.max_columns", 200)
pd.set_option("display.max_rows", 200)
pd.set_option("display.max_colwidth", 200)
pd.set_option('display.width', None)                            # Expandir a largura da exibição (evitar quebra de linha horizontal)
PROJECT_ROOT = Path.cwd().resolve().parents[0]
DATA_DIR = PROJECT_ROOT / "data"

GOLD_DIR = DATA_DIR / "03-gold"
MODELS_DIR = PROJECT_ROOT / "models" / "baseline"
REPORTS_DIR = PROJECT_ROOT / "artifacts" / "reports"
FIGURES_DIR = PROJECT_ROOT / "artifacts" / "figures"

MODELS_DIR.mkdir(parents=True, exist_ok=True)
REPORTS_DIR.mkdir(parents=True, exist_ok=True)
FIGURES_DIR.mkdir(parents=True, exist_ok=True)

print("PROJECT_ROOT:", PROJECT_ROOT)
print("GOLD_DIR    :", GOLD_DIR)
print("MODELS_DIR  :", MODELS_DIR)
print("REPORTS_DIR :", REPORTS_DIR)
print("FIGURES_DIR :", FIGURES_DIR)
PROJECT_ROOT: D:\_DS-Projects\nlp-triagem-inteligente-financeira
GOLD_DIR    : D:\_DS-Projects\nlp-triagem-inteligente-financeira\data\03-gold
MODELS_DIR  : D:\_DS-Projects\nlp-triagem-inteligente-financeira\models\baseline
REPORTS_DIR : D:\_DS-Projects\nlp-triagem-inteligente-financeira\artifacts\reports
FIGURES_DIR : D:\_DS-Projects\nlp-triagem-inteligente-financeira\artifacts\figures

📌 Observe:

  • As bases utilizadas aqui foram geradas no Notebook 03 — Data Preparation, o que significa que:
    • os textos já estão preparados para baseline
    • os labels já estão padronizados
    • o split de treino, validação e teste já foi definido

train_path = GOLD_DIR / "faq_bacen_gold_train.csv"
valid_path = GOLD_DIR / "faq_bacen_gold_valid.csv"
test_path = GOLD_DIR / "faq_bacen_gold_test.csv"
label_mapping_path = GOLD_DIR / "label_mapping.csv"

train_gold = pd.read_csv(train_path)
valid_gold = pd.read_csv(valid_path)
test_gold = pd.read_csv(test_path)
label_mapping_df = pd.read_csv(label_mapping_path).sort_values("label_id")

print("train_gold:", train_gold.shape)
print("valid_gold:", valid_gold.shape)
print("test_gold :", test_gold.shape)
print("label_mapping_df:", label_mapping_df.shape)
train_gold: (1044, 8)
valid_gold: (261, 8)
test_gold : (373, 8)
label_mapping_df: (242, 2)
train_gold.head()
question_raw question_clean_light question_clean category_final label_id answer split model_split
0 O que é unidade de recebíveis? o que é unidade de recebíveis? o que e unidade de recebiveis Operações com Recebíveis Conceitos importantes 154 É ativo financeiro composto por recebíveis de arranjo de pagamento, inclusive os recebíveis oriundos de operações de antecipação pré-contratadas, caracterizados pelo(a) mesmo(a): a) número de insc... train train
1 O empregado pode abrir uma conta-salário por sua livre iniciativa? o empregado pode abrir uma conta-salário por sua livre iniciativa? o empregado pode abrir uma conta salario por sua livre iniciativa Conta-Salário e Portabilidade Salarial 70 Não. A conta-salário não é aberta por iniciativa do empregado. É necessário que o empregador contrate um banco para prestar o serviço de pagamento dos salários de seus empregados. O empregador é o... train train
2 O que é endosso? o que é endosso? o que e endosso Cheques Endosso 58 O endosso é a transmissão de um cheque a outra pessoa que não o seu beneficiário original, identificado ou não. Por meio do endosso, o beneficiário do cheque transmite todos os seus direitos sobre... train train
3 O que é o Programa de Garantia da Atividade Agropecuária (Proagro)? o que é o programa de garantia da atividade agropecuária (proagro)? o que e o programa de garantia da atividade agropecuaria proagro Programa de Garantia da Atividade Agropecuária (Proagro) Informações Gerais 198 É um programa do governo federal, administrado pelo Banco Central (BC), conforme normas, critérios e condições definidas pelo Conselho Monetário Nacional (CMN), que:  permite aos produtores rurais... train train
4 Quais instituições participam do Open Banking? quais instituições participam do open banking? quais instituicoes participam do open banking Open Banking Informações gerais 151 Participam do Open Banking somente as instituições financeiras e demais instituições autorizadas a funcionar pelo Banco Central. Entre esse universo de instituições, no entanto, a regulamentação p... train train
label_ids = label_mapping_df["label_id"].tolist()
label_names = label_mapping_df["category_final"].tolist()

id_to_label = dict(zip(label_mapping_df["label_id"], label_mapping_df["category_final"]))
label_to_id = dict(zip(label_mapping_df["category_final"], label_mapping_df["label_id"]))

print("Número de labels:", len(label_ids))
print("Primeiras labels:", label_names[:10])
Número de labels: 242
Primeiras labels: ['Acordo Administrativo em Processo de Supervisão (APS)', 'Alerta contra golpes envolvendo o nome do Banco Central e de instituições financeiras', 'Aplicações financeiras', 'Arranjos de Pagamentos Compras e relações de consumo', 'Arranjos de Pagamentos Conceitos importantes', 'Arranjos de Pagamentos Informações Gerais', 'Arranjos de Pagamentos Interoperabilidade, liquidação centralizada e compulsório', 'Arranjos de Pagamentos Supervisão dos arranjos pelo BC', 'Atendimento bancário (fila, feriados e outros)', 'Bacen Jud e SISBAJUD Informações gerais']

✔️ Seção 2 — Definição das variáveis de modelagem

  • Objetivo da seção
    • Definir explicitamente a coluna textual utilizada pelo baseline e a variável-alvo numérica utilizada na classificação.
  • Ações realizadas
    • Definição da coluna de texto para treino
    • Definição da coluna target
    • Criação dos vetores de treino, validação e teste
  • Justificativa técnica
    • O baseline clássico com TF-IDF será treinado sobre a coluna question_clean, preservando question_raw para análises qualitativas e futura comparação com transformer.
  • Resultados esperados
    • Conjuntos de entrada e saída claramente definidos
    • Base pronta para o treino dos modelos candidatos

TEXT_COL = "question_clean"
TARGET_COL = "label_id"

X_train = train_gold[TEXT_COL].fillna("")
y_train = train_gold[TARGET_COL]

X_valid = valid_gold[TEXT_COL].fillna("")
y_valid = valid_gold[TARGET_COL]

X_test = test_gold[TEXT_COL].fillna("")
y_test = test_gold[TARGET_COL]

print("X_train:", X_train.shape)
print("y_train:", y_train.shape)
print("X_valid:", X_valid.shape)
print("y_valid:", y_valid.shape)
print("X_test :", X_test.shape)
print("y_test :", y_test.shape)
X_train: (1044,)
y_train: (1044,)
X_valid: (261,)
y_valid: (261,)
X_test : (373,)
y_test : (373,)
train_gold[[TEXT_COL, "category_final", TARGET_COL]].sample(5, random_state=42)
question_clean category_final label_id
971 e necessario emitir boleto de pagamento para realizacao da portabilidade Portabilidade de Crédito Procedimentos 176
280 onde posso consultar os escritorios de representacao de instituicoes financeiras estrangeiras Processos de Autorização do Banco Central Informações Gerais 189
536 posso obter um emprestimo em uma cooperativa de credito SEM-CATEGORIA 217
824 com que frequencia as instituicoes deverao enviar as informacoes de valores a receber Valores a Receber 241
644 quero abrir uma conta no exterior como faco Contas de brasileiros no exterior e de estrangeiros no Brasil Contas de brasileiros no exterior 71

📌 Observe:

  • A escolha de question_clean como entrada do baseline segue a lógica do projeto:
    • baseline clássico → texto limpo e padronizado
    • modelo transformer → texto mais próximo do original, com menor agressividade na limpeza

✔️ Seção 3 — Estratégia do baseline e configuração dos candidatos

  • Objetivo da seção
    • Definir os pipelines candidatos do baseline que serão comparados no conjunto de validação.
  • Ações realizadas
    • Definição de duas configurações candidatas
    • Variação do espaço de n-gramas
    • Manutenção da Regressão Logística como classificador
  • Justificativa técnica
    • A comparação entre unigramas e unigramas+bigrams permite testar se o ganho de contexto local melhora a separação entre categorias sem aumentar complexidade de forma desnecessária.
  • Resultados esperados
    • Conjunto de modelos candidatos pronto para avaliação
    • Estrutura clara de comparação entre configurações

candidate_configs = [
    {
        "name": "tfidf_word_unigram_logreg",
        "tfidf_params": {
            "analyzer": "word",
            "ngram_range": (1, 1),
            "min_df": 2,
            "max_df": 0.95,
            "sublinear_tf": True,
        },
        "logreg_params": {
            "C": 2.0,
            "max_iter": 3000,
            "solver": "saga",
            "class_weight": "balanced",
            "random_state": 42,
        },
    },
    {
        "name": "tfidf_word_unigram_bigram_logreg",
        "tfidf_params": {
            "analyzer": "word",
            "ngram_range": (1, 2),
            "min_df": 2,
            "max_df": 0.95,
            "sublinear_tf": True,
        },
        "logreg_params": {
            "C": 2.0,
            "max_iter": 3000,
            "solver": "saga",
            "class_weight": "balanced",
            "random_state": 42,
        },
    },
]

candidate_configs
[{'name': 'tfidf_word_unigram_logreg',
  'tfidf_params': {'analyzer': 'word',
   'ngram_range': (1, 1),
   'min_df': 2,
   'max_df': 0.95,
   'sublinear_tf': True},
  'logreg_params': {'C': 2.0,
   'max_iter': 3000,
   'solver': 'saga',
   'class_weight': 'balanced',
   'random_state': 42}},
 {'name': 'tfidf_word_unigram_bigram_logreg',
  'tfidf_params': {'analyzer': 'word',
   'ngram_range': (1, 2),
   'min_df': 2,
   'max_df': 0.95,
   'sublinear_tf': True},
  'logreg_params': {'C': 2.0,
   'max_iter': 3000,
   'solver': 'saga',
   'class_weight': 'balanced',
   'random_state': 42}}]

⚙️ Funções auxiliares do baseline

  • Objetivo desta célula
    • Centralizar funções reutilizáveis do notebook para:
      • construir o pipeline
      • calcular métricas
      • gerar relatórios por classe
  • Justificativa técnica
    • Funções auxiliares tornam o notebook mais organizado, reduzem repetição e facilitam eventual migração desse código para os módulos em src/.

def build_baseline_pipeline(tfidf_params: dict, logreg_params: dict) -> Pipeline:
    return Pipeline(
        steps=[
            ("tfidf", TfidfVectorizer(**tfidf_params)),
            ("clf", LogisticRegression(**logreg_params)),
        ]
    )

# ---------------------------------------------------------------------------------------------------

def compute_metrics(y_true, y_pred) -> dict:
    return {
        "accuracy": accuracy_score(y_true, y_pred),
        "macro_f1": f1_score(y_true, y_pred, average="macro", zero_division=0),
        "weighted_f1": f1_score(y_true, y_pred, average="weighted", zero_division=0),
        "macro_precision": precision_score(y_true, y_pred, average="macro", zero_division=0),
        "macro_recall": recall_score(y_true, y_pred, average="macro", zero_division=0),
    }

# ---------------------------------------------------------------------------------------------------

def build_report_df(y_true, y_pred, labels, target_names) -> pd.DataFrame:
    report = classification_report(
        y_true,
        y_pred,
        labels=labels,
        target_names=target_names,
        output_dict=True,
        zero_division=0,
    )
    return pd.DataFrame(report).T

# ---------------------------------------------------------------------------------------------------

✔️ Seção 4 — Treino e comparação das configurações candidatas

  • Objetivo da seção
    • Treinar os pipelines candidatos e comparar seu desempenho no conjunto de validação.
  • Ações realizadas
    • Treino de cada configuração candidata
    • Geração de previsões na validação
    • Cálculo de métricas de comparação
    • Organização dos resultados em DataFrame comparativo
  • Justificativa técnica
    • Antes de consolidar o baseline final, precisamos selecionar a melhor configuração com base em um critério técnico consistente.
  • Resultados esperados
    • Tabela comparativa entre os candidatos
    • Melhor configuração identificada

model_registry = {}
valid_results = []

for config in candidate_configs:
    name = config["name"]
    print(f"Treinando: {name}")

    model = build_baseline_pipeline(
        tfidf_params=config["tfidf_params"],
        logreg_params=config["logreg_params"],
    )

    model.fit(X_train, y_train)
    valid_pred = model.predict(X_valid)
    metrics = compute_metrics(y_valid, valid_pred)

    valid_results.append(
        {
            "model_name": name,
            **metrics,
        }
    )

    model_registry[name] = {
        "config": config,
        "model": model,
        "valid_pred": valid_pred,
        "valid_metrics": metrics,
    }

valid_results_df = pd.DataFrame(valid_results).sort_values(
    by=["macro_f1", "weighted_f1", "accuracy"],
    ascending=False
).reset_index(drop=True)

valid_results_df
Treinando: tfidf_word_unigram_logreg
Treinando: tfidf_word_unigram_bigram_logreg
model_name accuracy macro_f1 weighted_f1 macro_precision macro_recall
0 tfidf_word_unigram_logreg 0.310345 0.224697 0.289012 0.235980 0.255121
1 tfidf_word_unigram_bigram_logreg 0.256705 0.186703 0.250611 0.199029 0.207195
valid_results_df.style.format(
    {
        "accuracy": "{:.4f}",
        "macro_f1": "{:.4f}",
        "weighted_f1": "{:.4f}",
        "macro_precision": "{:.4f}",
        "macro_recall": "{:.4f}",
    }
)
  model_name accuracy macro_f1 weighted_f1 macro_precision macro_recall
0 tfidf_word_unigram_logreg 0.3103 0.2247 0.2890 0.2360 0.2551
1 tfidf_word_unigram_bigram_logreg 0.2567 0.1867 0.2506 0.1990 0.2072
plt.figure(figsize=(8, 6))
plt.bar(valid_results_df["model_name"], valid_results_df["macro_f1"])
plt.title("Comparação de configurações — Macro F1 na validação")
plt.ylabel("Macro F1")
plt.xlabel("Modelo")
#plt.xticks(rotation=20, ha="right")
plt.tight_layout()
plt.show()
Graph

📌 Observe:

  • O critério principal de escolha será Macro F1, pois ele é mais apropriado para cenários multiclasses com possível desbalanceamento entre categorias.

✔️ Seção 5 — Seleção do melhor baseline e avaliação na validação

  • Objetivo da seção
    • Selecionar o melhor baseline com base no conjunto de validação e analisar seu desempenho por classe.
  • Ações realizadas
    • Escolha do melhor pipeline
    • Geração de classification report
    • Ordenação das classes por desempenho
  • Justificativa técnica
    • A análise agregada por métricas globais é necessária, mas insuficiente.
    • Em problemas multiclasses, também precisamos observar o comportamento classe a classe.
  • Resultados esperados
    • Melhor baseline identificado
    • Desempenho da validação documentado por classe

best_model_name = valid_results_df.iloc[0]["model_name"]
best_entry = model_registry[best_model_name]

best_model_name, best_entry["valid_metrics"]
('tfidf_word_unigram_logreg',
 {'accuracy': 0.3103448275862069,
  'macro_f1': 0.2246974079704937,
  'weighted_f1': 0.2890115669020334,
  'macro_precision': 0.2359803139132748,
  'macro_recall': 0.25512104283054005})
valid_pred_best = best_entry["valid_pred"]

valid_report_df = build_report_df(
    y_true=y_valid,
    y_pred=valid_pred_best,
    labels=label_ids,
    target_names=label_names,
)

valid_report_df.head(15)
precision recall f1-score support
Acordo Administrativo em Processo de Supervisão (APS) 0.666667 0.666667 0.666667 3.0
Alerta contra golpes envolvendo o nome do Banco Central e de instituições financeiras 0.000000 0.000000 0.000000 0.0
Aplicações financeiras 0.000000 0.000000 0.000000 2.0
Arranjos de Pagamentos Compras e relações de consumo 0.000000 0.000000 0.000000 0.0
Arranjos de Pagamentos Conceitos importantes 0.000000 0.000000 0.000000 0.0
Arranjos de Pagamentos Informações Gerais 0.000000 0.000000 0.000000 0.0
Arranjos de Pagamentos Interoperabilidade, liquidação centralizada e compulsório 0.000000 0.000000 0.000000 0.0
Arranjos de Pagamentos Supervisão dos arranjos pelo BC 0.500000 1.000000 0.666667 1.0
Atendimento bancário (fila, feriados e outros) 0.000000 0.000000 0.000000 1.0
Bacen Jud e SISBAJUD Informações gerais 0.000000 0.000000 0.000000 0.0
Bacen Jud e SISBAJUD Ordem judicial de bloqueio/desbloqueio de bens e requisição de informações 0.000000 0.000000 0.000000 0.0
Bacen Jud e SISBAJUD SISBAJUD 0.000000 0.000000 0.000000 0.0
Banco Central do Brasil 0.416667 1.000000 0.588235 5.0
CBE - Capitais Brasileiros no Exterior Acesso ao sistema de declaração 0.000000 0.000000 0.000000 0.0
CBE - Capitais Brasileiros no Exterior Declarações de anos anteriores e multas 0.000000 0.000000 0.000000 0.0
valid_class_report = valid_report_df.loc[label_names].copy()
valid_class_report = valid_class_report.sort_values(by="f1-score", ascending=False)

valid_class_report.head(15)
precision recall f1-score support
Cadastro Positivo Solicitação de cancelamento ou suspensão do cadastro positivo 1.000000 1.0 1.000000 2.0
Cadastro Positivo Nota do cadastro positivo 1.000000 1.0 1.000000 1.0
Cadastro de Clientes do Sistema Financeiro Nacional (CCS) Informações gerais 1.000000 1.0 1.000000 1.0
Contas de brasileiros no exterior e de estrangeiros no Brasil Contas no Brasil de residentes no exterior 1.000000 1.0 1.000000 1.0
Cheques Endosso 1.000000 1.0 1.000000 1.0
Correspondentes no País (lotéricas, banco postal e outros) 1.000000 1.0 1.000000 1.0
Consórcios Obrigações financeiras dos consorciados 1.000000 1.0 1.000000 2.0
Cheque especial Uso do limite de Cheque Especial 1.000000 1.0 1.000000 1.0
Solicitação de Relatórios Sigilosos referentes a pessoa falecida ou desaparecida 1.000000 1.0 1.000000 1.0
Microcrédito Microcrédito 1.000000 1.0 1.000000 1.0
Sistema de Pagamentos em Moeda Local (SML) 1.000000 1.0 1.000000 2.0
Regimes de Resolução - Definições Intervenção 1.000000 1.0 1.000000 1.0
Protocolo Digital Informações Gerais 1.000000 1.0 1.000000 1.0
Relatório de Câmbio e Transferências Internacionais 1.000000 1.0 1.000000 1.0
Conta-Salário e Portabilidade Salarial 0.857143 1.0 0.923077 6.0

✔️ Seção 6 — Visualizações focadas da validação

  • Objetivo da seção
    • Gerar visualizações legíveis e úteis para interpretação do desempenho do baseline na validação.
  • Ações realizadas
    • Foco nas classes mais frequentes
    • Uso de matriz absoluta
    • Uso de matriz normalizada
  • Justificativa técnica
    • Com muitas classes, uma matriz de confusão completa perde valor interpretativo. Recortes analíticos tornam a leitura mais útil e mais apresentável para portfólio.
  • Resultados esperados
    • Visualização das classes mais frequentes
    • Melhor leitura relativa dos erros por meio da normalização

TOP_N = 15

top_valid_labels = (
    valid_gold["category_final"]
    .value_counts()
    .head(TOP_N)
    .index
    .tolist()
)

top_valid_label_ids = [label_to_id[label] for label in top_valid_labels]

valid_mask_top = valid_gold["label_id"].isin(top_valid_label_ids)

y_valid_top = y_valid[valid_mask_top]
valid_pred_top = pd.Series(valid_pred_best, index=valid_gold.index)[valid_mask_top]

cm_valid_top = confusion_matrix(
    y_valid_top,
    valid_pred_top,
    labels=top_valid_label_ids
)

fig, ax = plt.subplots(figsize=(14, 14))
disp = ConfusionMatrixDisplay(
    confusion_matrix=cm_valid_top,
    display_labels=top_valid_labels
)
disp.plot(ax=ax, xticks_rotation=-90, colorbar=False)
plt.title(f"Matriz de confusão — Validação | Top {TOP_N} classes mais frequentes")
plt.tight_layout()
plt.show()
Graph
cm_valid_top_norm = confusion_matrix(
    y_valid_top,
    valid_pred_top,
    labels=top_valid_label_ids,
    normalize="true"
)

fig, ax = plt.subplots(figsize=(15, 14))
disp = ConfusionMatrixDisplay(
    confusion_matrix=cm_valid_top_norm,
    display_labels=top_valid_labels
)
disp.plot(ax=ax, xticks_rotation=-90, colorbar=True)
plt.title(f"Matriz de confusão normalizada — Validação | Top {TOP_N} classes")
plt.tight_layout()
plt.show()
Graph

✔️ Seção 7 — Análise dos erros na validação

  • Objetivo da seção
    • Investigar os erros mais relevantes do baseline no conjunto de validação.
  • Ações realizadas
    • Identificação das previsões incorretas
    • Mapeamento dos pares de confusão mais frequentes
    • Análise das classes com pior recall
  • Justificativa técnica
    • Entender os erros do modelo é tão importante quanto medir acertos.
    • Em problemas multiclasses, isso ajuda a identificar sobreposição semântica entre categorias e limites do baseline.
  • Resultados esperados
    • Principais pares de confusão identificados
    • Classes mais difíceis evidenciadas
    • Base para comparação futura com transformer

valid_errors = valid_gold.copy()
valid_errors["y_true"] = y_valid.values
valid_errors["y_pred"] = valid_pred_best
valid_errors["true_label"] = valid_errors["y_true"].map(id_to_label)
valid_errors["pred_label"] = valid_errors["y_pred"].map(id_to_label)
valid_errors["is_error"] = valid_errors["y_true"] != valid_errors["y_pred"]

valid_errors = valid_errors[valid_errors["is_error"]].copy()

print("Quantidade de erros na validação:", valid_errors.shape[0])
valid_errors[["question_raw", "true_label", "pred_label"]].head(15)
Quantidade de erros na validação: 180
question_raw true_label pred_label
0 Segundo a natureza das garantias, como devem ser utilizados os títulos de crédito rural? Crédito Rural Assistência Técnica e Garantias Crédito Rural Liberação dos recursos financeiros e pagamento para operações com recursos controlados
1 O que o investidor deve fazer? Liquidação Extrajudicial - Corretoras de Títulos e Valores Mobiliários Processos de Autorização do Banco Central Processo de autorização para constituição e funcionamento – Administradoras de Consórcio
2 O que é o Bacen Jud? SEM-CATEGORIA Cheques Emissão
4 Instituições de pagamento podem realizar atividades de instituições financeiras? SEM-CATEGORIA Instituições de Pagamento
5 O que é necessário para abrir uma conta de depósitos? Contas de depósitos (conta corrente e conta poupança) Abertura Contas de depósitos (conta corrente e conta poupança) Informações gerais
7 Como são validados os atos processuais em meio eletrônico? Processo Administrativo Sancionador Rito do Processo Administrativo Sancionador Cédulas manchadas de tinta
8 Posso fazer um Pix Agendado por meio de um iniciador? Pagamento Instantâneo (Pix) Entendendo sobre iniciação de transação de pagamento no Pix Pagamento Instantâneo (Pix) Entendendo quem pode usar o Pix e como usar o Pix
9 Já quitei minha dívida, mas o meu nome não saiu do SCR. Por quê? Sistema de Informações de Créditos (SCR) Atualização dos dados Crédito Rural Renegociação das dívidas
10 Como faço para habilitar meu crédito? Serei avisado sobre isso? De que forma? Liquidação Extrajudicial - Consórcios Empréstimos consignados Cartão de crédito consignado
12 Possuo uma empresa no exterior juntos com outros sócios. Declaro o valor total ou apenas minha parcela? CBE - Capitais Brasileiros no Exterior Informando os ativos no exterior Empréstimos
13 É a primeira vez que se usam tamanhos diferenciados no Brasil? SEM-CATEGORIA CBE - Capitais Brasileiros no Exterior Obrigatoriedade da declaração
14 Preciso efetuar algum pagamento ao contratar? Programa de Garantia da Atividade Agropecuária (Proagro) Contratação Outras Informações
15 Quais instituições o Bacen Jud consegue alcançar para realizar bloqueios e requisitar informações? SEM-CATEGORIA Bacen Jud e SISBAJUD Ordem judicial de bloqueio/desbloqueio de bens e requisição de informações
16 Se eu desistir, recebo o que paguei? Integralmente? Liquidação Extrajudicial - Consórcios Consórcios Desistência e exclusão de consorciado
17 Como é calculado o Ranking do VET? SEM-CATEGORIA Taxa de câmbio
top_confusions_valid = (
    valid_errors.groupby(["true_label", "pred_label"])
    .size()
    .reset_index(name="count")
    .query("true_label != pred_label")
    .sort_values("count", ascending=False)
    .head(20)
)

top_confusions_valid
true_label pred_label count
131 SEM-CATEGORIA Cheques Compensação e pagamento 3
41 Consórcios Grupo de consórcio Consórcios Consórcios - Informações gerais 2
120 Registrato Open Banking Segurança dos dados pessoais compartilhados 2
148 SEM-CATEGORIA Pagamento Instantâneo (Pix) Entendendo quem pode usar o Pix e como usar o Pix 2
20 Cartão de Crédito Internacional Importações Pagamento das importações 2
169 Termo de Compromisso Após a celebração do Termo de Compromisso Termo de Compromisso Informações gerais 2
6 CBE - Capitais Brasileiros no Exterior Informando os ativos no exterior Crédito Rural Renegociação das dívidas 1
7 CBE - Capitais Brasileiros no Exterior Informando os ativos no exterior Empréstimos 1
8 CBE - Capitais Brasileiros no Exterior Iniciando a declaração Envio e recebimento de recursos em moeda estrangeira 1
5 CBE - Capitais Brasileiros no Exterior Informando os ativos no exterior Cheques Emissão 1
2 Aplicações financeiras Cédulas e Moedas em Circulação 1
1 Aplicações financeiras Contas de depósitos (conta corrente e conta poupança) Informações gerais 1
0 Acordo Administrativo em Processo de Supervisão (APS) Open Banking Autorização do cliente para compartilhamento de seus dados 1
12 Cadastro Informativo de créditos não quitados do setor público federal (Cadin) Informações gerais Cadastro Informativo de créditos não quitados do setor público federal (Cadin) Inclusão dos dados no Cadin 1
11 Cadastro Informativo de créditos não quitados do setor público federal (Cadin) Exclusão dos dados do Cadin Cadastro Informativo de créditos não quitados do setor público federal (Cadin) Inclusão dos dados no Cadin 1
15 Cadastro de Clientes do Sistema Financeiro Nacional (CCS) Dúvidas sobre dados Cadastro de Clientes do Sistema Financeiro Nacional (CCS) Dados do CCS 1
13 Cadastro Positivo Conceitos importantes Processos de Autorização do Banco Central Instituições, regras e sistemas que necessitam apenas da autorização para funcionamento (dispensadas da etapa de autorização para constituição) 1
16 Cadastro de Emitentes de Cheques sem Fundos (CCF) Exclusão do nome no CCF Cheques Emissão 1
17 Cadastro de Emitentes de Cheques sem Fundos (CCF) Inclusão do nome no CCF Cadastro de Emitentes de Cheques sem Fundos (CCF) Consulta do CCF 1
18 Calculadora do cidadão Correção de Valores Calculadora do cidadão Aplicação com Depósitos Regulares 1
plt.figure(figsize=(12, 8))
plt.barh(
    (top_confusions_valid["true_label"] + "  →  " + top_confusions_valid["pred_label"])[::-1],
    top_confusions_valid["count"][::-1]
)
plt.title("Principais pares de confusão na validação")
plt.xlabel("Quantidade de erros")
plt.ylabel("Classe verdadeira → classe predita")
plt.tight_layout()
plt.show()
C:\Users\Roberto\AppData\Local\Temp\ipykernel_16152\1019251551.py:9: UserWarning: Tight layout not applied. The left and right margins cannot be made large enough to accommodate all Axes decorations.
  plt.tight_layout()
Graph
valid_class_report = valid_report_df.loc[label_names].copy()
valid_class_report["support"] = valid_class_report["support"].astype(float)

MIN_SUPPORT = 3
WORST_N = 15

worst_classes = (
    valid_class_report[valid_class_report["support"] >= MIN_SUPPORT]
    .sort_values(by="recall", ascending=True)
    .head(WORST_N)
    .index
    .tolist()
)

worst_label_ids = [label_to_id[label] for label in worst_classes]

valid_mask_worst = valid_gold["label_id"].isin(worst_label_ids)

y_valid_worst = y_valid[valid_mask_worst]
valid_pred_worst = pd.Series(valid_pred_best, index=valid_gold.index)[valid_mask_worst]

cm_valid_worst = confusion_matrix(
    y_valid_worst,
    valid_pred_worst,
    labels=worst_label_ids,
    normalize="true"
)

fig, ax = plt.subplots(figsize=(14, 12))
disp = ConfusionMatrixDisplay(
    confusion_matrix=cm_valid_worst,
    display_labels=worst_classes
)
disp.plot(ax=ax, xticks_rotation=-90, colorbar=True)
plt.title(f"Matriz normalizada — {WORST_N} classes com pior recall")
plt.tight_layout()
plt.show()
Graph

📌 Observe:

  • As classes com pior recall não devem ser interpretadas isoladamente como “falha do modelo”.
  • Elas podem refletir:
    • suporte muito pequeno
    • sobreposição semântica entre categorias
    • formulações muito curtas ou ambíguas nas perguntas

✔️ Seção 8 — Reajuste final do baseline

  • Objetivo da seção
    • Reajustar o melhor pipeline utilizando o conjunto combinado de treino + validação.
  • Ações realizadas
    • Concatenação de treino e validação
    • Refit do melhor pipeline selecionado
    • Preparação para avaliação final em teste
  • Justificativa técnica
    • Após escolher a melhor configuração com base na validação, o modelo final deve aproveitar mais dados supervisionados antes da avaliação no holdout final.
  • Resultados esperados
    • Modelo final do baseline pronto para teste

train_valid_gold = pd.concat([train_gold, valid_gold], ignore_index=True)

X_train_valid = train_valid_gold[TEXT_COL].fillna("")
y_train_valid = train_valid_gold[TARGET_COL]

final_model = build_baseline_pipeline(
    tfidf_params=best_entry["config"]["tfidf_params"],
    logreg_params=best_entry["config"]["logreg_params"],
)

final_model.fit(X_train_valid, y_train_valid)

print("Modelo final reajustado com treino + validação.")
Modelo final reajustado com treino + validação.

✔️ Seção 9 — Avaliação final no conjunto de teste

  • Objetivo da seção
    • Medir o desempenho final do baseline em dados não utilizados nem para treino nem para seleção de configuração.
  • Ações realizadas
    • Predição no conjunto de teste
    • Cálculo das métricas globais
    • Geração do relatório por classe
    • ***Construção de visualizações focadas do teste**8
  • Justificativa técnica
    • O teste final deve funcionar como uma leitura honesta da capacidade de generalização do baseline.
  • Resultados esperados
    • Métricas finais do baseline
    • Relatório por classe
    • Base de previsões pronta para análise qualitativa

test_pred = final_model.predict(X_test)

test_metrics = compute_metrics(y_test, test_pred)
test_metrics
{'accuracy': 0.30294906166219837,
 'macro_f1': 0.23681279636053504,
 'weighted_f1': 0.3028420789814892,
 'macro_precision': 0.25571907154821727,
 'macro_recall': 0.2639985642498205}
test_metrics_df = pd.DataFrame([test_metrics])
test_metrics_df.style.format(
    {
        "accuracy": "{:.4f}",
        "macro_f1": "{:.4f}",
        "weighted_f1": "{:.4f}",
        "macro_precision": "{:.4f}",
        "macro_recall": "{:.4f}",
    }
)
  accuracy macro_f1 weighted_f1 macro_precision macro_recall
0 0.3029 0.2368 0.3028 0.2557 0.2640
test_report_df = build_report_df(
    y_true=y_test,
    y_pred=test_pred,
    labels=label_ids,
    target_names=label_names,
)

test_class_report = test_report_df.loc[label_names].copy()
test_class_report = test_class_report.sort_values(by="f1-score", ascending=False)

test_class_report.head(20)
precision recall f1-score support
Cadastro Informativo de créditos não quitados do setor público federal (Cadin) Exclusão dos dados do Cadin 1.000000 1.000000 1.000000 1.0
CBE - Capitais Brasileiros no Exterior Obrigatoriedade da declaração 1.000000 1.000000 1.000000 2.0
Cadastro de Clientes do Sistema Financeiro Nacional (CCS) Dados do CCS 1.000000 1.000000 1.000000 3.0
Cartão de Crédito Internacional 1.000000 1.000000 1.000000 1.0
Empréstimos consignados Cartão de crédito consignado 1.000000 1.000000 1.000000 1.0
Consórcios Aquisição de bens e serviços 1.000000 1.000000 1.000000 2.0
Crédito Rural Renegociação das dívidas 1.000000 1.000000 1.000000 1.0
Crédito Rural Monitoramento e Fiscalização 1.000000 1.000000 1.000000 1.0
Empréstimos consignados Principais dúvidas 1.000000 1.000000 1.000000 2.0
Empréstimos consignados Margem Consignável 1.000000 1.000000 1.000000 1.0
Processo Administrativo Sancionador Informações gerais 1.000000 1.000000 1.000000 2.0
Programa Nacional de Fortalecimento da Agricultura Familiar - Pronaf 1.000000 1.000000 1.000000 6.0
Política Monetária 1.000000 1.000000 1.000000 2.0
Portabilidade de Crédito Dificuldades à portabilidade 1.000000 1.000000 1.000000 1.0
Investimentos Investimentos de estrangeiros no Brasil 1.000000 1.000000 1.000000 1.0
Fundo Garantidor de Créditos (FGC) Informações gerais 1.000000 1.000000 1.000000 1.0
Sistema de Pagamentos em Moeda Local (SML) 1.000000 0.857143 0.923077 7.0
Conta-Salário e Portabilidade Salarial 1.000000 0.750000 0.857143 4.0
Empréstimo, financiamento e arrendamento mercantil (leasing) Arrendamento Mercantil (leasing) 0.750000 1.000000 0.857143 3.0
Valores a Receber 0.666667 1.000000 0.800000 2.0
TOP_N = 15

top_test_labels = (
    test_gold["category_final"]
    .value_counts()
    .head(TOP_N)
    .index
    .tolist()
)

top_test_label_ids = [label_to_id[label] for label in top_test_labels]

test_mask_top = test_gold["label_id"].isin(top_test_label_ids)

y_test_top = y_test[test_mask_top]
test_pred_top = pd.Series(test_pred, index=test_gold.index)[test_mask_top]

cm_test_top_norm = confusion_matrix(
    y_test_top,
    test_pred_top,
    labels=top_test_label_ids,
    normalize="true"
)

fig, ax = plt.subplots(figsize=(16, 14))
disp = ConfusionMatrixDisplay(
    confusion_matrix=cm_test_top_norm,
    display_labels=top_test_labels
)

disp.plot(ax=ax, xticks_rotation=-90, colorbar=True)
plt.title(f"Matriz de confusão normalizada — Teste | Top {TOP_N} classes")
plt.tight_layout()
plt.show()
Graph
test_predictions_df = test_gold.copy()
test_predictions_df["y_true"] = y_test.values
test_predictions_df["y_pred"] = test_pred
test_predictions_df["true_label"] = test_predictions_df["y_true"].map(id_to_label)
test_predictions_df["pred_label"] = test_predictions_df["y_pred"].map(id_to_label)
test_predictions_df["is_error"] = test_predictions_df["y_true"] != test_predictions_df["y_pred"]

test_predictions_df[["question_raw", "true_label", "pred_label", "is_error"]].head(15)
question_raw true_label pred_label is_error
0 Qual a diferença entre credenciadores e subcredenciadores? Instituições de Pagamento Pagamento Instantâneo (Pix) Entendendo a diferença entre o Pix e os outros meios de pagamento (TED, DOC, boleto bancário e cartões) True
1 O cliente pode revogar o consentimento anterior? Open Banking Autorização do cliente para compartilhamento de seus dados Open Banking Autorização do cliente para compartilhamento de seus dados False
2 O que devo fazer se suspeitar que uma cédula pode ser falsa? Cédula de R$200,00 Itens de segurança e falsificações Cédulas Falsas e Suspeitas Identificação de cédulas falsas ou suspeitas True
3 Com o Pix, a TED e o DOC vão acabar? Pagamento Instantâneo (Pix) Entendendo a diferença entre o Pix e os outros meios de pagamento (TED, DOC, boleto bancário e cartões) Transferências True
4 Todas as operações de câmbio de uma instituição compõem a média calculada para classificação? SEM-CATEGORIA Câmbio True
5 Como se classificam os recursos do crédito rural? SEM-CATEGORIA Crédito Rural Informações Gerais True
6 Quando os recursos livres de clientes em posse da corretora serão liberados? Liquidação Extrajudicial - Corretoras de Títulos e Valores Mobiliários Liquidação Extrajudicial - Corretoras de câmbio True
7 Quero efetuar o pagamento de uma conta com um cheque, mas o banco se recusa a receber. O procedimento do banco está correto? Cheques Talão de cheque Cheques Sustação e revogação de cheque True
8 Quais dados estão contidos no CCS? Cadastro de Clientes do Sistema Financeiro Nacional (CCS) Dados do CCS Cadastro de Clientes do Sistema Financeiro Nacional (CCS) Dados do CCS False
9 Quais são as condições básicas dos créditos de investimento do Pronaf - Floresta? Programa Nacional de Fortalecimento da Agricultura Familiar - Pronaf Programa Nacional de Fortalecimento da Agricultura Familiar - Pronaf False
10 Qual o horário de funcionamento das agências bancárias? Atendimento bancário (fila, feriados e outros) Processos de Autorização do Banco Central Processo de autorização para constituição e funcionamento – Geral True
11 Os bancos centrais atuam como garantidores das operações? Sistema de Pagamentos em Moeda Local (SML) Microcrédito Microcrédito True
12 Como é calculada a Taxa SML? Sistema de Pagamentos em Moeda Local (SML) Sistema de Pagamentos em Moeda Local (SML) False
13 Quais as consequências para o correntista que sustar indevidamente o seu pagamento? Cheques Sustação e revogação de cheque Cheques Devolução de cheques True
14 O que deve estar previsto no contrato de adesão? Consórcios Cuidados aos contratar consórcios Cadastro de Emitentes de Cheques sem Fundos (CCF) Informações gerais True
test_errors = test_predictions_df[test_predictions_df["is_error"]].copy()

top_confusions_test = (
    test_errors.groupby(["true_label", "pred_label"])
    .size()
    .reset_index(name="count")
    .query("true_label != pred_label")
    .sort_values("count", ascending=False)
    .head(20)
)

top_confusions_test
true_label pred_label count
24 Calculadora do cidadão Informações gerais Calculadora do cidadão Metodologia e cálculos 3
188 SEM-CATEGORIA Pagamento Instantâneo (Pix) Entendendo como receber um Pix 3
149 Registro Declaratório Eletrônico - Registro de Operações Financeiras (RDE-ROF) Registro de operações de Empréstimos Diretos ou Títulos Registro Declaratório Eletrônico - Registro de Operações Financeiras (RDE-ROF) Acesso ao RDE-ROF 3
169 SEM-CATEGORIA Cédulas Falsas e Suspeitas Cédula falsa ou suspeita sacada em banco 3
174 SEM-CATEGORIA Cédulas manchadas de tinta 3
64 Empréstimo, financiamento e arrendamento mercantil (leasing) Formas de contratação e cuidados ao contratar operações de crédito Microcrédito Microcrédito Produtivo Orientado – Limites e requisitos 2
75 Importações Pagamento das importações Importações Informações gerais 2
89 Mercado de câmbio Câmbio 2
63 Empréstimo, financiamento e arrendamento mercantil (leasing) Custo Efetivo Total (CET) Empréstimo, financiamento e arrendamento mercantil (leasing) Formas de contratação e cuidados ao contratar operações de crédito 2
18 Cadastro Informativo de créditos não quitados do setor público federal (Cadin) Consulta aos meus dados no Cadin Cadastro Informativo de créditos não quitados do setor público federal (Cadin) Informações gerais 2
8 Atendimento bancário (fila, feriados e outros) Cheques Sustação e revogação de cheque 2
153 SEM-CATEGORIA Cadastro de Clientes do Sistema Financeiro Nacional (CCS) Acesso a órgãos e instituições participantes 2
124 Processo Administrativo Sancionador Dúvidas e informações Processo Administrativo Sancionador Acompanhamento do Processo e Pagamento de Multas 2
133 Processos de Autorização do Banco Central Instituições, regras e sistemas que necessitam apenas da autorização para funcionamento (dispensadas da etapa de autorização para constituição) Processos de Autorização do Banco Central Processo de autorização para constituição e funcionamento – Geral 2
158 SEM-CATEGORIA Cheques Sustação e revogação de cheque 2
166 SEM-CATEGORIA Cédula de R$200,00 Circulação e custo da cédula de 200 reais 2
170 SEM-CATEGORIA Cédulas Falsas e Suspeitas Dinheiro suspeito recebido em circunstância diferente do saque 2
163 SEM-CATEGORIA Crédito Rural Informações Gerais 2
142 Regimes de Resolução - Definições Informações gerais Banco Central do Brasil 2
106 Pagamento Instantâneo (Pix) Entendendo como se faz um Pix Pagamento Instantâneo (Pix) Entendendo quem pode usar o Pix e como usar o Pix 2
plt.figure(figsize=(10, 14))
plt.barh(
    (top_confusions_test["true_label"] + "  →  " + top_confusions_test["pred_label"])[::-1],
    top_confusions_test["count"][::-1]
)
plt.title("Principais pares de confusão no conjunto de teste")
plt.xlabel("Quantidade de erros")
plt.ylabel("Classe verdadeira → classe predita")
plt.tight_layout()
plt.show()
C:\Users\Roberto\AppData\Local\Temp\ipykernel_16152\1109364981.py:9: UserWarning: Tight layout not applied. The left and right margins cannot be made large enough to accommodate all Axes decorations.
  plt.tight_layout()
Graph
test_errors[[
    "question_raw",
    "true_label",
    "pred_label"
]].head(15)
question_raw true_label pred_label
0 Qual a diferença entre credenciadores e subcredenciadores? Instituições de Pagamento Pagamento Instantâneo (Pix) Entendendo a diferença entre o Pix e os outros meios de pagamento (TED, DOC, boleto bancário e cartões)
2 O que devo fazer se suspeitar que uma cédula pode ser falsa? Cédula de R$200,00 Itens de segurança e falsificações Cédulas Falsas e Suspeitas Identificação de cédulas falsas ou suspeitas
3 Com o Pix, a TED e o DOC vão acabar? Pagamento Instantâneo (Pix) Entendendo a diferença entre o Pix e os outros meios de pagamento (TED, DOC, boleto bancário e cartões) Transferências
4 Todas as operações de câmbio de uma instituição compõem a média calculada para classificação? SEM-CATEGORIA Câmbio
5 Como se classificam os recursos do crédito rural? SEM-CATEGORIA Crédito Rural Informações Gerais
6 Quando os recursos livres de clientes em posse da corretora serão liberados? Liquidação Extrajudicial - Corretoras de Títulos e Valores Mobiliários Liquidação Extrajudicial - Corretoras de câmbio
7 Quero efetuar o pagamento de uma conta com um cheque, mas o banco se recusa a receber. O procedimento do banco está correto? Cheques Talão de cheque Cheques Sustação e revogação de cheque
10 Qual o horário de funcionamento das agências bancárias? Atendimento bancário (fila, feriados e outros) Processos de Autorização do Banco Central Processo de autorização para constituição e funcionamento – Geral
11 Os bancos centrais atuam como garantidores das operações? Sistema de Pagamentos em Moeda Local (SML) Microcrédito Microcrédito
13 Quais as consequências para o correntista que sustar indevidamente o seu pagamento? Cheques Sustação e revogação de cheque Cheques Devolução de cheques
14 O que deve estar previsto no contrato de adesão? Consórcios Cuidados aos contratar consórcios Cadastro de Emitentes de Cheques sem Fundos (CCF) Informações gerais
17 Posso pagar boleto usando Pix? Pagamento Instantâneo (Pix) Entendendo a diferença entre o Pix e os outros meios de pagamento (TED, DOC, boleto bancário e cartões) Pagamento Instantâneo (Pix) Entendendo como funciona o Pix
18 Existe algum fundo de crédito que garanta as operações realizadas pelas corretoras de câmbio,a exemplo do Fundo Garantidor de Crédito (FGC) e do Fundo Garantidor do Crédito Cooperativo (FGCoop)? Liquidação Extrajudicial - Corretoras de câmbio Fundo Garantidor do Cooperativismo (FGCoop)
19 Como posso acessar a Calculadora do Cidadão? Calculadora do cidadão Informações gerais Calculadora do cidadão Metodologia e cálculos
24 Como posso agilizar a aprovação de um financiamento com o banco? Empréstimo, financiamento e arrendamento mercantil (leasing) Operação de crédito e seus principais tipos Crédito Imobiliário

📌 Observe:

  • A leitura de teste combina:
    • métricas globais
    • relatório por classe
    • visualização focada
    • inspeção qualitativa de erros
  • Esse conjunto é muito mais útil do que olhar apenas accuracy isoladamente.

✔️ Seção 10 — Persistência dos artefatos do baseline

  • Objetivo da seção
    • Salvar os principais artefatos produzidos neste notebook para reuso no projeto.
  • Ações realizadas
    • Persistência do pipeline final
    • Persistência das métricas
    • Persistência do relatório por classe
    • Persistência das previsões do teste
    • Persistência dos metadados do baseline
  • Justificativa técnica
    • Persistir artefatos melhora rastreabilidade, reprodutibilidade e integração futura com API e monitoramento.
  • Resultados esperados
    • Pipeline salvo para inferência futura
    • Resultados salvos para comparação com transformer

model_path = MODELS_DIR / "tfidf_logreg_pipeline.joblib"
valid_results_path = REPORTS_DIR / "baseline_valid_model_comparison.csv"
test_metrics_path = REPORTS_DIR / "baseline_test_metrics.csv"
test_report_path = REPORTS_DIR / "baseline_test_classification_report.csv"
test_predictions_path = REPORTS_DIR / "baseline_test_predictions.csv"
metadata_path = MODELS_DIR / "baseline_metadata.json"

joblib.dump(final_model, model_path)

valid_results_df.to_csv(valid_results_path, index=False)
test_metrics_df.to_csv(test_metrics_path, index=False)
test_class_report.to_csv(test_report_path)
test_predictions_df.to_csv(test_predictions_path, index=False)

baseline_metadata = {
    "project": "nlp-triagem-inteligente-financeira",
    "model_family": "TF-IDF + Logistic Regression",
    "selected_model_name": best_model_name,
    "text_column": TEXT_COL,
    "target_column": TARGET_COL,
    "n_train": int(train_gold.shape[0]),
    "n_valid": int(valid_gold.shape[0]),
    "n_test": int(test_gold.shape[0]),
    "n_train_valid": int(train_valid_gold.shape[0]),
    "label_count": int(len(label_ids)),
    "valid_metrics_selected_model": best_entry["valid_metrics"],
    "test_metrics": test_metrics,
    "tfidf_params": best_entry["config"]["tfidf_params"],
    "logreg_params": best_entry["config"]["logreg_params"],
}

with open(metadata_path, "w", encoding="utf-8") as f:
    json.dump(baseline_metadata, f, ensure_ascii=False, indent=2)

print("Artefatos salvos com sucesso:")
print(model_path)
print(valid_results_path)
print(test_metrics_path)
print(test_report_path)
print(test_predictions_path)
print(metadata_path)
Artefatos salvos com sucesso:
D:\_DS-Projects\nlp-triagem-inteligente-financeira\models\baseline\tfidf_logreg_pipeline.joblib
D:\_DS-Projects\nlp-triagem-inteligente-financeira\artifacts\reports\baseline_valid_model_comparison.csv
D:\_DS-Projects\nlp-triagem-inteligente-financeira\artifacts\reports\baseline_test_metrics.csv
D:\_DS-Projects\nlp-triagem-inteligente-financeira\artifacts\reports\baseline_test_classification_report.csv
D:\_DS-Projects\nlp-triagem-inteligente-financeira\artifacts\reports\baseline_test_predictions.csv
D:\_DS-Projects\nlp-triagem-inteligente-financeira\models\baseline\baseline_metadata.json
bas_met = pd.DataFrame(baseline_metadata)
bas_met
project model_family selected_model_name text_column target_column n_train n_valid n_test n_train_valid label_count valid_metrics_selected_model test_metrics tfidf_params logreg_params
accuracy nlp-triagem-inteligente-financeira TF-IDF + Logistic Regression tfidf_word_unigram_logreg question_clean label_id 1044 261 373 1305 242 0.310345 0.302949 NaN NaN
macro_f1 nlp-triagem-inteligente-financeira TF-IDF + Logistic Regression tfidf_word_unigram_logreg question_clean label_id 1044 261 373 1305 242 0.224697 0.236813 NaN NaN
weighted_f1 nlp-triagem-inteligente-financeira TF-IDF + Logistic Regression tfidf_word_unigram_logreg question_clean label_id 1044 261 373 1305 242 0.289012 0.302842 NaN NaN
macro_precision nlp-triagem-inteligente-financeira TF-IDF + Logistic Regression tfidf_word_unigram_logreg question_clean label_id 1044 261 373 1305 242 0.235980 0.255719 NaN NaN
macro_recall nlp-triagem-inteligente-financeira TF-IDF + Logistic Regression tfidf_word_unigram_logreg question_clean label_id 1044 261 373 1305 242 0.255121 0.263999 NaN NaN
analyzer nlp-triagem-inteligente-financeira TF-IDF + Logistic Regression tfidf_word_unigram_logreg question_clean label_id 1044 261 373 1305 242 NaN NaN word NaN
ngram_range nlp-triagem-inteligente-financeira TF-IDF + Logistic Regression tfidf_word_unigram_logreg question_clean label_id 1044 261 373 1305 242 NaN NaN (1, 1) NaN
min_df nlp-triagem-inteligente-financeira TF-IDF + Logistic Regression tfidf_word_unigram_logreg question_clean label_id 1044 261 373 1305 242 NaN NaN 2 NaN
max_df nlp-triagem-inteligente-financeira TF-IDF + Logistic Regression tfidf_word_unigram_logreg question_clean label_id 1044 261 373 1305 242 NaN NaN 0.95 NaN
sublinear_tf nlp-triagem-inteligente-financeira TF-IDF + Logistic Regression tfidf_word_unigram_logreg question_clean label_id 1044 261 373 1305 242 NaN NaN True NaN
C nlp-triagem-inteligente-financeira TF-IDF + Logistic Regression tfidf_word_unigram_logreg question_clean label_id 1044 261 373 1305 242 NaN NaN NaN 2.0
max_iter nlp-triagem-inteligente-financeira TF-IDF + Logistic Regression tfidf_word_unigram_logreg question_clean label_id 1044 261 373 1305 242 NaN NaN NaN 3000
solver nlp-triagem-inteligente-financeira TF-IDF + Logistic Regression tfidf_word_unigram_logreg question_clean label_id 1044 261 373 1305 242 NaN NaN NaN saga
class_weight nlp-triagem-inteligente-financeira TF-IDF + Logistic Regression tfidf_word_unigram_logreg question_clean label_id 1044 261 373 1305 242 NaN NaN NaN balanced
random_state nlp-triagem-inteligente-financeira TF-IDF + Logistic Regression tfidf_word_unigram_logreg question_clean label_id 1044 261 373 1305 242 NaN NaN NaN 42

✔️ Seção 11 — Leitura executiva do baseline

  • Síntese da etapa
    • O baseline com TF-IDF + Regressão Logística estabeleceu uma referência técnica consistente para o projeto, permitindo comparar configurações, selecionar o melhor pipeline e medir desempenho final em teste.
  • Leitura analítica
    • O modelo tende a apresentar melhor comportamento nas classes mais frequentes,
    • mas encontra dificuldade em categorias semanticamente próximas e em classes menos representadas,
    • o que é esperado em problemas multiclasses com taxonomia extensa.
  • Valor para o projeto
    • Este baseline cumpre três papéis importantes:
      1. referência quantitativa para comparação com transformer
      2. primeiro modelo reutilizável para API
      3. evidência de maturidade metodológica no pipeline de NLP

📌 Próximo passo do projeto

  • No Notebook 05 — Transformer Text Classifier, vamos avaliar um modelo baseado em transformer para medir o ganho real sobre este baseline clássico, especialmente em:
    • classes semanticamente próximas
    • generalização
    • qualidade global da classificação
    • potencial de uso em cenários mais avançados de NLP aplicado

Fim

#!uv pip install nbconvert -U -q
!jupyter nbconvert --to html --template-file my-template-html-v10.tpl 04_modeling__baseline_tfidf_logreg.ipynb