- 不均衡データとは -
- 不均衡データ:例えば障害を予知するモデルを学習データから作ろうとしている時、障害で無いデータは100万件あるのに対し、障害は100件程度しかないようなバランスの悪いデータ。
- 対策:
- モデル作成時に重みを与える
元のデータを操作せずに、少ないデータの重み(重要度)を上げることで、不均衡なデータに対応する。 - データを操作して不均衡な状態を解消する
以下が主な方法 - 少ないデータを増やすオーバーサンプリング
- 多いデータを減らすアンダーサンプリング
- その両方
- 6-1 アンダーサンプリングによる不均衡データの調整 -
データ量を減らす作業。なので、データの選択方法のみ考えれば良い。
- データの選択方法:
- 重複選択が勧められている
- 重複選択の問題点:
- 特定のデータが何度も選ばれることでデータに偏りが生まれ、過学習が発生しやすくなる。
- サンプリング数が少ない時に、偏りの無いランダムサンプリングを実現するテクニック:
- アンダーサンプリングの問題点:
- データを間引くので、情報量を減らしてしまい、さらには重要なデータも除いてしまう可能性がある。なので、なるべく使わない方が良い。
不均衡データのバランスをとりたいのならば、オーバーサンプリングをするほうがまし。ただし、オーバーサンプリングにより過学習が発生しやすくなるので、そういった時はオーバーサンプリングとアンダーサンプリングを併用することで対処する。まず、オーバーサンプリングで悪影響がない程度まで少ない方のデータ群を増やし、アンダーサンプリングにより、不均衡が解消される程度まで多い方のデータ群を減らす。
- 6-2 オーバーサンプリングによる不均衡データの調整 -
- オーバーサンプリング:
オリジナルデータから新たなデータを生成する。 - 方法:
- ランダムサンプリングにより元のデータ数より多くデータを抽出する:
問題として、完全に同じデータが出現してしまい、過学習が発生しやすくなる。 - SMOTE(Synthetic Minority Oversampling Technique):
過学習問題を軽減している手法。手法は、K-meansの応用っぽい。 - SMOTEのアルゴリズム:
- 生成元のデータからランダムに1つのデータを選択
- 設定したkの値を元に、1〜kの整数値(一様分布)からランダムに選択しnを設定
- 1で選択したデータにn番目に近いデータを新たに選択
- 1と3で選択したデータを元に新たにデータを生成
- [生成するデータの列値] = [1で選択した列値] + ( [3で選択した列値] - [1で選択した列値] ) * [0から1の一様乱数]
- 指定したデータ数に達するまで、1から4を繰り返す
図:Oversampling for Imbalanced Learning Based on K-Means and SMOTE
SMOTEにより生成されたデータは、元のデータと同じ特性を保ちながら異なるノイズを加えたデータを意味するため、単純にランダムサンプリングにより生成元のデータをコピーするより自然発生したデータに近い。
- SMOTEの問題点:
次元数(生成するデータの列数)が大きい場合、大きな空間が存在するのに対して、サンプリング元のデータ間の直線上のみからサンプリングすることにより、偏りが生じやすくなる。次元数が大きい場合は、アンダーサンプリングとバギングを組み合わせて予測モデルを構築するほうが安定する。
(バギングの詳細は、『はじめてのパターン認識(第11章)』のページ)
例)
製造レコードにおいて、障害が起きていない(fault_flgがfalse)レコードが927件、障害が起きている(fault_flgがTrue)レコードが73件ある。障害が起きているレコードをSMOTEでオーバーサンプリングを行い、障害が起きていないレコードの件数に近づける。
(SMOTEのkパラメータは5とする。)
# SMOTE関数のライブラリ
from imblearn.over_sampling import SMOTE
# SMOTE関数の設定
# ratioは不均衡データにおける少ない例のデータを多い方のデータの何割まで増やすか設定
# (autoの場合は同じ数まで増やす。0.5と設定すると5割までデータを増やす。)
# k_neighborsはsmoteのkパラメータ
# random_stateは乱数のseed(乱数の生成パターンの元)
sm = SMOTE(ratio='auto', k_neighbors=5, random_state=71)
# オーバーサンプリング実行
balance_data, balance_target = \
sm.fit_sample(production_tb[['length', 'thickness']], production_tb['fault_flg'])
sm.fit_sample(オーバーサンプリングする対象の列データ, 分類結果)
※上記コードでは、カテゴリ値はオーバーサンプリングできない。(エンコーディングすればいいのか?)
0コメント