SPSS Modelerで目的変数のレコード数に不均衡がある場合にそのバランスをそろえるのがバランス・ノードです。
このバランス・ノードを解説するとともに、Pythonのpandasで書き換えてみます。
#0.元データ
ここではローン審査での、顧客の属性と判定したリスクの入ったデータを使います。Riskが1の場合はリスクの高い顧客、0はリスクの低い顧客を示しています。
CustID:顧客番号
Age:年齢
Car_loans:車のローンランク
Credit_cards:クレジットカード利用ランク
Education:教育ランク
Income:収入ランク
Risk:リスクありなし
Riskの1と0のレコード件数を比較するとRisk=1のレコードは全体の25%、Risk=0のレコードは75%で、アンバランスになっていることがわかります。
通常こういうデータでRisk予測モデルを作る場合は、Riskがある人を予測したいのですが、仮にすべてをRiskなしと予測しても75%の精度で予測ができ、Riskなしと予想しがちなモデルができてしまいます。
これを避けるために、Riskありとなしのレコードのバランスをとるのがバランス・ノードです。
#1m.①アンダーサンプリング Modeler版
バランス・ノードは単体で使うこともできますが、棒グラフノードから作るのが一般的です。
グラフができたら、生成メニューから「バランスノード(減少)」を選びます。
中身を見るとRisk=1の時には1倍なのでそのまま、Risk=0の時には約0.3倍のレコード数にするというバランス比率が定義されます。
このサンプリングノードを接続したうえで、改めて棒グラフノードで結果を確認すると、Risk=0のデータが約1/3になって、ほぼ同数のレコード数になりました。
注意点はランダムシードが設定できないので、毎回結果が変わってしまうことです。ですので、キャッシュしてキャッシュデータを保存しておくか、エクスポートノードでファイルやDBのテーブルに出力しておくことをお勧めします。
#1p.①アンダーサンプリング pandas版
pandasでアンバランスデータの修正を行う場合はimblearnを使います。pipやcondaを使って導入しておきます。
#pip
pip install imbalanced-learn
#conda
conda install -c conda-forge imbalanced-learn
imblearnを使うためには、以下のように説明変数のデータフレームと目的変数のデータフレームに分割しておく必要があります。
df_x=df.drop(['Risk'],axis=1)
df_y=df[['Risk']]
件数とその棒グラフを表示してみます。
df_risk=df_y.groupby('Risk').size()
print(df_risk)
df_risk.plot.bar()
では、このデータをアンダーサンプリングしてみます。
RandomUnderSamplerをImportし、random_stateでランダムシードを指定してインスタンス化します。
その上で説明変数のデータフレームと目的変数のデータフレームを引数にfit_resampleを実行するとアンダーサンプリングされた説明変数のデータフレームと目的変数のデータフレームが戻ります。
from imblearn.under_sampling import RandomUnderSampler
sampler = RandomUnderSampler(random_state=1)
x_resampled, y_resampled = sampler.fit_resample(df_x,df_y)
件数とその棒グラフを表示してみます。どちらも600件と同数になっているのがわかります。
df_risk=df_y.groupby('Risk').size()
print(df_risk)
df_risk.plot.bar()
#2m.②オーバーサンプリング Modeler版
先ほどはRiskありの600件に合わせてRiskなしのレコードを減らすアンダーサンプリングをしましたが、Riskありのレコード件数を増やすオーバーサンプリングも可能です。
棒グラフの生成メニューから「バランスノード(増加)」を選びます。
中身を見るとRisk=0の時には1倍なのでそのまま、Risk=1の時には約3倍のレコード数にするというバランス比率が定義されます。
棒グラフで結果を見ると以下のようにRisk=1のレコードが3倍に増えて、同数程度になっていることがわかります。
データをみるとRisk=1のレコードが約3倍に重複していることがわかります。
#2p.②オーバーサンプリング pandas版
pandasでオーバーサンプリングする場合はRandomOverSamplerを使います。使い方はRandomUnderSamplerと同じです。
from imblearn.over_sampling import RandomOverSampler
sampler = RandomOverSampler(random_state=1)
x_resampled, y_resampled = sampler.fit_resample(df_x,df_y)
#3. 補足
オーバーサンプリングにはSMOTEという方法もあります。SMOTEは単にデータをコピーするのではなく、似たデータを生成します。
【リレー連載】わたしの推しノード –機械学習時代の申し子「SMOTEノード」が不均衡データの壁を突破する | IBM ソリューション ブログ
ModelerにはSMOTEノードがあります。imbalanced-learnでもSMOTEが可能です。
SMOTE — Version 0.8.0
#4. サンプル
サンプルは以下に置きました。
ストリーム
https://github.com/hkwd/200611Modeler2Python/raw/master/balance/balance3.str
notebook
https://github.com/hkwd/200611Modeler2Python/blob/master/balance/balance.ipynb
データ
https://raw.githubusercontent.com/hkwd/200611Modeler2Python/master/data/credit_risk.csv
■テスト環境
Modeler 18.3
Windows 10 64bit
Python 3.8.5
pandas 1.0.5
imblearn 0.7.0
#5. 参考情報
Python: 機械学習における不均衡データの問題点と対処法について - CUBE SUGAR CONTAINER
バランス・ノード - IBM Documentation
imbalanced-learn API reference — Version 0.8.0