Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

1
resposta

[Projeto] Faça como eu fiz: ajustando modelos de machine learning

Decidi explorar um pouco mais, adicionar novos modelos e formas de avaliar e comaprar resultados com um pouco de IA no processo.
Foi um pouco demorado pra rodar mesmo no colab.
Acredito que deu pra compreender melhor a combinação
Lembrando que California Housing é um problema de regressão

#==
# Ensemble Learning - California Housing
# Random Forest + Gradient Boosting + Extra Trees + AdaBoost
# Ensemble por Média + Stacking
#==

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

from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split

from sklearn.ensemble import (
    RandomForestRegressor,
    GradientBoostingRegressor,
    ExtraTreesRegressor,
    AdaBoostRegressor,
    StackingRegressor
)

from sklearn.linear_model import LinearRegression

from sklearn.metrics import (
    mean_squared_error,
    r2_score
)

#==
# Passo 1 - Carregar dataset
#==

california = fetch_california_housing()

df = pd.DataFrame(california.data, columns=california.feature_names)
df["PRICE"] = california.target
display(df.head())

#==
# Passo 2 - Separar atributos e alvo
#==

X = df.drop("PRICE", axis=1)
y = df["PRICE"]

#==
# Passo 3 - Dividir treino e teste
#==

X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.30, random_state=42)

#==
# Passo 4 - Criar modelos ensemble
#==

rf_model = RandomForestRegressor(
    n_estimators=200,
    max_depth=10,
    random_state=42,
    n_jobs=-1
)

gb_model = GradientBoostingRegressor(
    n_estimators=200,
    learning_rate=0.05,
    max_depth=5,
    random_state=42
)

et_model = ExtraTreesRegressor(
    n_estimators=200,
    max_depth=10,
    random_state=42,
    n_jobs=-1
)

ada_model = AdaBoostRegressor(
    n_estimators=200,
    learning_rate=0.05,
    random_state=42
)

#==
# Passo 5 - Treinar modelos
#==

rf_model.fit(X_train, y_train)
gb_model.fit(X_train, y_train)
et_model.fit(X_train, y_train)
ada_model.fit(X_train, y_train)

#==
# Passo 6 - Fazer previsões
#==

y_pred_rf = rf_model.predict(X_test)
y_pred_gb = gb_model.predict(X_test)
y_pred_et = et_model.predict(X_test)
y_pred_ada = ada_model.predict(X_test)

#==
# Passo 7 - Ensemble por média
#==

y_pred_ensemble = (
    y_pred_rf +
    y_pred_gb +
    y_pred_et +
    y_pred_ada
) / 4

#==
# Passo 8 - Stacking Ensemble
#==

stacking_model = StackingRegressor(
    estimators=[
        ("rf", rf_model),
        ("gb", gb_model),
        ("et", et_model),
        ("ada", ada_model)
    ],
    final_estimator=LinearRegression(),
    n_jobs=-1
)

stacking_model.fit(X_train, y_train)

y_pred_stack = stacking_model.predict(X_test)

#==
# Passo 9 - Avaliação
#==

modelos = {
    "Random Forest": y_pred_rf,
    "Gradient Boosting": y_pred_gb,
    "Extra Trees": y_pred_et,
    "AdaBoost": y_pred_ada,
    "Ensemble Média": y_pred_ensemble,
    "Stacking": y_pred_stack
}

resultados = []

print("=" * 70)

for nome, pred in modelos.items():

    mse = mean_squared_error(y_test, pred)
    rmse = np.sqrt(mse)
    r2 = r2_score(y_test, pred)

    resultados.append({
        "Modelo": nome,
        "MSE": mse,
        "RMSE": rmse,
        "R2": r2
    })

    print(f"{nome}")
    print(f"MSE  : {mse:.4f}")
    print(f"RMSE : {rmse:.4f}")
    print(f"R²   : {r2:.4f}")
    print("-" * 70)

#==
# Passo 10 - Tabela de resultados
#==

df_resultados = pd.DataFrame(resultados)

display(
    df_resultados.sort_values(
        by="R2",
        ascending=False
    )
)

#==
# Passo 11 - Comparação dos modelos
#==

plt.figure(figsize=(10, 6))

sns.barplot(
    data=df_resultados.sort_values(
        by="R2",
        ascending=False
    ),
    x="Modelo",
    y="R2"
)

plt.title("Comparação dos Modelos Ensemble")
plt.ylabel("R²")
plt.xlabel("Modelo")
plt.xticks(rotation=20)

plt.show()

#==
# Passo 12 - Melhor modelo (maior R²)
#==

melhor_modelo = df_resultados.loc[
    df_resultados["R2"].idxmax()
]

print("\nMelhor Modelo:")
print(melhor_modelo)

#==
# Passo 13 - Dispersão Real x Previsto (Stacking)
#==

plt.figure(figsize=(8, 6))

sns.scatterplot(
    x=y_test,
    y=y_pred_stack,
    alpha=0.5
)

plt.plot(
    [y_test.min(), y_test.max()],
    [y_test.min(), y_test.max()],
    "--r",
    linewidth=2
)

plt.xlabel("Valores Reais")
plt.ylabel("Valores Preditos")
plt.title("Stacking - Real vs Previsto")

plt.show()
1 resposta

Oii Marcelo, tudo bem?

Obrigada por compartilhar seu projeto aqui no fórum! Com certeza vai ajudar outros alunos que passarem por essa atividade.

Foi uma ótima iniciativa ir além do exercício e montar um pipeline completo de Ensemble Learning, comparando quatro modelos base mais dois métodos de combinação (média simples e Stacking). A escolha de usar o StackingRegressor com LinearRegression como meta-estimador é bem representativa do que Stacking propõe na prática: deixar um modelo aprender os pesos ideais de cada base learner em vez de simplesmente fazer a média.

Um detalhe que vale notar: ao criar o StackingRegressor passando os modelos já treinados (rf_model, gb_model, etc.), o Scikit-learn vai retreiná-los internamente com cross-validation para gerar as previsões do meta-estimador. Então o tempo de execução mais longo no Colab faz todo sentido. Uma alternativa para reduzir esse tempo em experimentos futuros é ajustar o parâmetro cv do StackingRegressor (por padrão são 5 folds), usando por exemplo cv=3.

Parabéns por ter ido além do proposto e por ter incluído a visualização de dispersão Real x Previsto no Stacking, que é uma forma clara de enxergar onde o modelo ainda escorrega nos valores extremos.

Conte com a Alura para evoluir seus estudos. Em caso de dúvidas, fico à disposição.

Bons estudos!

Sucesso

Imagem da comunidade