Примечание
Перейти к концу для скачивания полного примера кода. или для запуска этого примера в вашем браузере через JupyterLite или Binder
Преобразования признаков с помощью ансамблей деревьев
Преобразуйте свои признаки в более высокое, разреженное пространство. Затем обучите линейную модель на этих признаках.
Сначала обучите ансамбль деревьев (полностью случайные деревья, случайный лес или градиентный бустинг) на обучающем наборе. Затем каждому листу каждого дерева в ансамбле присваивается фиксированный произвольный индекс признака в новом пространстве признаков. Эти индексы листов затем кодируются в виде one-hot.
Каждая выборка проходит через решения каждого дерева ансамбля и попадает в один лист на дерево. Выборка кодируется путем задания значений признаков для этих листов в 1, а других значений признаков — в 0.
Полученный трансформер выучил контролируемую, разреженную, многомерную категориальную встраиваемость данных.
# Authors: The scikit-learn developers # SPDX-License-Identifier: BSD-3-Clause
Сначала мы создадим большой набор данных и разделим его на три набора:
- набор для обучения методов ансамбля, которые впоследствии используются в качестве трансформера обработки признаков;
- набор для обучения линейной модели;
- набор для тестирования линейной модели.
Важно разделить данные таким образом, чтобы избежать переобучения, не нарушая целостность данных.
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
X, y = make_classification(n_samples=80_000, random_state=10)
X_full_train, X_test, y_full_train, y_test = train_test_split(
X, y, test_size=0.5, random_state=10
)
X_train_ensemble, X_train_linear, y_train_ensemble, y_train_linear = train_test_split(
X_full_train, y_full_train, test_size=0.5, random_state=10
)
Для каждого из методов ансамбля мы будем использовать 10 оценщиков и максимальную глубину 3 уровня.
n_estimators = 10 max_depth = 3
Сначала мы начнём с обучения случайного леса и градиентного бустинга на отделённом обучающем наборе
from sklearn.ensemble import GradientBoostingClassifier, RandomForestClassifier
random_forest = RandomForestClassifier(
n_estimators=n_estimators, max_depth=max_depth, random_state=10
)
random_forest.fit(X_train_ensemble, y_train_ensemble)
gradient_boosting = GradientBoostingClassifier(
n_estimators=n_estimators, max_depth=max_depth, random_state=10
)
_ = gradient_boosting.fit(X_train_ensemble, y_train_ensemble)
Обратите внимание, что HistGradientBoostingClassifier намного быстрее, чем GradientBoostingClassifier начиная со средних наборов данных (n_samples >= 10_000), что не относится к данному примеру.
Метод RandomTreesEmbedding является неконтролируемым методом и, следовательно, не требует независимого обучения.
from sklearn.ensemble import RandomTreesEmbedding
random_tree_embedding = RandomTreesEmbedding(
n_estimators=n_estimators, max_depth=max_depth, random_state=0
)
Теперь мы создадим три конвейера, которые будут использовать описанную выше встраиваемость в качестве предварительной стадии обработки.
Встраиваемость случайных деревьев можно напрямую использовать в конвейере с логистической регрессией, так как это стандартный трансформер scikit-learn.
from sklearn.linear_model import LogisticRegression from sklearn.pipeline import make_pipeline rt_model = make_pipeline(random_tree_embedding, LogisticRegression(max_iter=1000)) rt_model.fit(X_train_linear, y_train_linear)
Затем, мы можем использовать конвейер случайного леса или градиентного бустинга с логистической регрессией. Однако преобразование признаков произойдёт при вызове метода apply. Конвейер в scikit-learn ожидает вызов transform. Поэтому мы обернули вызов apply в FunctionTransformer.
from sklearn.preprocessing import FunctionTransformer, OneHotEncoder
def rf_apply(X, model):
return model.apply(X)
rf_leaves_yielder = FunctionTransformer(rf_apply, kw_args={"model": random_forest})
rf_model = make_pipeline(
rf_leaves_yielder,
OneHotEncoder(handle_unknown="ignore"),
LogisticRegression(max_iter=1000),
)
rf_model.fit(X_train_linear, y_train_linear)
def gbdt_apply(X, model):
return model.apply(X)[:, :, 0]
gbdt_leaves_yielder = FunctionTransformer(
gbdt_apply, kw_args={"model": gradient_boosting}
)
gbdt_model = make_pipeline(
gbdt_leaves_yielder,
OneHotEncoder(handle_unknown="ignore"),
LogisticRegression(max_iter=1000),
)
gbdt_model.fit(X_train_linear, y_train_linear)
Наконец, мы можем показать различные кривые ROC для всех моделей.
import matplotlib.pyplot as plt
from sklearn.metrics import RocCurveDisplay
_, ax = plt.subplots()
models = [
("RT embedding -> LR", rt_model),
("RF", random_forest),
("RF embedding -> LR", rf_model),
("GBDT", gradient_boosting),
("GBDT embedding -> LR", gbdt_model),
]
model_displays = {}
for name, pipeline in models:
model_displays[name] = RocCurveDisplay.from_estimator(
pipeline, X_test, y_test, ax=ax, name=name
)
_ = ax.set_title("ROC curve")

_, ax = plt.subplots()
for name, pipeline in models:
model_displays[name].plot(ax=ax)
ax.set_xlim(0, 0.2)
ax.set_ylim(0.8, 1)
_ = ax.set_title("ROC curve (zoomed in at top left)")

Общее время выполнения скрипта: (0 минут 2.734 секунды)
Связанные примеры
© 2007–2025 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.6/auto_examples/ensemble/plot_feature_transformation.html