Преобразование категориальных данных с использованием TargetEncoder

Beginner

This tutorial is from open-source community. Access the source code

Введение

В этом лабораторном занятии мы научимся использовать класс TargetEncoder из библиотеки Scikit-learn. Целевое кодирование (target encoding) — это техника, используемая для преобразования категориальных данных в числовые, которые могут быть использованы в качестве входных данных для алгоритмов машинного обучения. Класс TargetEncoder заменяет каждую категорию категориального признака средним значением целевой переменной для этой категории. Этот метод полезен в случаях, когда между категориальным признаком и целевой переменной существует сильная связь.

Советы по виртуальной машине

После запуска виртуальной машины (VM) нажмите в левом верхнем углу, чтобы переключиться на вкладку Notebook и получить доступ к Jupyter Notebook для практики.

Иногда вам может потребоваться подождать несколько секунд, пока Jupyter Notebook загрузится. Валидация операций не может быть автоматизирована из-за ограничений Jupyter Notebook.

Если у вас возникнут проблемы во время обучения, не стесняйтесь обращаться к Labby. После занятия дайте обратную связь, и мы оперативно решим проблему для вас.

Установка необходимых библиотек

Сначала нам нужно установить необходимые библиотеки. Мы будем использовать библиотеки Scikit-learn, Pandas и Matplotlib. Выполните следующую команду для установки этих библиотек:

!pip install scikit-learn pandas matplotlib

Импорт необходимых библиотек

Далее нам нужно импортировать необходимые библиотеки. Выполните следующий код для импорта требуемых библиотек:

import numpy as np
import pandas as pd
from sklearn.preprocessing import KBinsDiscretizer, TargetEncoder
from sklearn.linear_model import Ridge
from sklearn.pipeline import make_pipeline
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt

Создание синтетического набора данных

В этом лабораторном занятии мы создадим синтетический набор данных с тремя категориальными признаками: информативным признаком со средней мощностью (cardinality), неинформативным признаком со средней мощностью и неинформативным признаком с высокой мощностью. Мы будем использовать класс KBinsDiscretizer из библиотеки Scikit-learn для генерации информативного признака. Выполните следующий код для создания синтетического набора данных:

n_samples = 50_000

rng = np.random.RandomState(42)
y = rng.randn(n_samples)
noise = 0.5 * rng.randn(n_samples)
n_categories = 100

kbins = KBinsDiscretizer(
    n_bins=n_categories, encode="ordinal", strategy="uniform", random_state=rng
)
X_informative = kbins.fit_transform((y + noise).reshape(-1, 1))

permuted_categories = rng.permutation(n_categories)
X_informative = permuted_categories[X_informative.astype(np.int32)]

X_shuffled = rng.permutation(X_informative)

X_near_unique_categories = rng.choice(
    int(0.9 * n_samples), size=n_samples, replace=True
).reshape(-1, 1)

X = pd.DataFrame(
    np.concatenate(
        [X_informative, X_shuffled, X_near_unique_categories],
        axis=1,
    ),
    columns=["informative", "shuffled", "near_unique"],
)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)

Обучение регрессора Ridge на исходных данных

В этом разделе мы обучим регрессор Ridge на наборе данных с и без кодирования и исследуем влияние целевого кодировщика (target encoder) с и без интервального кросс-валидации. Сначала мы обучим модель Ridge на исходных признаках. Выполните следующий код для обучения модели Ridge:

ridge = Ridge(alpha=1e-6, solver="lsqr", fit_intercept=False)

raw_model = ridge.fit(X_train, y_train)
print("Raw Model score on training set: ", raw_model.score(X_train, y_train))
print("Raw Model score on test set: ", raw_model.score(X_test, y_test))

Обучение регрессора Ridge с кросс-валидацией

Далее мы создадим конвейер (pipeline) с TargetEncoder и моделью Ridge. Конвейер использует TargetEncoder.fit_transform, который применяет кросс-валидацию. Выполните следующий код для обучения модели Ridge с кросс-валидацией:

model_with_cv = make_pipeline(TargetEncoder(random_state=0), ridge)
model_with_cv.fit(X_train, y_train)
print("Model with CV on training set: ", model_with_cv.score(X_train, y_train))
print("Model with CV on test set: ", model_with_cv.score(X_test, y_test))

Оценка коэффициентов линейной модели с кросс-валидацией

Коэффициенты линейной модели показывают, что основная часть веса приходится на признак с индексом столбца 0, который является информативным признаком. Выполните следующий код для оценки коэффициентов линейной модели с кросс-валидацией:

coefs_cv = pd.Series(
    model_with_cv[-1].coef_, index=model_with_cv[-1].feature_names_in_
).sort_values()
_ = coefs_cv.plot(kind="barh")

Обучение регрессора Ridge без кросс-валидации

В то время как TargetEncoder.fit_transform использует интервальную кросс-валидацию, сам метод TargetEncoder.transform не выполняет никакой кросс-валидации. Он использует агрегацию всего обучающего набора данных для преобразования категориальных признаков. Таким образом, мы можем использовать TargetEncoder.fit с последующим вызовом TargetEncoder.transform для отключения кросс-валидации. Затем это закодированное представление передается модели Ridge. Выполните следующий код для обучения модели Ridge без кросс-валидации:

target_encoder = TargetEncoder(random_state=0)
target_encoder.fit(X_train, y_train)
X_train_no_cv_encoding = target_encoder.transform(X_train)
X_test_no_cv_encoding = target_encoder.transform(X_test)

model_no_cv = ridge.fit(X_train_no_cv_encoding, y_train)
print(
    "Model without CV on training set: ",
    model_no_cv.score(X_train_no_cv_encoding, y_train),
)
print(
    "Model without CV on test set: ", model_no_cv.score(X_test_no_cv_encoding, y_test)
)

Оценка коэффициентов линейной модели без кросс-валидации

Модель Ridge переобучается, так как она придает больший вес признаку с чрезвычайно высокой мощностью (cardinality) по сравнению с информативным признаком. Выполните следующий код для оценки коэффициентов линейной модели без кросс-валидации:

coefs_no_cv = pd.Series(
    model_no_cv.coef_, index=model_no_cv.feature_names_in_
).sort_values()
_ = coefs_no_cv.plot(kind="barh")

Резюме

В этом практическом занятии (lab) мы научились использовать класс TargetEncoder из библиотеки Scikit-learn для преобразования категориальных данных в числовые данные, которые могут быть использованы в качестве входных данных для алгоритмов машинного обучения. Мы также узнали о важности интервальной кросс-валидации для предотвращения переобучения. Мы обучили модель Ridge на исходных данных и оценили ее производительность. Мы также обучили модель Ridge с использованием кросс-валидации и оценили коэффициенты линейной модели. Наконец, мы обучили модель Ridge без кросс-валидации и оценили коэффициенты линейной модели.