Spec-Zone.ru › scikit-learn

Примечание

Перейти к концу для скачивания полного примера кода. или для запуска этого примера в вашем браузере через 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)
Pipeline(steps=[('randomtreesembedding',
                 RandomTreesEmbedding(max_depth=3, n_estimators=10,
                                      random_state=0)),
                ('logisticregression', LogisticRegression(max_iter=1000))])
В среде Jupyter, пожалуйста, перезапустите этот ячейку, чтобы показать HTML-представление, или доверьтесь блокноту.
На GitHub HTML-представление не может быть отображено, пожалуйста, попробуйте загрузить эту страницу с nbviewer.org.
Pipeline(steps=[('randomtreesembedding',
                 RandomTreesEmbedding(max_depth=3, n_estimators=10,
                                      random_state=0)),
                ('logisticregression', LogisticRegression(max_iter=1000))])
RandomTreesEmbedding(max_depth=3, n_estimators=10, random_state=0)
LogisticRegression(max_iter=1000)


Затем, мы можем использовать конвейер случайного леса или градиентного бустинга с логистической регрессией. Однако преобразование признаков произойдёт при вызове метода 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)
Pipeline(steps=[('functiontransformer',
                 FunctionTransformer(func=<function rf_apply at 0x7656b79ddd30>,
                                     kw_args={'model': RandomForestClassifier(max_depth=3,
                                                                              n_estimators=10,
                                                                              random_state=10)})),
                ('onehotencoder', OneHotEncoder(handle_unknown='ignore')),
                ('logisticregression', LogisticRegression(max_iter=1000))])
В среде Jupyter, пожалуйста, перезапустите этот ячейку, чтобы показать HTML-представление, или доверьтесь блокноту.
На GitHub HTML-представление не может быть отображено, пожалуйста, попробуйте загрузить эту страницу с nbviewer.org.
Pipeline(steps=[('functiontransformer',
                 FunctionTransformer(func=<function rf_apply at 0x7656b79ddd30>,
                                     kw_args={'model': RandomForestClassifier(max_depth=3,
                                                                              n_estimators=10,
                                                                              random_state=10)})),
                ('onehotencoder', OneHotEncoder(handle_unknown='ignore')),
                ('logisticregression', LogisticRegression(max_iter=1000))])
FunctionTransformer(func=<function rf_apply at 0x7656b79ddd30>,
                    kw_args={'model': RandomForestClassifier(max_depth=3,
                                                             n_estimators=10,
                                                             random_state=10)})
OneHotEncoder(handle_unknown='ignore')
LogisticRegression(max_iter=1000)


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)
Pipeline(steps=[('functiontransformer',
                 FunctionTransformer(func=<function gbdt_apply at 0x7656b79ddee0>,
                                     kw_args={'model': GradientBoostingClassifier(n_estimators=10,
                                                                                  random_state=10)})),
                ('onehotencoder', OneHotEncoder(handle_unknown='ignore')),
                ('logisticregression', LogisticRegression(max_iter=1000))])
В среде Jupyter, пожалуйста, перезапустите этот ячейку, чтобы показать HTML-представление, или доверьтесь блокноту.
На GitHub HTML-представление не может быть отображено, пожалуйста, попробуйте загрузить эту страницу с nbviewer.org.
Pipeline(steps=[('functiontransformer',
                 FunctionTransformer(func=<function gbdt_apply at 0x7656b79ddee0>,
                                     kw_args={'model': GradientBoostingClassifier(n_estimators=10,
                                                                                  random_state=10)})),
                ('onehotencoder', OneHotEncoder(handle_unknown='ignore')),
                ('logisticregression', LogisticRegression(max_iter=1000))])
FunctionTransformer(func=<function gbdt_apply at 0x7656b79ddee0>,
                    kw_args={'model': GradientBoostingClassifier(n_estimators=10,
                                                                 random_state=10)})
OneHotEncoder(handle_unknown='ignore')
LogisticRegression(max_iter=1000)


Наконец, мы можем показать различные кривые 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")
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)")
ROC curve (zoomed in at top left)

Общее время выполнения скрипта: (0 минут 2.734 секунды)

Launch binder
Launch JupyterLite

Download Jupyter notebook: plot_feature_transformation.ipynb

Download Python source code: plot_feature_transformation.py

Download zipped: plot_feature_transformation.zip

Связанные примеры

Методы обучения на данных рукописных цифр: Вложение локально-линейными методами, Изомапа и…

Основные моменты выпуска scikit-learn 0.22

Регрессия на основе дерева решений

Кривая ROC с API визуализации

© 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API