TargetEncoder を使用したカテゴリデータの変換

Beginner

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

はじめに

この実験では、Scikit-learn ライブラリの TargetEncoder クラスの使い方を学びます。ターゲットエンコーディングは、カテゴリデータを機械学習アルゴリズムの入力として使用できる数値データに変換する手法です。TargetEncoder は、カテゴリ特徴量の各カテゴリを、そのカテゴリに対するターゲット変数の平均値で置き換えます。この方法は、カテゴリ特徴量とターゲットとの間に強い関係がある場合に役立ちます。

VM のヒント

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

合成データセットの作成

この実験では、3 つのカテゴリ特徴量を持つ合成データセットを作成します。具体的には、中程度のカーディナリティを持つ有益な特徴量、中程度のカーディナリティを持つ無益な特徴量、および高いカーディナリティを持つ無益な特徴量です。有益な特徴量の生成には、Scikit-learn の KBinsDiscretizer クラスを使用します。以下のコードを実行して、合成データセットを作成してください。

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 回帰モデルを学習させ、区間交差検証(interval cross-validation)の有無によるターゲットエンコーダの影響を調べます。まず、生の特徴量で 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 回帰モデルを学習させる

次に、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 は区間交差検証(interval cross-validation)を使用しますが、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 モデルは、有益な特徴量に比べてカーディナリティが非常に高い特徴量により多くの重みを割り当てるため、過学習(overfit)します。以下のコードを実行して、交差検証を用いない線形モデルの係数を評価してください。

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

まとめ

この実験では、Scikit-learn の TargetEncoder クラスを使用してカテゴリデータを機械学習アルゴリズムの入力として使用できる数値データに変換する方法を学びました。また、過学習を防ぐための区間交差検証(interval cross-validation)の重要性も学びました。生データに対して Ridge モデルを学習させ、その性能を評価しました。交差検証を用いて Ridge モデルを学習させ、線形モデルの係数を評価しました。最後に、交差検証を用いずに Ridge モデルを学習させ、線形モデルの係数を評価しました。