2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

不均衡データの取り扱い(oversampling_undersampling)

Posted at

はじめに

分類モデルを構築する際の
クラス間で事例の数や割合が極端に異なるデータは不均衡データと呼ばれます。

例:重篤な病気の発症有無、クレジットカードの不正利用予測

不均衡データでそのまま分類モデルを構築してしまうと
正解率 (Accuracy) こそ高いものの、適合率(recall)が低いモデルになることが想定されます。

極端な話、重篤な病気の発症予測であれば、すべて発症なしというモデルを作れば
未発症な人が大多数であるため正解率 (Accuracy)は高くなります。

発症あり 発症なし
発症ありと予測 0 0
発症なしと予測 40 9960

正解率 (Accuracy)→9960/10000 = 0.996

しかし、適合率(recall)は「発症ありと予測した人数/実際に発症あり」という式で
算出するため、発症ありと予測した人数が0人なのでrecall=0となります。

適合率(recall)→0/40 = 0

重篤な病気の発症有無やクレジットカードの不正利用のような例であれば
ある程度間違っていても発症ありの予測や不正利用ありの予測を
取りこぼさずにすることのほうが大切というのが感覚的にわかります。

分類モデルの評価指標はコンペであれば、
AUCやF値(F-measure、F-score)/F1スコア(F1-score)
で評価することが多いためなおさらrecallを上げることは大切といえます。

UuderSamplingについて

不均衡データのまま分類モデルを構築すると適合率(recall)という事象への
対応策の一つとして「UuderSampling」が挙げられます。

「UuderSampling」は「少数派のデータ群に合わせて多数派のデータ群を削除する」という考えの手法です。

先ほどの重篤な病気の発症予測であれば、発症あり40人に対して、発症なしが5000人と多すぎるので発症なしの人数を減らします。

しかしただ減らすだけではダメで、減らす前と減らした後でデータの分布が変わっていないことが担保される必要があります。

データ数をクラスが9:1に比率になるようにアンダーサンプリングを実施

UuderSampling pythonで実施
from imblearn.under_sampling import RandomUnderSampler

# クラス1の数を保存
count_train_class_one = y_train.sum()
print("サンプリング実施前")
print(y_train.value_counts()) 

# クラス1が全体の10%になるまでクラス0を減らす
under = RandomUnderSampler(sampling_strategy={0:count_train_class_one*9, 1:count_train_class_one}, random_state=100)

# 学習用データに反映
x_train_under, y_train_under = under.fit_resample(X_train, y_train)

print("サンプリング実施後")
print(y_train_under.value_counts())
-----------------------------------------------------------------
実行結果
サンプリング実施前
0    6687
1     313
Name: 発症有, dtype: int64
サンプリング実施後
0    2817
1     313
Name: 発症有, dtype: int64

OverSamplingについて

不均衡データの対応策の一つとして「UuderSampling」のほかにも
「OverSampling」が挙げられます。

「OverSampling」は「UuderSampling」とは逆に「少数派のデータを多数派に合わせて増やす」という考えの手法です。

OverSampling pythonで実施
from imblearn.over_sampling import SMOTE

# クラス1の数を保存
print("サンプリング実施前")
print(y_train.value_counts()) 

oversample = SMOTE(random_state=100)
x_train_over, y_train_over = oversample.fit_resample(X_train, y_train)

print("サンプリング実施後")
print(y_train_over.value_counts()) 
-----------------------------------------------------------------
実行結果
サンプリング実施前
0    6687
1     313
Name: 発症有, dtype: int64
サンプリング実施後
0    6687
1    6687
Name: 発症有, dtype: int64

最後に

「UnderSampling」も「OverSampling」もあくまでモデル構築時の訓練データに対して実施する処理であり
推論時は当手法は使わずにデータをモデルに投入し精度を確認する必要があります。

また2値分類以外のマルチクラス分類でも使用可能な手法となっています。

また実際のコンペの際は
「UnderSampling」と「OverSampling」どちらも使用して精度が上がる方を選択して
使用しています。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?