Este documento resume os principais conceitos, decisoes tecnicas e resultados vistos ate agora nos notebooks do projeto.
O projeto esta estruturado como um fluxo inicial de ciencia de dados para regressao supervisionada. A base usada e o dataset load_diabetes, disponivel no Scikit-learn.
O objetivo do problema e prever uma medida quantitativa de progressao da diabetes um ano apos a coleta inicial de variaveis clinicas dos pacientes.
A sequencia dos notebooks segue uma ordem adequada:
- analisar os dados;
- tratar e salvar a base;
- criar um modelo baseline;
- avaliar desempenho;
- diagnosticar aprendizado;
- organizar preprocessamento e modelo em pipelines;
- tratar variaveis categoricas corretamente;
- aplicar transformacoes em features e target;
- avaliar modelos com validacao cruzada;
- comparar modelos e preprocessamentos por metricas;
- comparar modelos lineares regularizados.
Notebook: notebooks/01_EDA.ipynb
Foi carregado o dataset de diabetes do Scikit-learn:
from sklearn.datasets import load_diabetes
dados = load_diabetes(as_frame=True, scaled=False)A base possui:
442linhas;10variaveis explicativas;1variavel alvo, chamadatarget.
As colunas originais foram renomeadas para nomes mais interpretaveis em portugues:
| Coluna original | Nome usado no projeto |
|---|---|
age |
idade |
sex |
sexo |
bmi |
imc |
bp |
pressao_media |
s1 |
colesterol_total |
s2 |
ldl |
s3 |
hdl |
s4 |
colesterol_hdl |
s5 |
triglicerides |
s6 |
glicose |
target |
target |
Foram avaliados:
- primeiras linhas com
head; - estrutura da base com
info; - estatisticas descritivas com
describe; - distribuicoes das variaveis;
- matriz de correlacao;
- mapa de calor com Seaborn.
Um ponto importante e que a base nao possui valores nulos. Isso simplifica a primeira etapa de modelagem, pois nao foi necessario aplicar imputacao.
A matriz de correlacao indicou algumas variaveis com relacao mais forte com o target, especialmente:
imc;pressao_media;triglicerides;colesterol_hdl.
Essa analise nao prova causalidade. Ela apenas indica associacao linear entre as variaveis e ajuda a orientar a interpretacao inicial.
Tambem foi feito ajuste dos tipos numericos com downcast.
Antes:
memory usage: 38.1 KB
Depois:
memory usage: 13.5 KB
Essa pratica e util principalmente em bases maiores, porque reduz custo de memoria sem alterar a estrutura analitica da base.
A base final foi salva em:
dados/diabetes_tratados.parquet
Isso cria uma separacao importante entre:
- dados brutos carregados do Scikit-learn;
- dados tratados usados nos proximos notebooks.
Nos notebooks com categorizacao de colesterol_hdl, tambem e usada a base:
dados/diabetes_categorizado.parquet
Essa segunda versao contem a coluna colesterol_hdl_cat, necessaria para os pipelines com OrdinalEncoder.
Notebook: notebooks/02_regressao_linear.ipynb
Foi criado o primeiro modelo baseline com LinearRegression.
O dataset foi separado em:
X = df.drop(columns="target")
y = df["target"]Depois, foi feita a divisao entre treino e teste:
X_train, X_test, y_train, y_test = train_test_split(
X,
y,
test_size=0.2,
random_state=42
)Essa divisao e fundamental para medir a capacidade de generalizacao do modelo. O modelo aprende com os dados de treino e e avaliado em dados que nao foram usados no ajuste.
O modelo usado foi:
regressor = LinearRegression()
regressor.fit(X_train, y_train)Esse modelo tenta ajustar uma relacao linear entre as variaveis explicativas e o target.
As principais metricas avaliadas foram:
| Metrica | Valor aproximado | Interpretacao |
|---|---|---|
R2 |
0.453 |
O modelo explica cerca de 45% da variacao do target |
MAE |
42.79 |
Erro absoluto medio em unidades do target |
MSE |
2900.20 |
Penaliza erros maiores por elevar o erro ao quadrado |
RMSE |
53.85 |
Erro medio na escala original do target |
O resultado e aceitavel como baseline, mas ainda existe bastante erro residual.
Os coeficientes indicam o impacto estimado de cada variavel na predicao, mantendo as demais constantes.
Alguns coeficientes observados:
| Variavel | Coeficiente aproximado |
|---|---|
triglicerides |
67.11 |
sexo |
-23.06 |
colesterol_hdl |
10.16 |
imc |
5.85 |
colesterol_total |
-1.28 |
Como as variaveis ainda nao estavam padronizadas nesse notebook, a comparacao direta entre magnitudes dos coeficientes deve ser feita com cuidado. Variaveis em escalas diferentes podem gerar coeficientes numericamente diferentes mesmo quando sua importancia real nao e proporcional a esse valor.
Notebook: notebooks/03_curva_aprendizado.ipynb
A curva de aprendizado foi usada para avaliar como o desempenho do modelo muda conforme a quantidade de dados de treino aumenta.
Foi usado:
from sklearn.model_selection import learning_curve, LearningCurveDisplayA curva compara desempenho em:
- treino;
- validacao.
Ela ajuda a diagnosticar tres situacoes comuns.
Ocorre quando o modelo aprende muito bem os dados de treino, mas nao generaliza bem para dados novos.
Sinais comuns:
- desempenho alto no treino;
- desempenho baixo na validacao;
- grande distancia entre as curvas.
Ocorre quando o modelo e simples demais ou nao consegue capturar os padroes relevantes dos dados.
Sinais comuns:
- desempenho ruim no treino;
- desempenho ruim na validacao;
- curvas proximas, mas em nivel baixo.
Ocorre quando as curvas de treino e validacao ficam proximas e com bom desempenho.
Esse e o comportamento desejado.
Notebook: notebooks/04_introducao_a_pipelines.ipynb
Foi introduzido o uso de Pipeline do Scikit-learn.
O pipeline criado combinou:
Pipeline([
("scaler", StandardScaler()),
("reg", LinearRegression())
])Pipelines sao importantes porque:
- organizam o fluxo de preprocessamento e modelagem;
- reduzem repeticao de codigo;
- evitam vazamento de dados;
- facilitam validacao cruzada;
- facilitam busca de hiperparametros com
GridSearchCVouRandomizedSearchCV; - tornam o modelo final mais facil de salvar e reutilizar.
O StandardScaler transforma as variaveis para media zero e desvio padrao um.
Isso e especialmente importante em modelos sensiveis a escala, como:
- regressao linear com regularizacao;
- KNN;
- SVM;
- modelos baseados em distancia;
- redes neurais.
Na regressao linear simples, a padronizacao nao deve mudar as predicoes de forma relevante, mas torna os coeficientes mais comparaveis.
As metricas de erro permaneceram praticamente iguais ao notebook anterior:
| Metrica | Valor aproximado |
|---|---|
MAE |
42.79 |
MSE |
2900.19 |
RMSE |
53.85 |
As metricas devem receber primeiro os valores reais e depois as predicoes:
r2_score(y_test, y_pred)No notebook de pipeline, essa ordem foi corrigida para MAE, MSE, RMSE, R2 e para o grafico de residuos. O R2 correto fica proximo de:
0.453
Essa observacao e importante porque algumas metricas sao simetricas, mas o R2 nao deve ser tratado assim.
Notebook: notebooks/05_one_hot.ipynb
A coluna sexo aparece numericamente como 1 e 2, mas conceitualmente ela representa uma categoria.
Se essa coluna for usada diretamente como numero, o modelo pode interpretar uma relacao ordinal inexistente. Por exemplo, pode assumir que 2 e maior que 1 em sentido quantitativo, quando na verdade sao apenas categorias.
Foi feita a conversao:
df["sexo"] = df["sexo"].astype("category")Foi usado ColumnTransformer para aplicar transformacoes diferentes em grupos diferentes de colunas:
ColumnTransformer([
("numeric", StandardScaler(), colunas_numericas),
("categoric", OneHotEncoder(drop="if_binary"), ["sexo"])
])Isso e uma boa pratica porque dados reais normalmente possuem diferentes tipos de variaveis:
- numericas continuas;
- numericas discretas;
- categoricas;
- datas;
- textos.
Cada grupo exige tratamentos diferentes.
O OneHotEncoder transforma categorias em colunas binarias.
Como sexo e uma variavel binaria, foi usado:
OneHotEncoder(drop="if_binary")Isso evita criar colunas redundantes para uma variavel com apenas duas categorias.
O fluxo final combinou:
- preprocessamento numerico com
StandardScaler; - preprocessamento categorico com
OneHotEncoder; - modelo
LinearRegression.
Esse e um formato muito mais proximo de um pipeline profissional de machine learning.
As metricas ficaram praticamente iguais ao baseline:
| Metrica | Valor aproximado |
|---|---|
R2 |
0.453 |
MAE |
42.79 |
MSE |
2900.19 |
RMSE |
53.85 |
Isso mostra que o tratamento categorico nao melhorou necessariamente o desempenho nesse dataset, mas melhorou a corretude tecnica do pipeline.
Notebook: notebooks/06_outras_transformacoes.ipynb
Esse notebook evolui o preprocessamento para um fluxo com transformacoes diferentes por grupo de variaveis.
Foram usadas:
PowerTransformer(method="box-cox")emimc,ldl,hdlecolesterol_total;StandardScaleremidade,pressao_media,triglicerideseglicose;OrdinalEncoderna nova variavelcolesterol_hdl_cat;OneHotEncoder(drop="if_binary")emsexo;LinearRegressioncomo estimador final.
A variavel colesterol_hdl foi arredondada, convertida para inteiro e depois categorizada em faixas:
pd.cut(
df["colesterol_hdl"],
bins=[2, 4, 6, 10],
labels=["2-3", "4-5", "6+"],
right=False,
)Como essas faixas possuem ordem natural, o uso de OrdinalEncoder faz sentido nesse caso.
O modelo com transformacoes mistas apresentou:
| Metrica | Valor aproximado |
|---|---|
R2 |
0.442 |
MAE |
43.64 |
MSE |
2957.29 |
RMSE |
54.38 |
O desempenho ficou um pouco pior que o baseline linear anterior. Isso e um ponto importante: nem toda transformacao melhora o modelo. Transformacoes devem ser avaliadas por metrica, validacao e coerencia com o problema.
Notebook: notebooks/07_target_transformer.ipynb
Esse notebook introduz o uso de TransformedTargetRegressor, que permite aplicar uma transformacao em y durante o treino e reverter essa transformacao durante a predicao.
O fluxo fica conceitualmente assim:
- transforma
yno treinamento; - ajusta o modelo usando o target transformado;
- gera predicoes;
- aplica a transformacao inversa para voltar a escala original do target.
Transformar o target pode ajudar quando y possui assimetria, caudas longas ou distribuicao pouco adequada para modelos lineares.
No projeto, essa tecnica foi combinada com:
Pipeline;ColumnTransformer;- transformacoes numericas e categoricas;
LinearRegression.
O target deve ser transformado dentro do processo de validacao ou treino, nao manualmente antes da separacao dos dados. O TransformedTargetRegressor ajuda a manter esse fluxo mais seguro e reproduzivel.
Notebook: notebooks/08_validacao_cruzada.ipynb
Foi introduzida a avaliacao com KFold e cross_validate.
Em vez de depender de uma unica divisao treino/teste, a validacao cruzada avalia o modelo em diferentes particoes dos dados. Isso gera uma estimativa mais estavel de desempenho.
Exemplo do conceito:
kf = KFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_validate(
model,
X,
y,
cv=kf,
scoring=[
"r2",
"neg_mean_absolute_error",
"neg_root_mean_squared_error",
],
)No Scikit-learn, metricas de erro usadas em scoring aparecem com sinal negativo quando seguem a convencao de que "maior e melhor".
Por isso:
neg_mean_absolute_errorrepresenta oMAEcom sinal negativo;neg_root_mean_squared_errorrepresenta oRMSEcom sinal negativo.
Para interpretar como erro comum, pode-se multiplicar por -1.
Notebook: notebooks/09_dummy_regressor.ipynb
Foi usado DummyRegressor como baseline ingenuo.
Esse modelo nao aprende relacoes reais entre X e y. Com strategy="mean", por exemplo, ele sempre prediz a media do target observada no treino.
Um modelo real precisa superar um baseline simples. Se LinearRegression, modelos regularizados ou modelos nao lineares nao superarem o DummyRegressor, existe algum problema no pipeline, nas features, na avaliacao ou na propria capacidade preditiva dos dados.
Esse passo melhora a qualidade da analise porque evita comparar modelos apenas entre si sem uma referencia minima.
Notebook: notebooks/10. analise_complexidade.ipynb
Esse notebook compara diferentes niveis de preprocessamento:
- preprocessamento categorico;
- preprocessamento simples;
- preprocessamento completo.
Como o preprocessamento completo usa colesterol_hdl_cat, o notebook deve carregar:
from src.config import DADOS_CATEGORIZADOS
df = pd.read_parquet(DADOS_CATEGORIZADOS)Se for usado DADOS_TRATADOS, a coluna colesterol_hdl_cat nao existe e o ColumnTransformer falha.
O objeto resultados retornado pela validacao cruzada e um dicionario. Ele nao deve ser passado diretamente para sns.boxplot, porque o Seaborn espera um DataFrame com colunas como model, test_r2 e time_seconds.
Fluxo correto:
resultados = {
nome_modelo: treinar_e_validar_modelo_regressao(X, y, **regressor)
for nome_modelo, regressor in regressors.items()
}
df_resultados = organiza_resultados(resultados)Depois:
sns.boxplot(
x="model",
y="test_r2",
data=df_resultados,
)Se aparecer o erro:
ValueError: Could not interpret value `model` for `x`
significa que o objeto passado em data nao possui a coluna model. Na pratica, isso costuma acontecer quando se usa data=resultados em vez de data=df_resultados.
Se aparecer:
NameError: name 'df_resultados' is not defined
significa que a celula que cria df_resultados = organiza_resultados(resultados) nao foi executada com sucesso antes do grafico.
A funcao organiza_resultados transforma o dicionario do cross_validate em formato tabular, expandindo as metricas por fold e criando a coluna model.
Esse formato e adequado para:
- graficos com Seaborn;
- comparacao de distribuicao das metricas;
- analise de tempo de treino e score;
- comparacao visual entre modelos e preprocessamentos.
Notebook: notebooks/11_outros_modelos.ipynb
Esse notebook amplia a comparacao iniciada na analise de complexidade. Alem de DummyRegressor e LinearRegression, foram avaliados modelos lineares regularizados:
Lasso;Ridge;ElasticNet.
Os modelos foram combinados com diferentes configuracoes:
- preprocessamento apenas categorico;
- preprocessamento simples com
StandardScaler; - preprocessamento completo com
PowerTransformer,StandardScaler,OrdinalEncodereOneHotEncoder; - preprocessamento completo com transformacao do target via
QuantileTransformer; - ajustes iniciais de hiperparametros, como
alpha=0.1.
Modelos regularizados sao importantes porque reduzem a liberdade do modelo e ajudam a controlar coeficientes instaveis.
O Lasso usa penalizacao L1. Essa penalizacao pode zerar coeficientes e, por isso, funciona como uma forma simples de selecao de variaveis.
O Ridge usa penalizacao L2. Ele nao costuma zerar coeficientes, mas reduz magnitudes e tende a ser util quando ha multicolinearidade entre variaveis.
O ElasticNet combina L1 e L2. Ele pode ser util quando se deseja equilibrar selecao de variaveis e estabilidade numerica.
A avaliacao manteve o mesmo padrao tecnico:
resultados = {
nome_modelo: treinar_e_validar_modelo_regressao(X, y, **regressor)
for nome_modelo, regressor in regressors.items()
}
df_resultados = organiza_resultados(resultados)Depois, foi criada a coluna model_group:
df_resultados["model_group"] = df_resultados["model"].str.split("_").str[0]Essa coluna permite comparar visualmente familias de modelos no Seaborn, por exemplo:
DummyRegressor;LinearRegression;Lasso;Ridge;ElasticNet.
O DummyRegressor continua sendo a referencia minima. Qualquer modelo treinado precisa supera-lo de forma consistente.
A regressao linear simples continua sendo um baseline forte para este dataset. A inclusao de modelos regularizados e tecnicamente correta porque permite avaliar se penalizacoes L1 e L2 melhoram generalizacao ou estabilidade.
Entretanto, a regularizacao nao deve ser assumida como melhoria automatica. O ganho deve aparecer nas metricas de validacao cruzada, especialmente em test_r2, test_neg_mean_absolute_error e test_neg_root_mean_squared_error.
Tambem e importante comparar tempo de execucao. Pipelines com PowerTransformer e QuantileTransformer adicionam custo computacional; esse custo so vale a pena se houver ganho claro de desempenho, estabilidade ou interpretabilidade.
O notebook usa a base categorizada:
from src.config import DADOS_CATEGORIZADOS
df = pd.read_parquet(DADOS_CATEGORIZADOS)Essa escolha e obrigatoria porque os preprocessadores usam colesterol_hdl_cat. Se a base numerica tratada for usada no lugar dela, o validador de colunas em src.modelos.validar_colunas_preprocessador deve bloquear o treino com uma mensagem indicando as colunas faltantes.
Antes de treinar um modelo, e necessario entender:
- tamanho da base;
- tipos de dados;
- valores ausentes;
- distribuicoes;
- correlacoes;
- possiveis outliers;
- comportamento do target.
Modelar sem EDA aumenta o risco de erro tecnico e interpretacao incorreta.
Avaliacao em dados de treino nao mede generalizacao. Por isso, o modelo deve ser avaliado em dados que nao foram usados no fit.
A regressao linear e simples, interpretavel e rapida. Mesmo quando nao e o modelo final, ela serve como ponto de comparacao.
Um modelo mais complexo so vale a pena se superar esse baseline de forma consistente.
Para regressao, as metricas usadas ate agora foram adequadas:
MAE: facil de interpretar;MSE: penaliza erros grandes;RMSE: fica na escala original do target;R2: mede proporcao de variancia explicada.
A ordem recomendada e sempre:
metric(y_true, y_pred)No projeto:
metric(y_test, y_pred)Coeficientes de regressao linear sao interpretaveis, mas:
- dependem da escala das variaveis;
- podem ser afetados por multicolinearidade;
- nao representam causalidade automaticamente;
- devem ser analisados junto com residuos e metricas.
Quando os dados passam por StandardScaler, a comparacao entre coeficientes fica mais justa.
Transformacoes como scaler, encoder e imputador devem ser ajustadas apenas nos dados de treino.
O Pipeline ajuda a garantir que:
- o
fitseja feito no treino; - o
transformseja aplicado corretamente no treino e no teste; - o fluxo seja reproduzivel.
Uma categoria codificada como 1, 2 ou 3 nao necessariamente possui ordem ou distancia numerica.
Quando nao ha ordem real, o tratamento correto geralmente e OneHotEncoder.
A curva de aprendizado ajuda a responder:
- o modelo melhoraria com mais dados?
- o modelo esta sofrendo overfitting?
- o modelo esta sofrendo underfitting?
- o modelo e limitado demais para o problema?
Uma unica separacao treino/teste pode gerar uma estimativa instavel em bases pequenas. Com KFold, o modelo e avaliado em varias particoes, tornando a comparacao mais confiavel.
O retorno de cross_validate e um dicionario de arrays. Para graficos comparativos, ele deve ser convertido para DataFrame.
No projeto, essa conversao e feita por:
df_resultados = organiza_resultados(resultados)O grafico deve usar data=df_resultados, nao data=resultados.
Se o preprocessador usa colesterol_hdl_cat, a base correta e DADOS_CATEGORIZADOS.
Se a base carregada for DADOS_TRATADOS, essa coluna nao existe e o erro esperado e uma incompatibilidade entre as colunas esperadas pelo ColumnTransformer e as colunas disponiveis em X.
Lasso, Ridge e ElasticNet sao alternativas naturais depois da regressao linear porque controlam a magnitude dos coeficientes e podem melhorar generalizacao.
Mesmo assim, a decisao deve ser baseada em validacao cruzada. Um modelo mais complexo ou mais regularizado so deve substituir o baseline se entregar ganho consistente em metrica, estabilidade ou interpretabilidade.
O modelo atual e tecnicamente coerente como baseline, mas ainda limitado.
O desempenho de R2 proximo de 0.453 indica que a regressao linear captura parte da relacao entre as variaveis e o target, mas deixa uma parcela relevante da variabilidade sem explicacao.
Isso pode acontecer por alguns motivos:
- relacoes nao lineares entre variaveis e target;
- interacoes entre variaveis nao modeladas;
- ruido natural nos dados clinicos;
- limite do proprio conjunto de variaveis disponiveis;
- multicolinearidade entre variaveis metabolicas.
A etapa mais recente torna o diagnostico mais robusto ao comparar familias de modelos. O proximo passo natural seria uma busca controlada de hiperparametros para Lasso, Ridge e ElasticNet, usando validacao cruzada e mantendo o DummyRegressor e a regressao linear como referencias.