Introdução
Neste laboratório, compararemos o desempenho de dois modelos de conjunto populares, Random Forest (RF) e Histogram Gradient Boosting (HGBT), para um conjunto de dados de regressão em termos de pontuação e tempo de computação. Variaremos os parâmetros que controlam o número de árvores de acordo com cada estimador e plotaremos os resultados para visualizar o trade-off entre o tempo de computação decorrido e a pontuação média de teste.
Dicas da Máquina Virtual
Após o arranque da VM, clique no canto superior esquerdo para mudar para a aba Notebook para aceder ao Jupyter Notebook para a prática.
Por vezes, pode ser necessário esperar alguns segundos para o Jupyter Notebook terminar de carregar. A validação das operações não pode ser automatizada devido a limitações no Jupyter Notebook.
Se tiver problemas durante o aprendizado, não hesite em contactar o Labby. Forneça feedback após a sessão e resolveremos prontamente o problema para si.
Carregar Conjunto de Dados
Vamos carregar o conjunto de dados de habitação da Califórnia usando a função fetch_california_housing do scikit-learn. Este conjunto de dados consiste em 20.640 amostras e 8 características.
from sklearn.datasets import fetch_california_housing
X, y = fetch_california_housing(return_X_y=True, as_frame=True)
n_samples, n_features = X.shape
print(f"O conjunto de dados consiste em {n_samples} amostras e {n_features} características")
Definir Modelos e Malhas de Parâmetros
Vamos definir dois modelos, Random Forest e Histogram Gradient Boosting, com suas respectivas malhas de parâmetros usando as classes RandomForestRegressor, HistGradientBoostingRegressor e GridSearchCV do scikit-learn. Também definiremos o número de núcleos físicos da máquina hospedeira a usar para processamento paralelo.
import joblib
import pandas as pd
from sklearn.ensemble import HistGradientBoostingRegressor, RandomForestRegressor
from sklearn.model_selection import GridSearchCV, KFold
N_CORES = joblib.cpu_count(only_physical_cores=True)
models = {
"Random Forest": RandomForestRegressor(
min_samples_leaf=5, random_state=0, n_jobs=N_CORES
),
"Hist Gradient Boosting": HistGradientBoostingRegressor(
max_leaf_nodes=15, random_state=0, early_stopping=False
),
}
param_grids = {
"Random Forest": {"n_estimators": [10, 20, 50, 100]},
"Hist Gradient Boosting": {"max_iter": [10, 20, 50, 100, 300, 500]},
}
cv = KFold(n_splits=4, shuffle=True, random_state=0)
results = []
for name, model in models.items():
grid_search = GridSearchCV(
estimator=model,
param_grid=param_grids[name],
return_train_score=True,
cv=cv,
).fit(X, y)
result = {"model": name, "cv_results": pd.DataFrame(grid_search.cv_results_)}
results.append(result)
Calcular Pontuações e Tempos de Computação
Vamos calcular os tempos médios de ajuste e pontuação para cada combinação de hiperparâmetros usando o atributo cv_results_ do objeto GridSearchCV. Em seguida, plotaremos os resultados usando plotly.express.scatter e plotly.express.line para visualizar o trade-off entre o tempo de computação decorrido e a pontuação média de teste.
import plotly.express as px
import plotly.colors as colors
from plotly.subplots import make_subplots
fig = make_subplots(
rows=1,
cols=2,
shared_yaxes=True,
subplot_titles=["Tempo de treinamento vs pontuação", "Tempo de predição vs pontuação"],
)
model_names = [result["model"] for result in results]
colors_list = colors.qualitative.Plotly * (
len(model_names) // len(colors.qualitative.Plotly) + 1
)
for idx, result in enumerate(results):
cv_results = result["cv_results"].round(3)
model_name = result["model"]
param_name = list(param_grids[model_name].keys())[0]
cv_results[param_name] = cv_results["param_" + param_name]
cv_results["model"] = model_name
scatter_fig = px.scatter(
cv_results,
x="mean_fit_time",
y="mean_test_score",
error_x="std_fit_time",
error_y="std_test_score",
hover_data=param_name,
color="model",
)
line_fig = px.line(
cv_results,
x="mean_fit_time",
y="mean_test_score",
)
scatter_trace = scatter_fig["data"][0]
line_trace = line_fig["data"][0]
scatter_trace.update(marker=dict(color=colors_list[idx]))
line_trace.update(line=dict(color=colors_list[idx]))
fig.add_trace(scatter_trace, row=1, col=1)
fig.add_trace(line_trace, row=1, col=1)
scatter_fig = px.scatter(
cv_results,
x="mean_score_time",
y="mean_test_score",
error_x="std_score_time",
error_y="std_test_score",
hover_data=param_name,
)
line_fig = px.line(
cv_results,
x="mean_score_time",
y="mean_test_score",
)
scatter_trace = scatter_fig["data"][0]
line_trace = line_fig["data"][0]
scatter_trace.update(marker=dict(color=colors_list[idx]))
line_trace.update(line=dict(color=colors_list[idx]))
fig.add_trace(scatter_trace, row=1, col=2)
fig.add_trace(line_trace, row=1, col=2)
fig.update_layout(
xaxis=dict(title="Tempo de treinamento (s) - menor é melhor"),
yaxis=dict(title="Pontuação R2 de teste - maior é melhor"),
xaxis2=dict(title="Tempo de predição (s) - menor é melhor"),
legend=dict(x=0.72, y=0.05, traceorder="normal", borderwidth=1),
title=dict(x=0.5, text="Trade-off entre velocidade e pontuação de conjuntos de árvores"),
)
Interpretar Resultados
Podemos observar que ambos os modelos HGBT e RF melhoram ao aumentar o número de árvores no conjunto. No entanto, as pontuações atingem um platô onde adicionar novas árvores apenas torna o ajuste e a pontuação mais lentos. O modelo RF atinge esse platô mais cedo e nunca consegue alcançar a pontuação de teste do modelo HGBDT maior. Os modelos HGBT dominam uniformemente os modelos RF no "trade-off entre pontuação de teste e velocidade de treinamento" e o "trade-off entre pontuação de teste e velocidade de predição" também pode ser mais favorável aos HGBT. O HGBT quase sempre oferece um trade-off velocidade-precisão mais favorável do que o RF, seja com os hiperparâmetros padrão ou incluindo o custo de ajuste de hiperparâmetros.
Resumo
Neste laboratório, comparamos o desempenho de dois modelos de conjunto populares, Floresta Aleatória e Reforço de Gradiente Histograma, para um conjunto de dados de regressão em termos de pontuação e tempo de computação. Variamos os parâmetros que controlam o número de árvores de acordo com cada estimador e plotamos os resultados para visualizar o trade-off entre o tempo de computação decorrido e a pontuação média de teste. Observamos que os modelos HGBT dominam uniformemente os modelos RF no "trade-off entre pontuação de teste e velocidade de treinamento" e o "trade-off entre pontuação de teste e velocidade de predição" também pode ser mais favorável aos HGBT. O HGBT quase sempre oferece um trade-off velocidade-precisão mais favorável do que o RF, seja com os hiperparâmetros padrão ou incluindo o custo de ajuste de hiperparâmetros.