# SIGNATEで金メダルをとった話
> この記事は、[法政大学アドベントカレンダー2023の12日目](https://adventar.org/calendars/8853)として投稿されています。
この度、[SIGNATE Student Cup 2023【モデリング部門】:中古車の価格予測チャレンジ](https://signate.jp/competitions/1051)において金メダル(2位)を獲得することができました。この記事ではコンペにおける解法について記載していきます。
## 参加目的
私自身、データ分析コンペティション(コンペ)を使って機械学習に対する知識のベースを作ってきました。特に、B3からB4にかけて色々なコンペの解法を読んだことが、基礎から応用までの一連の考え方を身に着けられた1つの要因だったと思っています。コンペに対する良し悪しはよく議論に上がる内容ですが、私個人はコンペがスキルの習得に一定の効果ある(あってほしい)と考えています。
以前から複数のコンペへの参加経験はあったのですが、研究の忙しさなどを言い訳にして本気で勝ちにいくレベルで本腰をいれたことはありませんでした。また、新しく研究室に入ってくれたB3や、研究が進みだしたB4に対して、コンペ参加をいつも勧めていたこともあり、自分でも1回やり切っておく必要があると思いました。
そんなこんなで色々とコンペサイトを探していると、ちょうど夏休み期間中にSIGNATEでStudent Cup 2023が開催されるとのことだったので、参加することにしました。同時に、コンペに参加するにあたり以下のような自分ルール的なものを設定していました。
1. 1人で取り組む
2. 順位に言い訳をしない
コンペ自体はチームを組むことも可能だったのですが、今回の目的の1つは自身の実力を知ることでもあったのでソロで参加することを決めました。同時に、コンペ開催中に研究が忙しくなったとしてもそれを順位の言い訳にしないようにしました(当時、ジャーナルのサブミット前だったので、それを理由にサボることを防止する目的も含んでいました)。
> ちなみに[弊研究室の先輩](https://journal.peakers.jp/110530495/)もコンペで実績を収めています。
## コンペ概要
今回のコンペは「中古自動車の情報(車種・走行距離など)をもとに、中古車の価格を予測する」というものでした。基本的なテーブルデータであり列に特徴量、行にIDという形でした。コンペの基本情報は以下の通りです。
期間:2023年7月24日~2023年8月24日(木)
評価指標:MAPE

外部データ:緯度経度のみ利用可能
参加人数(投稿人数):530人
目的変数:中古車価格(price)
説明変数:
* 販売地域(region)
* 製造年(year)
* 製造メーカー(manufacturer)
* 状態(condition)
* シリンダーの数?(cylinders)
* 燃料(fuel)
* 走行距離(odometer)
* 状態その2?(title_status)
* 操作方法(transmission)
* 駆動(drive)
* サイズ(size)
* 車種タイプ(type)
* 色(paint_color)
* 販売州(state)
学生のみでしたが、かなり多くの人数が参加していました。ちなみに、となりでは社会人限定の[SIGNATE Career Up Challenge](https://signate.jp/competitions/1054)がまったく同じデータ・条件で開催されていました。こちらも参加人数は1038人でしたので結構な規模感のコンペだったと思います。
## 解法
今回の解法ですが、ポイントは大きく「前処理」「走行距離予測」「priceの2段予測」に分かれます。以降ではこのポイントを含めて試したことをなるべく簡潔に記載していきます。これから記載する内容はPDCAサイクルのように、ぐるぐると回っていることに注意してください。
### EDA(+ベースラインの作成)
コンペが始まった当初はEDAに時間を割きました。「Garbage In Garbage Out」と代表して言われるように、データ自体に対する理解が浅い状態では上位になれないことはよく言われていたため、ここは焦らずに解析にまわりました。ベースラインも一応作成はするのですが、サブミット形式の確認程度に留めました。
幸い、特徴量は少なかったので、目的変数×説明変数、説明変数×説明変数などをgroubyなどを含めて徹底的に可視化して分布を見ました。研究では画像を扱っているので、こういうテーブルデータの解析は新鮮味があって非常に楽しかったです。
### 前処理+特徴量エンジニアリング
EDAとベースラインのスコアを通して最終的に以下の前処理を実装することを決めました。
* manufacturerの表記ゆれの修正
* yearの記載ミスの修正
* regionを用いてstateの欠損値補完
* カテゴリ変数をtarget encoding
* その他欠損値は対象の車と似た条件をもつ他の行から補完(詳細は省く)
詳細に書き出すと終わらないので、超簡潔に書いていますが、要は基本的なことしかしていません。恐らく他の参加者の方々も似た前処理を施していたと思います。ただ、なるべく丁寧に実装することを心がけたため、このあたりでリークや漏れが発生していなかったのは、順位をギリギリまで上げてくれた1つの要因かもしれません。
### 走行距離予測
さて、前処理の中で最も重要だったのが走行距離(odometer)の予測です。EDAの段階でodometerが高い車のほうが価格が安くなることはわかっていました。その中で問題だったのが、複数の車のodometerが欠損していることでした。odometerが欠損している車の価格予測は非常に困難だったため、何かしらで値を埋める必要があると考えました。
そこで、LightGBMを用いてodometerを予測することを考えました。目的変数をodometerに設定し、その他の特徴量を説明変数に設定しました。工夫としてはカテゴリカル変数のターゲットエンコーディングを目的変数のodometerと、本来の目的変数であったpriceの2種類で行いました。odometerと相関のあるpriceの情報をなんとか使おうと考えた案だったのですが、結果的にodometerの予測精度向上に繋がりました。
これらの処理によってtrain.csvとtest.csvの両方からodometerの欠損をなくすことができ、最終的にprice予測においても一定のスコア改善が見られました。
### priceの2段階予測
次に着目したのは評価指標のMAPEでした。MAPEの式は上述の通り(正解-予測)/ 正解となっており、under-estimationをする分には誤差が1を超えることはありませんがover-estimationの場合は無限に誤差が増え続けます。つまり、機械学習モデルにはなるべく正確でありながら、なるべくover-estimationしない能力が求められます。幸いなことにLightGBMにはMAPEを最適化する設定が含まれていたのですが、これだけでは上位にたどり着くことはできませんでした。
そこで、priceを直接LightGBM(MAPE最適化設定)で予測するのではなく、一度別のLightGBM(RMSE最適化設定)で予測し、その予測結果を特徴量に加えた上でLightGBM(MAPE最適化設定)で予測する2段階予測を考えました。
簡単に意図を書くと、MAPEはプラスとマイナスの評価が平等ではないため、1段目にプラスマイナスを平等に評価する指標で作った予測を特徴量に加えることで、2段目はそこからの差分に注目すれば良いという考えです。ちなみに、このアイデアは以前[この本](https://www.amazon.com/Hands-Gradient-Boosting-XGBoost-scikit-learn/dp/1839218355)でブースティングアルゴリズムの勉強をしていたときの応用で思いつきました。詳細は省きますがアルゴリズムの基礎を抑えられていたことは非常に良かったように感じます。
最終的には他の多くの上位者もこの2段階予測を使っていたので、ここのアイデアがでるかどうかが1つの壁だったなと振り返って思います。
## 結果
最終順位はPublic6位くらい(忘れました)、Private2位という結果になりました。Shake upできたことは非常に嬉しかったです。しかも私以外のtop5はみんなチームだったので、結果発表後は「ソロでは1位だぜ」的な感じで調子に乗ってました。最初に決めた順位に言い訳をしないというのはどこへやら。。。
今年は残念ながら解法の発表が1位のみだったこともあり、表彰式で自身の解法をプレゼンする機会を得ることはできませんでした。ただ、1位の方の発表を聞く限りスコア以上に実力差はあったかなという印象は受けました。そのあたりは最後に記述します。
いずれにせよ2位を取れたことは非常に嬉しかったです。ちなみに賞金は5万円で、トロフィーがついてきました。いつかもっと大金をゲットできるように頑張ります笑

## 参加してみての感想
さて、参加した感想ですがやはり疲れました笑。現在は留学中のため昼間は8時間ほど研究をしながら、帰宅後と土日でコンペを進めるというスケジュールはかなりタイトだったと思います。特に、論文が佳境を迎えていたこともあり、心身ともに削った1ヶ月でした。ですが逆に、機械学習関連のことであれば自分の体は多少の無理を許容できることを自覚できました笑。
次に反省点ですが、結果に対する理解・解釈が足りなかったなと思っております。1位の方の解法を聞いていて驚いたのが、結果とその後の仮説・検証がしっかりと可視化できるまでに具体化されていることでした。特に、LightGBMのfeature importanceの解釈の部分はかなり参考になりました。私自身、得られた結果から次のアクションを決めるまでの一連の流れは相当にこだわるタイプだと思っていましたが、1位の方はもう一段高いレベルでした。ただ、こういったレベルの高い人の解法を聞けるのはコンペの良さだと改めて実感しています。
## まとめ
今回のコンペに関しての記事は以下になります。
* [プレスリリース](https://www.hrpro.co.jp/series_detail.php?t_no=3225)
* [表彰式](https://signate.jp/articles/signate-student-cup-2023)
近年では弊研究室のコンペ熱があまりなく(もとから多かった訳では無いが。。。)、個人的にはちょっと寂しい感じがしております。先輩方が卒業してからは特に参加者が減った印象を受けているので、この記事を読んで誰か1人だけでも興味をもってもらえたら嬉しいです。
ここまで読んでくださりありがとうございました!!
[法政大学理工学部 Advent Calendar 2023](https://adventar.org/calendars/8853)