Примечание
Перейти к концу, чтобы загрузить полный код примера. Или запустить этот пример в браузере через JupyterLite или Binder
Сравнение моделей случайных лесов и градиентного бустинга с гистограммами
В этом примере мы сравниваем производительность моделей случайного леса (RF) и градиентного бустинга с гистограммами (HGBT) по показателю качества и времени вычислений для регрессионного набора данных, хотя все представленные здесь концепции также применимы к задачам классификации.
Сравнение проводится путем изменения параметров, которые контролируют количество деревьев в каждом оценщике:
-
n_estimatorsуправляет количеством деревьев в лесу. Это фиксированное число. -
max_iter— максимальное количество итераций в модели градиентного бустинга. Количество итераций соответствует количеству деревьев для регрессионных и бинарных задач классификации. Более того, фактическое количество деревьев, необходимое модели, зависит от критериев остановки.
HGBT использует градиентный бустинг для итеративного улучшения производительности модели путем подгонки каждого дерева к отрицательному градиенту функции потерь по отношению к предсказанному значению. Случайные леса, с другой стороны, основаны на агрегации и используют метод большинства голосов для прогнозирования результата.
См. Руководство пользователя для получения дополнительной информации о моделях ансамбля или Характеристики деревьев градиентного бустинга с гистограммами для примера, демонстрирующего некоторые другие особенности моделей HGBT.
# Authors: The scikit-learn developers # SPDX-License-Identifier: BSD-3-Clause
Загрузка набора данных
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
HGBT использует алгоритм на основе гистограмм для значений признаков, сгруппированных в бины, который может эффективно обрабатывать большие наборы данных (десятки тысяч и более примеров) с высоким числом признаков (см. Почему это быстрее). Реализация случайного леса scikit-learn не использует бинирование и полагается на точное деление, что может быть вычислительно затратно.
print(f"The dataset consists of {n_samples} samples and {n_features} features")
The dataset consists of 20640 samples and 8 features
Вычисление показателя качества и временных затрат
Обратите внимание, что многие части реализации HistGradientBoostingClassifier и HistGradientBoostingRegressor по умолчанию выполняются параллельно.
Реализация RandomForestRegressor и RandomForestClassifier также может выполняться на нескольких ядрах с использованием параметра n_jobs, здесь установленного в соответствии с количеством физических ядер на хост-машине. См. Параллелизм для получения дополнительной информации.
import joblib
N_CORES = joblib.cpu_count(only_physical_cores=True)
print(f"Number of physical cores: {N_CORES}")
Number of physical cores: 2
В отличие от случайных лесов, модели HGBT предлагают возможность ранней остановки (см. Ранняя остановка в градиентном бустинге), чтобы избежать добавления лишних деревьев. Внутренне алгоритм использует набор вне выборки для вычисления обобщающей производительности модели на каждой итерации добавления дерева. Таким образом, если обобщающая производительность не улучшается в течение более чем n_iter_no_change итераций, добавление деревьев прекращается.
Другие параметры обеих моделей были настроены, но этот процесс здесь не показан для упрощения примера.
import pandas as pd
from sklearn.ensemble import HistGradientBoostingRegressor, RandomForestRegressor
from sklearn.model_selection import GridSearchCV, KFold
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)
Примечание
Настройка параметра n_estimators для случайного леса, как правило, приводит к пустой трате компьютерных ресурсов. На практике достаточно убедиться, что его значение достаточно велико, чтобы удвоение значения не приводило к значительному улучшению показателя качества тестирования.
Вывод результатов
Мы можем использовать plotly.express.scatter для визуализации компромисса между затраченным вычислительным временем и средним показателем качества тестирования. Наведение курсора на точку отображает соответствующие параметры. Погрешности соответствуют одному стандартному отклонению, рассчитанному в разных слоях перекрестной проверки.
import plotly.colors as colors
import plotly.express as px
from plotly.subplots import make_subplots
fig = make_subplots(
rows=1,
cols=2,
shared_yaxes=True,
subplot_titles=["Train time vs score", "Predict time vs score"],
)
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="Train time (s) - lower is better"),
yaxis=dict(title="Test R2 score - higher is better"),
xaxis2=dict(title="Predict time (s) - lower is better"),
legend=dict(x=0.72, y=0.05, traceorder="normal", borderwidth=1),
title=dict(x=0.5, text="Speed-score trade-off of tree-based ensembles"),
)
Как модели HGBT, так и модели случайного леса улучшаются при увеличении количества деревьев в ансамбле. Однако показатели достигают плато, где добавление новых деревьев только замедляет подгонку и оценку. Модель случайного леса достигает такого плато раньше и никогда не может достичь показателя качества модели крупнейшего HGBDT.
Обратите внимание, что результаты, показанные на приведенном выше графике, могут незначительно изменяться при разных запусках и еще более значительно при запуске на других машинах: попробуйте запустить этот пример на своей локальной машине.
В целом, часто наблюдается, что модели градиентного бустинга на основе гистограмм однозначно доминируют над моделями случайных лесов в «компромиссе показателя качества тестирования и скорости обучения» (кривая HGBDT должна находиться в левом верхнем углу кривой RF, но никогда не пересекать ее). «Компромисс показателя качества тестирования и скорости предсказания» также может быть более спорным, но чаще всего он благоприятствует HGBDT. Всегда рекомендуется проверить оба типа моделей (с настройкой гиперпараметров) и сравнить их производительность в вашей конкретной задаче, чтобы определить, какая модель лучше всего подходит, но HGBT почти всегда обеспечивает более благоприятный компромисс между скоростью и точностью, чем RF, как с параметрами по умолчанию, так и с учетом затрат на настройку гиперпараметров.
Однако есть одно исключение из этого правила: при обучении модели многоклассовой классификации с большим количеством возможных классов HGBDT внутренне подгоняет по одному дереву на каждый класс на каждой итерации бустинга, в то время как деревья, используемые в моделях RF, по своей природе многоклассовые, что должно улучшить компромисс между скоростью и точностью моделей RF в этом случае.
Общее время выполнения скрипта: (0 минут 56.419 секунд)
Связанные примеры
© 2007–2025 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.6/auto_examples/ensemble/plot_forest_hist_grad_boosting_comparison.html