カテゴリ変数エンコーディング4手法 ~ ワンホット、ラベル、ターゲット、Embedding ~

解説

機械学習モデルにおいて、カテゴリ変数の扱いは非常に重要です。
今回は、以下の4つの手法について、その直感的な考え方、メリット・デメリット、どのようなモデルや状況に適しているかを解説し、実際の実装コードも交えてご紹介します。

  1. ワンホットエンコーディング (One-Hot Encoding)
  2. ラベルエンコーディング (Label Encoding)
  3. ターゲットエンコーディング (Target Encoding)
  4. Embedding (埋め込み表現)

ワンホットエンコーディング (One-Hot Encoding)

概要と直感的な説明

ワンホットエンコーディングは、カテゴリごとに新たな二値の特徴量を作成する手法です。たとえば、「色」が「赤」「青」「緑」の場合、各サンプルは

  • 赤:[1, 0, 0]
  • 青:[0, 1, 0]
  • 緑:[0, 0, 1]
    と表現されます。これにより、カテゴリ間の序列関係を与えずに、各カテゴリを平等な次元で表現できます。

メリット・デメリット

  • メリット:
    • 単純で理解しやすい。
    • 順序情報を誤って導入しない(カテゴリ間に序列がない場合に有効)。
  • デメリット:
    • カテゴリ数が多い場合、次元が爆発的に増加する(高次元のスパース行列となる)。
    • 多くのモデルで効率的に扱えない場合がある。

適用例

  • 木構造系のモデル(ランダムフォレスト、GBDTなど)では、ワンホットエンコーディングで十分な場合が多い。
  • カテゴリ数が少なく、かつ各カテゴリに意味的な差がある場合に有効。

実装コード例(pandas を使用)

Python
import pandas as pd

# サンプルデータ
df = pd.DataFrame({'color': ['red', 'blue', 'green', 'blue', 'red']})
print("元データ:")
print(df)

# pandasのget_dummiesを利用したワンホットエンコーディング
one_hot_df = pd.get_dummies(df, columns=['color'])
print("ワンホットエンコーディング後:")
print(one_hot_df)

2. ラベルエンコーディング (Label Encoding)

概要と直感的な説明

ラベルエンコーディングは、各カテゴリに数値(整数)を割り当てるシンプルな手法です。たとえば、「色」が「赤」「青」「緑」の場合、

  • 赤 → 0
  • 青 → 1
  • 緑 → 2
    といった具合に変換します。ただし、この方法では数値に順序関係が暗黙的に含まれてしまうため、モデルによっては誤解釈される可能性があります。

メリット・デメリット

  • メリット:
    • 実装が非常に簡単で、データの次元数が増えない。
    • 木構造のモデルではこれで問題ない。
  • デメリット:
    • 数値に順序があるように誤認識されるリスクがある(線形モデルなど)。
    • カテゴリ間の類似度情報が失われる。

適用例

  • 決定木系のモデル(GBDT、ランダムフォレストなど)は、ラベルエンコーディングに対して比較的ロバストである場合が多い。
  • カテゴリ数が非常に多い場合、次元削減のために使用されることがある。

実装コード例(scikit-learn の LabelEncoder を使用)

Python
from sklearn.preprocessing import LabelEncoder
import pandas as pd

# サンプルデータ
df = pd.DataFrame({'color': ['red', 'blue', 'green', 'blue', 'red']})
print("元データ:")
print(df)

# LabelEncoderの使用
le = LabelEncoder()
df['color_encoded'] = le.fit_transform(df['color'])
print("ラベルエンコーディング後:")
print(df)

ターゲットエンコーディング (Target Encoding)

概要と直感的な説明

ターゲットエンコーディングは、カテゴリごとの統計量(例えば目的変数の平均など)でカテゴリ変数を置き換える手法です。例えば、店舗ごとの売上データがある場合、各店舗の平均売上でその店舗のカテゴリを表現することで、直接的な数値情報を与えることができます。また、スムージングを適用することで、サンプル数が少ないカテゴリに対する過学習を抑制します。

メリット・デメリット

  • メリット:
    • 目的変数に対する強い情報を反映でき、予測精度の向上に寄与する場合がある。
    • 特にGBDTなどの数値特徴量を重視するモデルに有効。
  • デメリット:
    • データリークのリスクがあるため、クロスバリデーションやネストしたfoldを用いた厳密な実装が必要。

適用例

  • 回帰や分類タスクで、カテゴリ変数と目的変数に強い関連がある場合。
  • 特に、GBDTや線形モデルなど数値特徴量として扱えるモデルに対して有効。

実装コード例(シンプルな例)

Python
import pandas as pd
import numpy as np
from sklearn.model_selection import KFold

# サンプルデータ
df = pd.DataFrame({
    'store': ['A', 'B', 'A', 'C', 'B', 'A', 'C', 'B', 'C', 'A'],
    'sales': [100, 150, 200, 80, 170, 130, 90, 160, 85, 110]
})

def target_encode(train, target_col, cat_col, smoothing=10, n_splits=5):
    # 新たなカラム名
    new_col = f"{cat_col}_target_mean"
    train[new_col] = np.nan
    global_mean = train[target_col].mean()
    kf = KFold(n_splits=n_splits, shuffle=True, random_state=42)
    
    for train_idx, val_idx in kf.split(train):
        train_fold = train.iloc[train_idx]
        val_fold = train.iloc[val_idx]
        mapping = train_fold.groupby(cat_col)[target_col].agg(['mean', 'count']).reset_index()
        mapping['target_mean'] = (mapping['count'] * mapping['mean'] + smoothing * global_mean) / (mapping['count'] + smoothing)
        val_fold = val_fold.merge(mapping[[cat_col, 'target_mean']], on=cat_col, how='left')
        train.loc[val_idx, new_col] = val_fold['target_mean']
    return train

encoded_df = target_encode(df.copy(), target_col='sales', cat_col='store', smoothing=10, n_splits=5)
print("ターゲットエンコーディング後:")
print(encoded_df)

Embedding (埋め込み表現)

概要と直感的な説明

Embeddingは、カテゴリ変数を低次元の連続ベクトルに変換する手法です。特にディープラーニングモデル(例えばRNN、Transformer、CNN)では、学習可能な埋め込み層を用いて、各カテゴリを密なベクトル表現に変換します。
この手法は、カテゴリ間の意味的な類似性を学習することが可能であり、表現学習の一環として利用されます。

メリット・デメリット

  • メリット:
    • 低次元の連続表現で表現できるため、メモリ効率が良い。
    • カテゴリ間の類似度や関係性を学習できる。
    • ディープラーニングモデルと相性が良い。
  • デメリット:
    • 学習データが少ない場合、十分な表現を学習できない可能性がある。
    • ハイパーパラメータ(埋め込み次元数)の調整が必要。

適用例

  • ニューラルネットワークベースのモデル(特に自然言語処理、推薦システム、時系列予測など)。
  • カテゴリ数が非常に多く、密な表現が必要な場合。

実装コード例(Keras の Embedding 層を利用)

Python
import tensorflow as tf
from tensorflow.keras import layers, models

# サンプルデータ:カテゴリ変数を整数IDに変換済みとする
# 例:色のカテゴリ [0, 1, 2, ...](ここでは色の数が vocab_size に対応)
vocab_size = 10    # カテゴリ数
embedding_dim = 8  # 埋め込み次元

inputs = tf.keras.Input(shape=(None,), dtype="int32")
embedding_layer = layers.Embedding(input_dim=vocab_size, output_dim=embedding_dim)
embedded = embedding_layer(inputs)
model = models.Model(inputs=inputs, outputs=embedded)
model.summary()

まとめ

各カテゴリ変数エンコーディング手法にはそれぞれ特徴があり、状況に応じた選択が求められます。

  • ワンホットエンコーディング:
    理解しやすく実装も簡単ですが、カテゴリ数が多いと次元が増大しやすい。
  • ラベルエンコーディング:
    次元数は増えませんが、カテゴリに順序があるかのような誤解釈のリスクがあります。
    決定木系のモデルには比較的適しています。
  • ターゲットエンコーディング:
    目的変数の情報を反映でき、予測精度向上に寄与する可能性がありますが、データリークに注意が必要です。
  • Embedding:
    ニューラルネットワークとの親和性が高く、低次元で密な表現を学習できますが、学習データやハイパーパラメータの調整が重要です。

この記事が各手法の特徴を簡単に理解し、これからより深く学んでいく足掛かりになれば幸いです。

コメント

タイトルとURLをコピーしました