#概要
カテゴリカル変数の処理の仕方にMean_encodeというものがあります。
これは,カテゴリ別にターゲット変数の平均などの統計量を特徴量として渡すというもので、
それをPythonで実装した。
#疑似データ作成
sklearnで提供されているデータセットで
カテゴリ変数がいい感じに含まれているものがなかったので
適当に作成します
import pandas as pd
import numpy as np
target = np.random.randn(100)
fruit = ["apple", "banana", "strawberry", "peach", "orange"]*20
color = ["red","yerrow","red","pink","orange"]*20
df = pd.DataFrame({"value":target,"fruit":fruit,"color":color})
上位5件を見てみるとこんな感じです。
df.head()
#過学習を避けるために
Kaggleのコンペでの経験から、それぞれのカテゴリの出現頻度はかなり差が見られることが多いです。
観測母数が少ないデータではそのカテゴリでのターゲット変数の平均値がそのままターゲット変数になってしまい、
過学習する原因となってしまうので、少し工夫必要です。
よってKfoldを利用してデータを分けてenocdeするコードを書きます。
#Mean_Encode実装
こんな感じで関数は実装しました。
def target_encode(train,df,target,categorical):
for col in categorical:
tmp = pd.DataFrame(train.groupby(col)[target].agg(["mean","sum","count","std","var","max","min","median"])).fillna(-999)
tmp.reset_index(inplace=True)
tmp.columns = [col,col+"_mean",col+"_sum",col+"_count",col+"_std",col+"_var",col+"_max",col+"_min",col+"_median"]
df = pd.merge(df,tmp,how="left",on=col)
del(tmp)
return df
3行目を見るとわかると思いますが,平均だけではなく分散や中央値など様々な統計量を指定しています。
Lightgbmなどに代表される木系のアルゴリズムは比較的特徴を取捨選択してくれるので,作れるだけ特徴を作るようにしています。
from sklearn.model_selection import KFold
kf = KFold(n_splits = 10,shuffle=True)
categorical = ["fruit","color"]
dfs = []
for train_index, test_index in kf.split(df):
tmp = target_encode(df.loc[train_index],df.loc[test_index],"value",categorical)
dfs.append(tmp)
return_df = pd.concat(dfs,axis=0)
最終的にreturn_dfという名前のデータフレームに結果が返ってくるようにしています。
return_dfの先頭5行を見てみます。
return_df.head()
全ての列が入り切れていませんが、きちんと動いています。
#参考文献
#追記
https://www.kaggle.com/c/avito-demand-prediction/discussion/59881
こちらのDiscussionにあるように地域別やアイテム別の値段の平均などを取得し,レコードの値段がその集合内でどのような特徴をもつのかを組み込むと有効みたいな戦略がありました。こちらの記事を利用してできると思います。