Fire Engine

消防士→ITエンジニア→研究者

Kaggle初コンペの振り返り〜Riiidコンペで銀メダル獲得〜

Kaggleで開催されていたRiiid! Answer Correctness Predictionに参加しました.結果を簡単にまとめると以下の通りです.

  • 順位:139位(3406チーム中)
  • メダル:銀メダル(上位5%以内)
  • 解法:LightGBMとSAKTのアンサンブル
  • チーム:1人で参加

自身初となるデータ解析コンペでしたが,なんとか銀メダルを獲得することができました.今回はその振り返りを時系列で書いていきたいと思います. 先に感想を述べると,Kaggleは本や論文ではなかなか得られない学びに溢れている上に,世界中の人々と順位を競い合うゲームのような感じでとにかく楽しいので最高すぎました. この記事がこれからKaggleを始める方々の参考になれば嬉しいです.

目次

Kaggleとの出会い

Kaggleの存在を知ったのは4年くらい前ですが,Kaggleを始めるきっかけとなったのは2020年11月に開催された第23回情報論的学習理論ワークショップ (IBIS2020)という学会でした.IBIS2020のチュートリアルセッションにて「Kaggle・実践データ解析入門」という発表がありました.この発表では,Kaggleの称号の最高位であるGrandmasterを持つ登壇者の方が,Kaggleの概要や,「こういうデータのコンペでは初手としてこういう手法が有効である」といった実践的なテクニック,研究や論文の成果をどのようにKaggleに使っているか,など非常に興味深い内容が盛り沢山でした.動画や資料は公開されていませんが,Kaggleの概要の部分に関しては,発表中で紹介されていた以下のスライドがまとまっています.

結局、Kagglerは何を必死にやっているのか? / What is Kaggle? - Speaker Deck

この発表を聞いて,単純に「Kaggle面白そう!」と思いました.さらに,Kaggleでは最新の研究や論文の成果がどんどん実戦で使われていることを知り,Kaggleと研究に繋がりが見えたことが始める大きなきっかけとなりました.実際に登壇者の方は常に最新の論文から新しく提案された機械学習モデルをチェックしていて,精度が良さそうなものがあれば,論文を読みながら実装してKaggleで実戦投入するといったことをやっているようです.現在私は,さくらインターネット研究所で,機械学習をソルバーとして用いて自分たちのドメインクラウドコンピューティングなど)における課題を解決する研究に取り組んでいるため,機械学習を用いた問題解決能力は研究に直結します.そのため,Kaggleを通して最新のモデル,かつ提案論文内での評価とは異なるデータで実用性が検証されているモデルを把握しておくこと,また実践を通じて自身の問題解決能力を高めることは,研究活動に大きく貢献するだろうと確信しました.そんなこんなで興味を持ってすぐにアカウントを作ってKaggleを始めました.

コンペ参戦準備

Kaggleを始めるといっても,コンペへの参加の仕方さえ分からなかったので,まずはKaggleの全体像を掴むところから始めました.具体的には,以下の本を一通り手を動かしながら読みました.

実践Data Scienceシリーズ PythonではじめるKaggleスタートブック (KS情報科学専門書)

この本は,Kaggleをゼロから始める人にとっては非常に良い本で,アカウント作成からコンペへの参加,予測結果のSubmitまでの流れを一通り学ぶことができるため,初めてのコンペ参加へのハードルをかなり下げてくれます.

コンペに登録

Kaggleスタートブックを読み終えた時点ですぐにコンペに参加登録をしようと思い,良さそうなコンペを探しました. Kaggleスタートブックの中で初めてのコンペを選ぶときのコツとして,「すでに開催から一定時間が経過していてコンペ終了まで一ヶ月程度のコンペがおすすめ」と書いてありました.その意図としては,開催から一定時間が経過していると,Discussionや公開Notebookなどの充実した情報が集まっているので,それを参考に自分のモデルを作ることができるためです.これを参考にRiiid! Answer Correctness Predictionに登録しました.コンペの概要は以下の通りです.

  • 開催期間:2020/10/06〜2021/01/08
  • データ:TOEICの学習アプリで各ユーザが過去に取り組んだ問題とその問題に正解したかどうかのデータ
  • 問題:将来あるユーザはある問題に正解できるかを予測する二値分類問題

このような人間の知識の習得をモデリングする問題はKnowledge Trackingというそうで,教育分野では重要な問題なようです.
私がコンペに登録したのが2020/11/25で締切まで約1ヶ月半程度全力で取り組みました.ちなみに,取り組んだ時間としては,毎日寝る前2~3時間程度で,大晦日は格闘技を見るためにやりませんでしたが,それ以外は休まず毎日やりました.

初Submit

まず簡単な特徴量とモデルでSubmitまでやってみようと思ったのですが,このSubmitまでが鬼門でした. 本コンペは,KaggleのNotebook環境を用いてSubmitする必要がある「Code Competition」と呼ばれるコンペでした.このコンペの特性上,以下の2点がSubmit時の大きな制約となりました.

  1. Notebook環境のメモリ上限は16GB

  2. Notebook環境上での予測時間は9時間以内(テストデータは250万行)

この2点の制約により,機械学習やデータサイエンスの力だけでなくエンジニアリング力も試されました. まず,メモリ上限についてですが,学習データのCSVファイルを普段通りpandasでread_csvしたところ,読み込みに数十分かかる上にメモリが上限の16GBを超えてしまいエラーになりました.というのも学習データのCSVは,行数が1億を超えていました.さっそくデータの読み込みさえできずに焦りましたが,公開Notebookに「Tutorial on reading large datasets」という素晴らしいNotebookがあり,データ型をきちんと指定することや,読み書きが早いファイル形式を利用することなど知見が溜められていました.

次に,予測時間の制限についてですが,私は最初,学習データで作った独自の特徴量をPandasのDataFrameで保持し,テストデータに対してPandasのmerge関数でLeft joinすることで特徴量を追加していましたが,どうやらこのDataFrameのjoinの処理が遅いらしく,推論時間を9時間以内おさめることができませんでした.これもまた素晴らしいNotebookに助けられて「LGBM with Loop Feature Engineering」に特徴量を辞書型で保持し,テストデータのDataFrameの行に対してfor文を回し,特徴量を追加していくといった手法でした.これを真似ると推論時間は大幅に改善されました.このように悩んだことがあっても多くのKagglerが有益な情報を公開してくれていて学びながら取り組んで行けることもKaggleの魅力だと実感しました.(補足:Pandasのleft joinを357倍高速化したというNotebookも公開されていてこちらも参考になりそうですがコンペ中は追いきれませんでした)

これらの問題を解決して,やっとSubmitまで行き着きました.モデルには,LightGBMを選択しました.LightGBMは,ここ数年のテーブルデータのコンペの初手として多くのKagglerが用いているようです.なぜ初手にLightGBMを用いるかについては,以下の記事にわかりやすくまとまっていて非常に参考になります.

upura.hatenablog.com

初Submit後にLeaderboard(コンペの順位表)に自分の名前が載っているのを見てとにかくモチベーションが上がりました.

特徴量エンジニアリング

コンペ期間において一番時間を割いたのは特徴量エンジニアリングです.まずは簡単に思いつくようなユーザの正解率や,問題の正解率など,直感的に有用そうな特徴量を追加していきました.あとから知ったのですが,これはTarget encodingと呼ばれる特徴量生成のテクニックでした.Target encodingとは,説明変数に含まれるカテゴリ変数と目的変数を元にして特徴量を作り出すことです.
ここでTarget encodingにより明らかに有効そうな特徴量を追加して手元のスコアが上がっているのに,Submitしたスコアが全然上がらないという問題に悩まされました.これはTarget encodingにおける定番的なミスで「リーク」という問題を起こしていました.例えば,ユーザの正解率という特徴量を作るときに,学習データ全てを使って算出したユーザの正解率を特徴量として使うと,ある時点では将来の情報が漏れていることとなってしまい,精度が過剰に高くなってしまいます.そこで,ある時点のユーザの正解率はそれより過去のユーザの問題の回答から正解率を算出するように変更したところ,手元とSubmit時のスコアに相関が取れるようになりました.私はこれまで数年ほど機械学習の勉強をしてきたのにいざ実戦でやってみると知らないことが多いなと辛い気持ちになりましたが,これが成長というやつです.
自分がコンペに取り組む上で重要な知識が欠落していること認識したので,知識を補うために以下の本を読みました.

Kaggleで勝つデータ分析の技術

この本は,Kaggleのコンペに取り組む上で必要な情報が網羅的に書かれていてめちゃくちゃ参考になりました.前述のTarget encodingのリークの話もしっかり書いてありました.この本を参考に思いつく特徴量をどんどん追加していきました.最終的な特徴量の数は30~40程度でした.

モデルの構築

モデルは,最初のSubmitの時に採用したLightGBMを主に使っていました.特徴量エンジニアリングの成果が出て,早い段階でLightGBMのシングルモデルで銅メダル圏内に届きました.しかし,特徴量エンジニアリングが行き詰まってきてスコアの伸びが小さくなってきたので,モデルのパラメータチューニングに着手しました.パラメータチューニングにはOptunaを用いました.

github.com

Optunaには,LightGBMに特化したLightGBM Tunerという拡張機能があり,Pyhtonコードのimport文を1行変更するだけで簡単にチューニングができて便利でした.しかし,このチューニングはスコアにはあまり貢献しませんでした.
この点については,コンペのDiscussionの「LGBM Parameter Tuning」で議論が展開されており,パラメータチューニングは大きく精度に貢献しないことなどが書かれていました.このようにコンペ開催中にも惜しみなく知識や経験を共有する文化は素晴らしいと思いました.
締切まで残り3週間程度の時期にLightGBMのスコアが停滞してきたので,この時点で他の学習モデルの検討を始めました.

アンサンブル学習

LightGBM以外の学習モデルには,TransformerをベースにしたSelf Attentive Knowledge Tracing(SAKT)を選択しました.その理由は,公開されているNotebookの中で,LightGBMなどの勾配ブースティング系とSAKTのアンサンブル学習で大きくスコアを伸ばしているものがちらほら見つかったためです.SAKTは以下の提案論文と公開Notebookを読みながら実装しました.

arxiv.org

SAKTの実装は完了したものの,LightGBMのスコアには到達しませんでした.しかし,アンサンブル学習を試してみると一気にスコアが伸び,そのときの順位で100位くらいで銀メダル圏内に到達しました.アンサンブルの方法は単純な加重平均で,この時点でのスコア的にはAUCでLightGBMが0.778,SAKTが0.772で5:5のアンサンブルをすると一気に0.786まで上がりました.
このようにモデルのアンサンブル学習を行うと,単体のモデルの最高スコアを大きく上回ることが起きうるというのは「Kaggle Ensembling Guide」を読んで知っていたのですが,どうも直感的には低いスコアの方に引きづられそうな気がしていました.ただ,結果を見ると,これがアンサンブル学習の力か…となりました.また,ここでスコアを大きく向上させられた大きな要因として,アンサンブル学習を行ったのが勾配ブースティング系のモデルと,ニューラルネットワーク系のモデルの異なる種類のモデルをアンサンブルさせたことだと思われます.これもアンサンブル学習にはモデルの多様性が重要であるとよく語られることではあるのですが,本などで学んだこともこうやって実際に体験すると,より知識として定着するので実践から学ぶのは良いなと改めて思いました. あとはコンペ終了まで,ひたすら特徴量エンジニアリングを頑張ってLightGBMとSAKTのアンサンブルでスコアを出すというのを繰り返していました.

コンペ終了:Leaderboardの公開

2021/01/08の午前9時にコンペが終了し,最終的なLeaderboardが公開されました, 結果は3406チーム中139位でなんとかソロで銀メダルを獲得できました.

f:id:hirotsuru314:20210108230540p:plain

コンペ全体を通しての感想と今後

初コンペを終えた感想としては,Kaggleはとにかく学びが多くて,とにかく楽しいので,これからもKaggleを続けていこうと思いました.当初は初コンペでメダルが取れたら嬉しいなーくらいの気持ちでしたが,いざ銀メダルを獲得すると,嬉しさよりも,上位陣との歴然の差を目の当たりにした悔しさの方が勝っていました. 銀メダルというと一見あとちょっと頑張れば金メダルだと思えるかもしれませんが,そこには大きな壁があり,コンペ期間中一度も金メダルにかすりそうな瞬間はありませんでした.さらにコンペ終了後に公開された上位の解法にざっと目を通しましたが,どんな頭しているんだと思うくらいすごくてさらに悔しい気持ちがこみ上げてきました.ただ,こういった悔しい経験がどんどん自分を強くしていくので勝てなくても参加するのが大事だと思いました.これからコンペの上位解法をしっかり読んで勉強します.
今後は,自分もコンペで優勝争いをしたいし,いずれは最高位であるGrandmasterにもなりたいです.そのためにもまずは次のコンペでもメダルをとってKaggle Expert(銅メダル以上2個)を目指します.
長くなりましたが最後まで読んでいただきありがとうございました.Kaggleやっていきましょう!