Home Credit Default Riskの1位の訳と振り返り


[home-credit-default-risk](https://www.kaggle.com/c/home-credit-default-risk)のコンペの1位の情報量が多かったのでひたすら訳してまとめました。コンペ自体は半年ほど前ですが完全に積んでいたので、この年末の機会にまとめておきます。

## はしがき

このコンペは与えられた個人のクレジットの情報や以前の応募情報などから、各データが債務不履行になるかどうかを予測する問題です。7000チーム前後が参加するというかなりの大規模コンペでしたが、上位の点数が相当団子で0.001を競うコンペになっていた記憶です。

大元の1位のソリューションはこちら
https://www.kaggle.com/c/home-credit-default-risk/discussion/64821

## TL;DR
* 特徴量設計と選択がほとんど
* 多様なモデルでアンサンブル
* ハイパーパラメータチューニングは全然できなかった
* NN（ニューラルネット）とTree系が主だが、DAE(swap noise)などちょいちょいテクニカルな要素も使っている

## 感想(長いので先に)
かなり多くの特徴量やエンコーディングを利用しているなぁと。期間を区切った特徴量とか近傍500個のデータの平均とかはなかなかテクニカルだな...と。NN系のswap noiseも自分は元々知らなかったのでかなり勉強になりました。一方でパラメータチューニングができていないというのは驚きました。自分もやっててこれいつチューニングするんだ...とはずっと思っていたので。やはり一にも二にも特徴量設計なのでしょうか。

またスキを見てこうしたコンペにも果敢に挑みたいと思います。


## 以下、訳まとめ
### 概要
* 難しかった
	* データが異質であり、異なる期間のデータや多くのデータソースから組み込まれていた。
	* 深いドメイン知識やビジネス分析スキルが必要だった
*  1. Good set of smart features. 2. Diverse set of base algorithms
* １つ目はKernelに上がってたOliverの特徴量をベースにした
	* 様々な特徴量を集計し一つのapplication tableにまとめた
	* 約700の特徴量を利用した

## 詳細
### 特徴量設計
#### Ryan
* EXT_SOURCE_3でapplicationを割ったのがわずかに効果があった
* カテゴリカル特徴量をラベルエンコーディングしたのがさらにより良いスコア上昇になった
* これらを全てのapplication_trainとprevious_applicationの最後のapplicationのカテゴリカル特徴量について行った
* SK_ID_PREV & SK_ID_BUREAUの集計だけではなく、異なる期間のデータの集計を行った
* Previous_application.csvの最後の 3, 5番目と最初の2, 4番目のapplicationsについてそれぞれ集計を行った
* Installment_payments.csvについては
	* 最後の2,3,5のpaymentsについて集計
	* NUM_INSTALMENT_NUMBER が 1, 2, 3, 4の installmentsについて集計
	* DAYS_INSTALMENTが最後が60, 90,180,365のものをフィルタリングして集計
	* past due(延滞)についても集計した。これはDAYS_ENTRY_PAYMENT and DAYS_INSTALMENTの間が0より大きい物を1、そうでないものを0とした
* POS_CASH_balance.csv, credit_card_balance.csvについてはInstallment_payments.csvと同様に集計を行った
* lag特徴量を用いた。last 5回までのprevious applicationをlag特徴量として利用した

#### Oliver
* だいたいpublicのkernelに自分が上げたやつ
* 内容としては
	* aggregation系
	* hand craft features系
がメイン

#### Phil
* 一番良かった特徴量が近傍500個でのtargetの平均
	* 3種類のexternal sourcesとcredit/annuity ratioによって決めた
* REGION_ID_POPULATIONはカテゴリカルに変換した
* debt_credit_ratio_None
	* SK_ID_CURRでgroup by してAMT_CREDIT_SUM_DEBTの合計をAMT_CREDIT_SUMの合計で割った
* credit_annuity_ratio
	* AMT_CREDIT / AMT_ANNUITY
* prev_PRODUCT_COMBINATION
	* 一番直近の応募の特徴量
* DAYS_CREDIT_mean
	* bureauにあるCREDIT_DAYSをSK_ID_CURRでgroupbyした平均
* credit_goods_price_ratio
	* AMT_CREDIT / AMT_GOODS_PRICE
* last_active_DAYS_CREDIT
	* SK_ID_CURRでgroup byした最も最近のactiveなDAYS CREDIT
* credit_downpayment
	* AMT_GOOD_PRICE - AMT_CREDIT
* AGE_INT
	* int(DAYS_BIRTH / -365)
* installment_payment_ratio_1000_mean_mean
	* installment paymentsの中でDAYS_INSTALLMENT>-1000のものだけ取り出し、AMT_PAYMENT - AMT_INSTALMENTの平均をとった
	* 最初にSK_ID_PREVでgroup byし、次にSK_ID_CURRでgroup byした
* annuity_to_max_installment_ratio
	* AMT_ANNUITY / (installments_paymentsをSK_ID_CURRでgroup byしたのち、最大のinstallment)

#### Yang
* open solutionにもあるlast, 3, 5, 10番目のcredit card, installment, and posを利用する。
* the time periodを調整(詳細不明)
* 重み付き平均をannuity, credit, and paymentに関するいくつかの特徴量に対して利用
	* これらの特徴量は人間の行動を抽出するのに有用
* income, payment and timeからいくつかのKPI指標を作成した(詳細不明)

### Feature selection and reduction
#### Bojan
* あまりにも特徴量が多いと余分であったりノイズになったりする
* 数値特徴量をFrequency Encodingで変換、それらをRidge回帰による前進選択により選択した
* これにより1600 -> 240まで特徴量が削減できた(最終的にいくらか足して287になった)
* メンバーが増えたときに最初は全部特徴量を試したが、最後の方は全部試すのが難しかったため、目検で今までにない特徴量を探して追加した
*  Yang’s base set が最も良かった(0.802 private, 0.803 public)。最後に各々の特別な特徴量を足していって1800くらいになった

### Base Model
* StratifiedKFold, with 5-foldsを利用した
* 普通のk-foldとも比較したが今回は大きな差はなかった

####　Olivier
* LightGBM, FastRGF, FFM を使ったがCVは良くならなかった(AUC 0.76)
	* [rgf_python · PyPI](https://pypi.org/project/rgf_python/)
	* [GitHub - keyunluo/python-ffm: Python Wrapped LibFFM](https://github.com/keyunluo/python-ffm)

####　Bojan
* XGBoost, LightGBM, CatBoost, 及び単純な Linear Regressionを使った。
	* XGBはkernelにあったものを一つ
	* LightGBMはkernelにあったもの、Neptuneのチームが使っていたもの(Open Solution..?)、自分で組んだものの3つを利用
	* XGBはGPU、LightGBMはCPUで学習
	* Catboostはあまり性能良くなかったが、結果の多様性的に良かったと思ってる

####　Ryan and Yang
* 色々加工したデータセットでLGBMのモデルを作成した。RyanはFFMも試した

####　Michael Jahrer
* 主にNeural Networkを担当した
* 他の人の通り、基本的にNNよりもLGBMやXGBの方が精度がいい(今回もNNは最初0.785程度でLGBMは0.79以上あった)。しかし、NNはある程度のレベルまで行けばblendingするのに良い候補なので頑張った
* DAE(Denoising Auto Encoder)+NNがNN単体よりもいい精度が出た
* はじめ、特徴量が100-5000程度だったので、情報が損失しないようにDAEはかなり大きなものになった
* 最初の教師なしDAEは10000-10000-10000でNNは1000-1000くらいのパラメータが良かった
* DAEはswapnoise(同じ要素で行を入れ替えるノイズ)=0.2とし、最初のlearn rateは高めに設定して1000エポック回した。
* NNはlRate=2.5e-5(弱いdecayもつけた), dropout=0.5とし、overfitを避けるために50エポックでloglossを評価関数とした
* 隠れ層は全てReLU, OptimizerはSGD,ミニバッチサイズは128とした
* GTX1080Tiで約1日使った
* 色々細かく調整してNNで0.795程度まで行った(一方LGBMは0.8039だった)

### Ensembling
* 三段階でアンサンブルを行った。レベル1ではNN, XGB, LGBM, Hill Climber linear modelを用いた
* だんだんスコアが上がるとCVとLBがより相関した
* CVとLBが伸びなくなったらレベル2に進んだ
* レベル2のレイヤーではNN, ExtraTreeとHill Climberを使った
* この時、re-stackingと生の特徴量を少し加えた
* 最終層では3つのモデルの平均をとった

####　Michael
* 1層500ReLUユニットのNNをstackingに使った
* lRate=1e-3 , lRateDecay=0.96, dropout=0.3としたら良かった

####　Phill
* ExtraTreeのL3モデルはかなり浅くmaxdepth=4で正則化項を極端に大きくした(minsamplesleaf=1000とした)
* L2モデル7個とAMT_INCOME_TOTALの特徴量を使用した
* ↑はCV: 0.80665, LB:80842, PB: 80565だった

### Other things that we tried, some interesting insights, and a few recommendations
* どのチームもあまりハイパーパラメータチューニングに時間をかけられなかった
* 最適化もしようとしたがローカルの結果があまり良くなかった
* そのため、一個のより良いモデルよりも色々なモデルをアンサンブルすることを選んだ
* フォーラムに0.98AUCのものがあったが使えなかった(おそらくadvisarial validation系だろう)
* EXT_*の特徴量を補完しようとしたがそこまで役には立たなかった
* 終わってみてみるとトップ3つのモデルは結局全てトップ10以内に入っており、それらの単純平均で1位になった
* こうしたコンペではやはり特徴量設計と選択が最重要
* 自分たちはパラメータチューニングの時間なかったけどちゃんとチューニングすれば単一のモデルでも凄いいい結果が出せるかもしれない