機械学習モデルにおいて、カテゴリ変数の扱いは非常に重要です。
今回は、以下の4つの手法について、その直感的な考え方、メリット・デメリット、どのようなモデルや状況に適しているかを解説し、実際の実装コードも交えてご紹介します。
- ワンホットエンコーディング (One-Hot Encoding)
- ラベルエンコーディング (Label Encoding)
- ターゲットエンコーディング (Target Encoding)
- 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:
ニューラルネットワークとの親和性が高く、低次元で密な表現を学習できますが、学習データやハイパーパラメータの調整が重要です。
この記事が各手法の特徴を簡単に理解し、これからより深く学んでいく足掛かりになれば幸いです。
コメント