アンダーサンプリングによる不均衡データへの対処
アンダーサンプリングとは
アンダーサンプリングとは、目的変数がある特定の値(クラス)に偏っている場合、その偏りを解消するためにテスト用データでのクラスの比率を均一にすることです。
どういうことかというと、例えばボートレースの着順を予測するモデルを作るとします。
ボートレースや競馬においては3連単のように3着以内に入るかが重要であるため、4着以下はすべて4着扱いにまとめるように前処理をしたとします。
つまり、5着や6着であっても4着として扱うようにします。
すると、結果的に以下のように4着のデータが多くなります。
df['arrival'] = df['arrival'].fillna(6)
df["arrival"] = df["arrival"].astype(int)
df['arrival'] = df['arrival'].apply(lambda x: 4 if x > 3 else x)
df['arrival'].value_counts()
arrival
4 81081
2 27030
1 27026
3 27025
Name: count, dtype: int64
このような偏りがあるデータをこれを不均衡データといいます。
このようなデータを用いてモデルの学習を行うと、モデルは4着のデータを多く学習するため、4着の予測精度は高くなるものの、1着、2着、3着の予測精度は低くなります。
予測が多数クラスに偏るようなことを避けるため、訓練データでは各クラスのサンプル数を揃える必要があります。
アンダーサンプリングを用いることで、少数クラス(1着, 2着, 3着)に合わせて多数クラス(4着)のデータを減らし、クラス間のバランスを取ります。
もうひとつ例を出しておくと、スパムメールの分類なんかも不均衡データが多いと思います。
仮にスパムメールが全体の1%しかない場合、スパムメールのデータが少なく、非スパムメールのデータが多いというクラス不均衡が発生します。
これらの例から分かるように、アンダーサンプリングは主に分類問題において使用されるデータ準備の手法です。
例えば、回帰問題では目標値が連続値であり、クラス不均衡の概念は直接適用されません。
したがって、アンダーサンプリングは通常、回帰問題に対して使用されません。
実装例
from imblearn.under_sampling import RandomUnderSampler
def undersample_data(
X_train: pd.DataFrame, y_train: pd.Series, random_state: int = 42
) -> tuple[pd.DataFrame, pd.Series]:
class_counts = y_train.value_counts()
sample_count = class_counts.min()
sampling_strategy = {cls: sample_count for cls in class_counts.index}
rus = RandomUnderSampler(sampling_strategy=sampling_strategy, random_state=random_state)
X_train_resampled, y_train_resampled = rus.fit_resample(X_train, y_train)
return X_train_resampled, y_train_resampled
X = df.drop(columns=['arrival'])
y = df['arrival']
X_resampled, y_resampled = undersample_data(X, y)
y_resampled.value_counts()
arrival
1 27025
2 27025
3 27025
4 27025
Name: count, dtype: int64
補足
テストデータの分割
訓練データのアンダーサンプリングとテストデータの分割は別々に行います。
テストデータではクラスの比率を自然に保つことが一般的です。
これにより、モデルの評価が実際のデータの分布を反映するようになります。
適用範囲
アンダーサンプリングは、クラス不均衡が存在する場合に有効です。
ただし、データの全体数が少ない場合や、重要なデータが失われるリスクがある場合には注意が必要です。
Discussion