1年かけてKaggle Expertになった話(+Riiid参戦期)
こんにちは!今関と申します!
これがはてなブログ初投稿です!
この度、Kaggleにて開催されていたRiiid! Answer Correctness Predictionで無事、銅メダルを獲得し、メダル銀1銅1でKaggle Expertに上がれました!正直言うと、嬉しさよりも悔しさの気持ちの方が大きいのですが、めでたいことはめでたいですね!笑。
今回、皆さんがriiidのソリューションを投稿されているのに乗じて自分も投稿しようと思ったのですが、「大したことしてなさすぎて中身がスッカスカだ...」となったので、Expertになったしせっかくだからこれまでどんなコンペに参加して、そこでどんなことしてきたのか、ざっくり振り返りつつ、おまけでriiidのソリューションを書いていきます。
ちなみに自分の経歴を簡潔に書くと、社会人からエンジニアデビュー(SIerのSE)して、2019年2月に一度目の転職でデータサイエンスのようなお仕事をするようになり、2020年10月に二度目の転職で現在はデータエンジニアの端くれとしてぬくぬく生きております。現在、社会人4年目です。
DSBにてKaggle初参戦
自分が初めて参加したKaggleコンペは2019 Data Science Bowl(以下、DSB)でした。ちょうど1年前に開催されていたコンペですね。多クラス分類問題でクラス間に順序関係があるコンペでした。
Kaggleの存在は一度目の転職当時から知っていたのですが、実務が慣れてきた頃に参戦すればいいやと思っていて、結局転職後に半年以上経ってからの参戦でした。今思えばもっと早く参戦すれば良かったなと反省しております。
当時の自分は、実務ではLightGBMやXGboost、CatBoostは使ったことがなかったレベルです(ランダムフォレストは使っていましたが)。機械学習系の知識も疎い中、参戦当時のハイスコアカーネルをフォークして、それを読んで、分からないところは調べ、自分の考えた特徴量を足していくということをしていました。DSBに参戦していた人はご存知だと思いますが、評価指標がquadratic weighted kappa(QWK)と言い、これに色々悩まされましたが、世界中の人と競い合うことに楽しさを感じられたコンペでした。
スコアを上げていくにあたって、こちらのKaggle本が非常に参考になりましたこの本を読んだおかげでハイスコアカーネルなどを見た時に何しているのかもスッと理解できたような気がしています。
最終的な結果はソロ銀という初めてにしては上々のものになりました。
ただ上記画像を見て分かる通り、めちゃくちゃシェイクアップしてます。当時、Public LBにoverfitしているハイスコアカーネルがあり、それを使用していた人らが軒並みシェイクダウンしたことがおそらくこの結果になったのかなと思います。斯く言う自分もその毒入りカーネルを使用していましたが、コンペ中盤に出していた毒なしカーネルを最終subの一つに選んでおり(ちなみに選択していたことはすっかり忘れていました)、それがたまたまこのような結果になったということです。
実力で勝ち取ったメダルではなく、完全に運勝ちしたコンペでした。ただ、初心者にとって学びとして得るものは大きく、参加して良かったなと思っております。
コロナ禍の中のバスケコンペ
次に参加したコンペはこちらのバスケコンペです。自分は女子大会の方に参戦しました。DSBでKaggleの楽しさを知った自分は終わってすぐこちらのコンペに2月から参加しました。
DSBでは運でメダルを勝ち取りましたが、今回はちゃんと自分の実力でメダルを取りに行こうと思っておりました。また会社の同僚と一緒にチーム組んで参加したコンペであり、とても楽しいコンペでした。
バスケコンペは毎年開催されており、昨年のコンペでよく使われていたカーネルをフォークしてきて、それをベースに特徴量を作成していました。使用していたモデルはXGboostです。
生データを細かく見たり、レーティングシステムのことを調べたりなどして個人的には満足のいく特徴量を作成できました。こちらはPublic LBがほとんど意味をなさない(最終sub後に開催される大会の結果がLBになる)ため、昨年までのコンペだったら結果としてどうだったんだろうという形で様子を見ていました(もちろん、当時の大会結果のデータは学習時に含めないように注意しながら)。一応推定でしかないのですが、おそらく銀程度、少なくとも銅は狙えるんじゃないかと自分で思える程度のモデルは組めました。
「これでメダル取れたら運勝ちじゃないよな」と思って大会開催を待っていたのですが、当時流行り始めていたCOVID-19によって大会自体が中止に、もちろんコンペも中止となりました。
中止になった日、悔しすぎてお酒をバカ飲みしました。
初めての自然言語処理コンペ
前回のバスケコンペで不完全燃焼をし、少々モチベが下がっていたので1ヶ月の間を置いて5月頃、Tweet Sentiment ExtractionというNLPコンペに参戦しました。
なぜこのコンペを選んだかと言うと、実務でNLP案件に4月から入っており、そこで学んだことが活きるかも、逆にこのコンペで学んだことを実務で活かせるかもという理由です。
結論から言うと、スコアは全く上がりませんでした...
上位のソリューションを見ると、magicに気付けるかどうか(今回はデータのノイズに見えていた部分が実はある規則に則っていた)が主になっており、これに気付けるかどうかのコンペに感じました。もちろん、自分の実力不足もありましたが...
反省すべきことは反省して、さっさと別のコンペに参戦しようと当時は考えていました。Pytorchを使って色々データやモデルをいじったり、BERTなどのNLPモデルに触ることができたので、その点では色々学べて良かったなと思っております。
ちなみにこのコンペが開催されている間に、atmacup#5に参加しており、そちらでは個人的に納得いく結果を得られており、次のコンペでは二度目のメダルを獲得しようと意気込んでおりました。
迷走した小麦コンペ
二度目のメダル獲得を目標に参加したコンペがこちらの小麦コンペになります。前回のコンペでPytorchに慣れたので、次もPytorchなどを使ったDL系のコンペに参加しようと思い、選びました。画像にも慣れておくことで、自分のできることの幅を広げておこうとも考えていました。自分は7月上旬から参加しました。
Data Augmentationの部分など、NLPでは中々やりづらい部分を画像で経験でき、とても楽しかったのを覚えています。全くスコアを上げられなかった前回のコンペに比べて、時間はかかったけど、少しずつスコアが上がっていくのも良かったですね。
自分がケチ付けられるレベルではないことは百も承知で言うのですが、このコンペはデータのラベリングが酷かったり、コンペ終盤(終了まで残り1ヶ月を切った頃)に使用してはいけないモデルを指定されたり。自分もそのモデルを使用してメダル圏内に入っていたので、ショックだったのを覚えています。
ちなみにデータのラベリングはPrivate LBのデータのみ修正されたそうです。ということはPublic LBのスコアはそこまで参考にならないなと思いました。また、そのPublic LBは禁止されているモデルのスコアが反映されているため、順位さえも当てにならない状態に。
手元の学習データの特に酷い部分は修正していたものの、学習データの全てを修正できるほどの時間はなかったので、CVもLBも完全には信用できない状態で暗闇の中を進んでいる気持ちでした。
最終的な結果は、メダルまでもう一歩というところで終わりました。これで取れてもまた運勝ちになってしまうし、これはこれで良かったかなと考えています。もちろん、実力ある方は上位にいらっしゃいますし、取れなかったのは自分の実力不足ですね。
この後、Riiid参戦まで3ヶ月以上経過しています。NLPコンペのmagicといい、小麦コンペの運営に少々嫌気を感じており、モチベが下がっていました。
ちなみにこの時期に、データエンジニアリングに興味が出てきており、そちらの職種に転職しております。
そしてRiiid参戦
小麦コンペが終了してから3ヶ月、データエンジニアに転職して、直接モデルをいじることはないだろうなと思いつつ、モデルを構築する経験はこの職種でも活きるだろうと思い、Riiid! Answer Correctness Predictionに参加しました。あと一歩でExpertになれるというのもモチベーションの一つになっておりました。
11月下旬〜12月上旬
はじめは久々に機械学習モデルをいじるので、リハビリを兼ねつつ、当時ハイスコアカーネルだったこちらのノートブックを読んでいました。
読み終えて、中身の処理を理解した後、自分で考えた特徴量を実装して学習させようとしたのですが、メモリエラーやタイムアウトの連発でスコアを全く上げられませんでした。pandasに入っているデータを1行ずつループさせており、特徴量を作成しているので、新しい特徴量を追加したら、そうなるのは当たり前ですよね...
当時はストレスが溜まりに溜まって仕事にも支障が出そうになっており、やめようかと思っていました。
12月中旬〜下旬
やめようかなと思っていた矢先、別のハイスコアカーネルが登場しました。
こちらのカーネルはpandasのデータをcumsum, cumcountなど、累積和を取るように特徴量を作成しており、こちらであれば、自分でも特徴量を追加してもメモリエラーはある程度減るだろうと思いました。というかこういうのはちゃんと自分の方で思い浮かばなければいけませんよね...勉強になります...
また、上記カーネルとSAKTをアンサンブルしたノートブックが公開されます。
当時のハイスコアカーネルはこちらなのですが、各モデル単体ではそれらより高いモデルが公開されておりました。それらのアイデアを自分のコードに追加していくことで、メダル圏内に入りました。
また参考にしたコードでは、LGBM学習時に全データを使用するとメモリエラーになってしまうため、2割ほどサンプリングして学習しています。モデルのfeature importanceを見ると、低いものもあるので、それらを特徴量から除外することで学習データのサンプリング量を増やしました(0.2->0.25~0.3)。これでもCV, LBのスコアは向上しました。0.5割から1割増えたと言っても、元データが1億件近くあるので、数百万から1000万件ほど増えています。
その他にもDiscussionや他の公開カーネルを色々眺めたり、自分で考えて良さそうなアイデアを実装していきました。ここでもうすぐ銀圏というところまで上がってきます。
ただ若干アイデアが尽き初めてきたのもこの時期でした。
ちなみに自分がメインでいじっていたモデルはLGBMです。SAKTの方はキャッチアップする時間が確保できないと判断し、ほぼいじっておりません。
1月
コンペも終盤になって自分は前から考えていた策を実行することにしました。それは、AWSで256GBメモリのインスタンスを立てて、LGBMを学習させるというものですAWS Deep Learning AMIを使えば、簡単にjupyter notebookサーバーを構築できることも知っていたので、こちらを使ってモデルの学習を再開しました。ちなみに自分のlocal PCはメモリが16GBしかないです...
こちらのインスタンスを利用することで学習時間は相当膨らみましたが(特徴量にもよるが6時間〜12時間程度)、1億件近いデータのほぼ全てを使用して学習を始めました。
これによってLBは銀圏に滑り込みます。
しかし、周りもスコアを上げてきていたので、すぐに銅に落ちてしまいました。
その後、kaggle上ではメモリが落ちるから諦めていた特徴量の実装を始めますが、一部しか実装できずにコンペが終了してしまいました。結果はこのブログの冒頭で述べたように182位で銅でした。
もう少しで銀という結果に悔しい気持ちはもちろん、金までの道のりの遠さを感じました。このコンペでKaggleは最後でいいかなと思っていましたが、また少ししたらどこかのコンペに参戦していそうです。実業務で活きるかは分かりませんが、SAKTやSAINT+の論文などを読んで実装してみることにも挑戦してみようかなと思います。今まで論文を読んでの実装は「まだ自分はそのレベルじゃない」と逃げていましたが、やってみて足りないものがあるんじゃないかと思い、挑戦してみようかなというお気持ちです。
ちなみにすごいどうでもいいことですが、Riiidのモデル学習中にFE風花雪月、ゼルダの伝説BotWをクリア、チェンソーマンを一気読みしていました。
これだけやっておけばメダルは取れる??
さて、半分運の力を使いつつ何とかKaggle Expertになれた自分ですが、メダルを取るために初心者がやるべきことを列挙しておこうかなと思います。これだけやっておけば、コンペによってはメダルを取ることくらいはできるんじゃないかなと思います。少なくとも自分がメダル取れた時にやっていたことは下記だけです。もちろん、コンペの内容や場合によっては運も絡みますが...笑。
ただ自分が参加していて感じたのは、金圏に入るような上級者たちはおそらくハイスコアカーネルをフォークするのではなく、自分で一からコードを書いている気がします(少なくとも自分で実装ができる)。
自分も次参加する時は可能な限り、自分でコードを書いたり、論文読んでそれを実装してみたりしながら金圏を目指したいなと思います。
終わりに
Kaggle、勉強目的で参加しましたが、思っていたよりも楽しいですね。コンペ中は辛い時もありますが。
正直、自分よりも後にkaggleを初めて、自分より早くExpertになっていたり金メダルを獲得している人をたくさん見ていて、自分の実力不足を痛感しまくっていますが、焦らず頑張っていきたいと思います。
思ってた以上に長くなってしまいましたが、読んでいただき、ありがとうございます。
拙い文章ばかりですみません...