<実践>HomeCredit作業記録(3) - FeatureEngineeringのアプローチ

Kaggle挑戦中です!
債務不履行になる人を予想するタスクです。
Home Credit Default Risk | Kaggle

最近は特徴量エンジニアリング(FeatureEngineering)をやっています。

やっている中で気づいたことがあるのでブログにします

特徴量エンジニアリングのアプローチ

特徴量エンジニアリングを、ボトムアップでやっていたのですが、どうやら最初は「トップダウン」でやるほうがよさそうです。

※業務経験2ヶ月の新米データサイエンティストのいち考察として読んでいただければ幸いです。。

ボトムアップ

https://www.kaggle.com/c/home-credit-default-risk/data データの特徴量(=項目)を1つずつ吟味して、特徴量を生成する
以下は、「クレジットカードの返済期限を過ぎてしまった回数」という特徴量を作成しました。
(返済期限を過ぎた人が多いほど債務不履行になるのでは?という私の推測から)

def count_credit_day_overdue(df):
    """
    credit_day_overdue>0の件数を、ユーザーIDごとに数える
    :param df:
    :return:
    """
    def _count_over_zero(array):
        count = 0
        for val in array["CREDIT_DAY_OVERDUE"].values.flatten():
            if val > 0:
                count += 1
        return count

    df_tmp = df[["SK_ID_CURR", "CREDIT_DAY_OVERDUE"]]

    series_count_by_id = df_tmp.groupby("SK_ID_CURR").apply(_count_over_zero)
    series_count_by_id.name = "*DAY_OVERDUE_COUNT"

    df_count_by_id = pd.DataFrame(series_count_by_id).reset_index()
    return df_count_by_id

・・・こんな感じで2,3項目を作ってみたのですが、これじゃ日がくれそうです。
KaggleのKernelを見ると・・・トップダウンアプローチで作っている人が多いです。

トップダウン

    output_dir = "../../data/edited/all_mean"
    label_enc = LabelEncoder()

    def labelencode_cat(df):
        df = df.copy()
        cat_var = df.select_dtypes(['object']).columns.tolist()
        for col in cat_var:
            df["category_{}".format(col)] = label_enc.fit_transform(df[col].astype('str'))
            df = df.drop(col, axis=1)
        return df

    original_dir = "../../data/original"

    def output_mean(df, filename):
        df_avg = df.groupby("SK_ID_CURR").mean().reset_index()
        output_csv(df=df_avg,
                   output_path="{}/{}.csv".format(output_dir, filename))

    print("bureau")
    fname = "bureau"
    df_bureau = pd.read_csv("{}/{}.csv".format(original_dir, fname)).pipe(labelencode_cat)
    df_bureau = df_bureau.drop("SK_ID_BUREAU", axis=1)
    output_mean(df=df_bureau,
                filename=fname)
    del df_bureau

ざっくりと全部の項目についてユーザーごとに値の平均を取って、特徴量としてしまう。
なんと大雑把なー!!と思ったのですがこっちのほうが良さそうです。

なぜトップダウンがいいのか?

ローコスト

とにかく楽です。30行くらいのコードで、全ファイルの特徴量ごとの平均が取れちゃいました。

大事な項目を絞り込める

上記のような形で全部のデータをLightGBMやXGBoostなどの学習器で学習させると、feature_importances_を出力してくれます。

f:id:kurupical:20180530213313p:plain:w500

この図でわかることは、「予測にあたり学習器が重要視した項目」です。
つまり、(平均という大雑把なやり方とはいえ)重要な項目がなんとなくつかめます。
ここから、各項目について「ボトムアップ」で、特徴量作成するのがいいような気がします。

トップダウンのデメリット

カテゴリ変数(=文字列項目)の平均?

機械学習にかけるときは数値変換をする必要があります。
動物であれば、うさぎ=1、象=2、犬=3、・・・など。1
カテゴリ変数の「平均」を取ると、うさぎと犬の平均は象!?みたいな変なことになります。
トップダウン的なアプローチは、「数値」にのみ有効なんだと思います。

まとめ

最初からボトムアップで泥臭くやるより、トップダウン→特徴見てボトムアップのほうが当たりがつきやすく、素人にはよいのかもしれません。

途中経過

f:id:kurupical:20180530214633p:plain:w500

score: 0.706 -> 0.735
順位: 936位/1197 (上位80%)


  1. LightGBMはカテゴリ変数に対応しており、OneHotEncodeしなくてもよい