かなり時間がかかってしまいましたが、オブジェクトデータの処理を加え流ことが出来ました。ダミー化ということでカラムがかなり増えてしまってメモリ不足に悩まされましたが、テーブルを一つずつ処理していくという基本的な対応をすることで何とか処理することが出来ました。
対象となるコードは下記となります。基本的なテーブルの読み込みなどは過去のHome Creditトライの記事をご覧ください。
#おさらい。対象となるテーブルを読み込み
bur = pd.read_csv("bureau.csv")
bur_b = pd.read_csv("bureau_balance.csv")
#二つで共通するカラムで結合
bur_com = pd.merge(bur, bur_b, on="SK_ID_BUREAU", how="left")
#ここからダミー変換
#続いてカテゴリ変換をfor文章で回す
#事前にbur_com.infoでobjectカラムを確認して、colsに収納
cols = ["CREDIT_ACTIVE", "CREDIT_CURRENCY", "CREDIT_TYPE", "STATUS"]
for c in cols:
#カテゴリ化
bur_com[c] = pd.Categorical(bur_com[c])
#ダミーの作成
dummy = pd.get_dummies(bur_com[c], drop_first =False)
#ダミーの結合
bur_com2 = pd.concat([bur_com, dummy], axis=1)
#元のカラムの削除
bur_com3 = bur_com2.drop(cols, axis=1
この処理を行うと、CREDIT_ACTIVEカラムのケースでは、データの中身であるClosedとActiveの2種のカラムが追加されて、binaryで0, 1のデータが入ることになります。もし8種類あったら8個カラムが追加されてしまいますので、データ量がかなり増えてしまうのでご注意ください。
ちなみにテーブルにあるオブジェクトを抽出するコードはこちら。
#テーブルのオブジェクトカラムを確認するコード
tables = [cd_b, ins_p, pos_c, prv_a]
#objectのカラム名を抽出
for t in tables:
print("----start------")
print(t.select_dtypes('object').columns)
print("------end----")
他のテーブルも同様に実施しています。今回唯一previous_application.csvというテーブルはオブジェクトカラムが16個とえらい多かったので、こちらは今回ダミー化をしないことにしました。データ種類数も確認しないとカラムが物凄い数になってしまうのがダミー化の難点な気がします。
cd_b["NAME_CONTRACT_STATUS"].value_counts()
#カテゴリ化
cd_b["NAME_CONTRACT_STATUS"] = pd.Categorical(cd_b["NAME_CONTRACT_STATUS"])
#ダミーの作成
dummy = pd.get_dummies(cd_b["NAME_CONTRACT_STATUS"], drop_first =False)
#ダミーの結合
cd_b2 = pd.concat([cd_b, dummy], axis=1)
#元のカラムの削除
cd_b3= cd_b2.drop("NAME_CONTRACT_STATUS", axis=1)
#オブジェクトが消えて、ダミー化できているか確認
cd_b3.info()
#同様にpos_cを処理。一つくらいのオブジェクトならダミー化で問題ない気がする
#カテゴリ化
pos_c["NAME_CONTRACT_STATUS"] = pd.Categorical(pos_c["NAME_CONTRACT_STATUS"])
#ダミーの作成
dummy = pd.get_dummies(pos_c["NAME_CONTRACT_STATUS"], drop_first =False)
#ダミーの結合
pos_c2 = pd.concat([pos_c, dummy], axis=1)
#元のカラムの削除
pos_c3= pos_c2.drop("NAME_CONTRACT_STATUS", axis=1)
#オブジェクトが消えて、ダミー化できているか確認
pos_c3.info()
ここまで実行したら、前回と同様な処理です。trainとtestではCURR_IDがユニークですので、同じ形になるようにそれぞれのテーブルを雑に平均化しました。もう少し詳細が気になる方は、お手数ですが下記前回記事をご参照ください。
#cd_b, ins_p, pos_c, prv_a:::SK_ID_PREVとSK_ID_CURRから成り立つ→数値の平均をとる(SK_ID_CURRベース)
cd_b4 = cd_b3.groupby(["SK_ID_CURR"], as_index=False).mean()
ins_p4 = ins_p.groupby(["SK_ID_CURR"], as_index=False).mean()
pos_c4 = pos_c3.groupby(["SK_ID_CURR"], as_index=False).mean()
prv_a4 = prv_a.groupby(["SK_ID_CURR"], as_index=False).mean()
bur_com4 = bur_com3.groupby(["SK_ID_CURR"], as_index=False).mean()
#tables = [cd_b3, ins_p, pos_c3, prv_a, bur_com3]
#PREV, BUREAUのIDは意味ないデータなので削除
cd_b5 = cd_b4.drop("SK_ID_PREV", axis=1)
ins_p5 = ins_p4.drop("SK_ID_PREV", axis=1)
pos_c5 = pos_c4.drop("SK_ID_PREV", axis=1)
prv_a5 = prv_a4.drop("SK_ID_PREV", axis=1)
bur_com5 = bur_com4.drop("SK_ID_BUREAU", axis=1)
ここまで作成したところで、前回同様に結合+エンコーディングを行います。ここからランダムフォレスト、csv出力を行い、提出しました。
スコアは0.53670.終わったコンペなので順位は出ませんでしたが、おおよそ本日時点で6813位。前回0.5000だった時の想定順位は6987位。極少しだけアップしてました。ちなみに0.5000はsampleと一緒というレベル。とりあえず点数が上がったのは良いことです。
次の修正ポイント候補は
・今回Nullには0で置換している。これで良いのか?
・効果を考えずに全てのカラムを使用。抽出すべきではないか?
・他の学習も試したい。ランダムフォレスト以外を使ってみる
・学習を仮決めしたら、ハイパーパラメータなどのチューニングを試す
Nullの処理と、使用するカラムの抽出に次回トライしていこうと思います。今後のコンペでも必要な処理と思うので。
ちなみにダミー化処理は下記の前処理大全という本を参照しました。他にも参考になりそうなコードがあったので紹介しておきます。
さらにlightGBMのトライなどこの後取り組みましたが、結局スコアは伸び悩んだので一旦このコンペは終了。やはり基本的なところの理解が少ないので、しばらく下記の本で勉強します。