u++の備忘録

コルモゴロフ-スミルノフ検定を利用した特徴量選択

はじめに

えじさんの下記記事を読んで「コルモゴロフ-スミルノフ検定を利用した特徴量選択」が気になりました。自分なりに簡単に手を動かしてみたので、備忘録としてまとめておきます。

amalog.hateblo.jp

元になったdiscussionの投稿はこちらです。

f:id:upura:20190303233244p:plain

www.kaggle.com

コルモゴロフ-スミルノフ検定を利用した特徴量選択

コルモゴロフ-スミルノフ検定とは

Pythonでは「scipy.stats.ks_2samp」で実行できます。

docs.scipy.org

This tests whether 2 samples are drawn from the same distribution.

日本語にすると「2つの集合が同じ分布から生まれたか否かを検定する」くらいでしょうか。

特徴量選択にどう活用する?

Kaggleでの特徴量選択に当たって、目的の一つは「testデータの予測に有用な特徴量を選択する」ことです。

ここで、trainデータの予測で言えば、正解の目的変数の値が分かっているので、何が有用な特徴量なのかは評価しやすいです。つまり、trainデータとtestデータで分布が似ている特徴量は、testデータの予測においても有用か否かを評価しやすいです。

逆に言えば、trainデータとtestデータで分布が似ていない場合は、仮にtrainデータの予測で良い評価を得ている特徴量でも、testデータの予測に有用か否かは判断がつきません。そのため、コルモゴロフ-スミルノフ検定を実施し、trainデータとtestデータで分布が似ていない特徴量を選択しないという手段が考えられます。

Kaggle Kernel

trainデータとtestデータの分布が違いそうな「Santander Value Prediction Challenge」のデータを利用しました。

実装の全容はKaggle Kernelとして公開しています。

www.kaggle.com

最初に、trainデータとtestデータを読み込み、予測に使わない列は削除しました。

train = pd.read_csv('../input/train.csv')
test = pd.read_csv('../input/test.csv')
train.drop(['target', 'ID'], inplace=True, axis=1)
test.drop(['ID'], inplace=True, axis=1)

あとは、discussionに貼られたコードをそのまま利用できます。このコードではp値が0.1以下の特徴量を list_discarded に格納しています。

from tqdm import tqdm
from scipy.stats import ks_2samp
list_p_value =[]

for i in tqdm(train.columns):
    list_p_value.append(ks_2samp(test[i] , train[i])[1])

Se = pd.Series(list_p_value, index = train.columns).sort_values() 
list_discarded = list(Se[Se < .1].index)

おわりに

本記事では、コルモゴロフ-スミルノフ検定を利用した特徴量選択を紹介しました。えじさんと同様に、僕もこのテクニックは手持ちに加えておこうと思います。