【SIGNATE】 (学生限定)マイナビコンペの振り返り
今回学生限定のコンペが開催されるということで、初めてSIGNATEに参加しました。
結果から言うと300人中90位と思うような結果は得られませんでしたが、初めてテーブルコンペにまともに取り組んでみて、学びが非常に多かったため今回ここにまとめておこうと思います。
コンペの概要
今回のコンペの目的は東京23区内の家賃予測でした。約3万件の訓練データとテストデータが与えられており、説明変数には、住所、築年数、土地面積などを含む15個の特徴量が与えられていました。
KaggleのHouce pricesやSIGNATEの土地の販売価格の予測など比較的似た内容のコンペに関する情報が公開されていたので、これらを参考に進めていきました。
signate.jp
序盤で行ったこと
データの前処理
序盤は主にデータの前処理ばかりを行っていたような気がします。与えられているデータはほとんどが日本語で書かれた未処理のデータであったため、正規表現とpandasのモジュールを使用してデータ整形を行いました。ここでの作業でpandasの処理にだいぶ慣れることができました。個人的にはデータを可視化する作業がとても好きなので、序盤にEDAをしている時はワクワクしていたように思います。
学習モデルはとりあえずGBDT*1を使っとこうという理由でlightGBMを使用しました。
この段階ではベンチマークを僅かに超えたくらいでした。ただ既存のデータを前処理してパラメータを適当に選んだ状態で学習させた程度であるにも関わらず、それなりの精度がでるGBDTには正直驚きました。のちに知ることとなるのですがGBDTモデルでは欠損値を補完する必要がないことを知らなかったため、当初は全ての欠損値を律儀に補完していました。またデータの特徴量化に関しては当時はone-hot encodingしか知らなかったため、カテゴリ変数は全てone-hot-encodingで処理していました。
中盤で行ったこと
緯度経度のデータ取得
今回のコンペは外部データの利用も可であったので、与えられている住所から緯度と経度をgeocodingというサイトを利用して取得しました。
しかしこの作業がかなり大変で、サーバーに負担をかけないために10秒間隔でスクレイピングを行う必要がありました。テストデータも含めると約6万件だったので全てのデータを取得するのに1週間ほどかかる計算でした。しかも試してみるとうまくデータを取得できなかったり、予期せぬエラーが発生して計算が途中で止まり取得したデータが消える場面もありました。
そこでデータを1000件ずつに分けて1000件データを取得できたらcsvにデータを保存するを繰り返すという方法を取りました。試行錯誤を繰り返しながらなんとか無事に全データの取得が終わったのがコンペ終了の1週間前でした。
Kaggle本を読んでとりあえず色々試す
2019年10月9日(コンペ開催期間)に『Kaggleで勝つデータ分析の技術』が発売されました。twitter等で話題になっていた本で、u++さんの書評を見てこれは今読むべき本だと思い、購入しました。
読んでみると、テーブルデータに対してのありとあらゆる手法が網羅されている印象で非常に買ってよかった1冊でした。またコードも掲載されていたためこの本を見ながらすぐに様々な手法を試すことができました。
今回私がこの本から学んだことをいかに整理しておきます。
- target encoding, label encoding等のカテゴリ変数をencodingする手法
- 評価指標RMSEは外れ値に影響を受けやすい
- 特徴量の作成手順
- GBDTは欠損値補完や数値の変換をしなくてもいい
- k分割交差検証モデルの予測値の平均を予測値とする方法
- スタッキング
特にtarget encodingとスタッキングはリークの可能性があるためout-of-foldで行う点は非常に重要であると感じました。
特徴量の作成
データが3万件と非常に多いのに対して特徴量が15個と少ないこと、加えてGBDTはある程度意味のない特徴量の追加に対してもロバストであることから特徴量をとりあえず大量に増やす方針に変えました。具体的に作成した特徴量は
- 家賃÷面積=地価とみなし、各カテゴリ変数の水準ごとに算出した地価の平均を各物件の地価から引き算、割り算
- 面積×階数=建物の体積(建設費用と相関がありそうと仮定)
- 居住階÷最上階=建物内での相対的な位置
- 面積÷間取り(2LDKなど)から得た部屋数=1部屋あたりの面積
これらを組み合わせながら特徴量を200個ほどに増やしていったのが中盤でのハイライトです。
終盤で行ったこと
クラスタリング
取得した緯度経度のデータを用いてより細かく土地区分を行おうと思いクラスタリングを行いました。
上記の図はクラスタ数が100のもので、その他に50, 500, 1000も特徴量に加え他の特徴量と組み合わせて特徴量を計290個にまで増加しました。
スタッキング
上記のKaggle本で掲載されていたスタッキングをコンペ終了前日から取り組みました。
lightGBMで予測した値を特徴量として、線形モデル・lightGBMで再度学習を行いました。しかしここではスタッキング後の精度の方が悪くなってしまい、2層目にlightGBMを用いたモデルに関しては精度が倍以上に悪くなったため、おそらくリークしていたのだろうと思われます。
ここをごちゃごちゃ触っているうちに制限時間がきて90位でコンペを終えました。
コンペを終えての所感
正直最初は「自分上位食い込めるのでは」という謎の期待を抱いていましたが、あえなく散ってしまいました。ただ学びは非常に多く参加したことには意義があったと思います。あわよくば賞金が欲しかった。笑
またこれが初めてのブログ投稿でしたが、ただ「コンペに参加して90位でした」だけだと周りからも特に評価されないし、自分としてもやっただけで終わってしまう気がしたので、今後はこういった取り組みの過程も逐一残していこうと思いました。
[GitHub] https://github.com/kuto5046/signate
*1:Gradient Boosting Decceision Tree