Existe uma diferença entre "tomei cuidado para não vazar dado" e "não é possível vazar dado aqui". A primeira depende de disciplina e falha num dia ruim. A segunda é arquitetura. Esta fase é sobre construir a segunda.
Os tratamentos
| Problema | Tratamento |
|---|---|
| Renda faltante | Imputação pela mediana + flag renda_ausente |
| Dependentes faltantes | Mesmo tratamento, com dependentes_ausente |
| Outliers de renda | Corte no topo (R$ 50.000) |
| Sentinelas de atraso | Corte em 20 ocorrências + flag de sinalização |
| Texto em coluna numérica | Conversor de locale pt-BR, sem coerce |
A flag junto com a imputação é o detalhe que importa. Imputar sem sinalizar apaga a informação de que o dado faltava — e nesta base, como mostrei na parte anterior, faltar é sinal de risco menor. A mediana preenche o buraco; a flag preserva o que o buraco significava.
A parte que é arquitetura, não tratamento
O erro clássico: tratar a base inteira, depois separar treino e teste. Parece inofensivo, mas a mediana usada para imputar foi calculada com dados do teste dentro. O modelo já viu, de forma indireta, informação que não deveria ter. A métrica sai melhor do que a realidade.
A solução aqui foi colocar a preparação dentro do pipeline, de modo que o fit aconteça separadamente em cada dobra da validação cruzada:
pipeline = criar_pipeline(modelo) # preparo → imputação → modelo
pipeline.fit(X_treino, y_treino)
O split é 75/25 estratificado, e a base de teste — 37.500 clientes — não é tocada até a fase de avaliação. As estatísticas aprendidas (medianas, cortes) são gravadas num arquivo de parâmetros: a função de preparo aprende quando recebe None e apenas aplica quando recebe o dicionário do treino. É a mesma função que o deploy vai chamar.
Como o fit acontece dentro de cada dobra, o vazamento não é evitado — ele é impossível por construção. Essa é a diferença entre um processo que depende de lembrar e um que depende de existir.
Um detalhe que salva a explicabilidade
Todos os passos do pipeline devolvem DataFrame com nomes de coluna preservados. Parece preciosismo até a fase de explicabilidade, quando o SHAP precisa dizer razao_divida e não feature 4. Comitê de crédito não audita "feature 4".
Parte 5 de 12 da série Aurora — um modelo de risco de crédito do zero ao deploy. O mapa completo da série reúne todas as partes e os números finais. Veja também a documentação técnica e o código no GitHub ↗.