🀄

Kaggle Competition Grandmasterになるまでを振り返る

2024/03/11に公開

0.はじめに

こんにちはchumajinです. kaggle profile, X(旧twitter) profile.

本記事は、Kaggle Competition Grandmaster(GM)になったので、その振り返り記事です.私は、kaggleを始めたときは、「俺はGrandmasterになる !!」なんて、ONE PIECEのルフィみたいな大きな志をもって始めたわけではなく、まさか自分がGMになれるとは思っていなかったので、何か参考になる箇所があれば嬉しいです。2024.3.1の関西kaggler会のLTで、本内容を以下のポイントで重点的に話しましたので、この内容を踏まえて、書いていきます!

  • 強くなれたと思えるイベントが確かにあった。
  • 高かった金メダルへの壁を乗り越えた話。
  • 人生で一番苦しかったソロ金取った時の話。

※ いろいろまとめてたら、長くなってしまったので、飽きてしまったら、適当に飛んで読んでもらえば幸いです!

※ このGrandmasterになるまでを振り返るシリーズはたくさん出ていてGMのなり方は人それぞれですので、以下は自分の場合はというところにご注意ください!

1.自己紹介

  • CompetitionとNotebookの2X Grand master。
  • 応用化学科出身
  • もともとは、工場の欠陥検査装置担当から、kaggleなどをやってデータサイエンスグループ立ち上げして、テーマ長に就任。
  • 趣味は、海外旅行、麻雀(天鳳もと6段)、サッカー、Splatoon、モンハン(昔は称号コンプリート目指して、最小金冠うぉぉぉとかやってました)、他、読書など。

1.1 Kaggle Competition 自分年表

2019年11月にkaggleを始めて、Contributor半年、Expert2年、Master1年4カ月、Grandmasterまで約4年間かかったという経歴です。この絵を見てわかるとおり、いきなり金メダルを取ってしまうとかそういうタイプではなく、kaggleの中で、成長していったタイプの人間です。

1.2 継続の意味

立ちはだかる壁ランキングを作ってみました。

  • 1位 ソロ金
  • 2位 初めての金メダル
  • 3位 初めての銀メダル

年表を書いて、思ったことはkaggleの継続の意味です。kaggleは継続が大事と他の方の発表でも言われてますが、私の場合、なぜ継続が大事かというと、実績が変わると気持ちも変わるからだと思いました。例えば、銅メダルをたくさん取ってくると、もう銅メダルはいらない、銀メダルをたくさん取ってくると、もう銀メダルはいらない、そして、金メダルを2枚とると、ソロ金いけるのでは?となり、ソロ金を取ると、グランドマスターいけるのでは?となりました。

結果として、kaggleを始めたときは、自分がグランドマスターになるなんて、夢のそのまた夢くらいでしたが、実際になることができました。なので、継続することはやっぱり大事だと私も思います。

1.3 強くなれたと思えたきっかけランキング

強くなれたと思えたきっかけランキングも作ってみました。

  • 1位 Petfinder2コンペでぼろ負け
  • 2位 kaggle daysでの決勝進出
  • 3位 ソロ金
  • 4位 素人が一瞬publicで1位になったこと
  • 5位 初のチームマージ

年表を振り返ってみると、確かに、この辺から自分が強くなれたときっかけになったポイントが確かに存在していたと思います。この辺も踏まえて、以下、初めから振り返っていきたいと思います!

2. kaggleとの出会い

社内の研修がきっかけでした。社内の未来予測プロジェクトに参加して、新規事業の提案か社内改革か、どちらかに挑戦しましょうという研修でした。その時のプロジェクトリーダーがイケイケで、社内にkaggleに参加するサークルを作ってみてはどうかと声をかけてもらって、もともと画像処理や、機械学習に興味を持っていたので、社内サークルの設立を、pythonも覚えたて、kagglerの知り合いもなしという状態からやってみることにしました。

3. Novice & Contributor時代

3.1 初sub & 初参戦 - kaggleって楽しい -

初subはNFL Big Data Bowlで、単にCopy and editしただけでした。何もわからず、何かスコアが出るのが楽しかった記憶があります。

このNFL Big Data Bowlコンペに社内でチームを作って、参加しました。もうほとんど覚えていないのですが、確か、public notebookを基に初めて、斜め成分のベクトルをx方向とy方向に分けて、特徴量を生成しただけだったのはなんとなく記憶にあります。メールを見返したら、このころ、xgboost? 勉強しておきます… なんて、今見たら、当時の自分は、めちゃくちゃ可愛い初心者に見えました。

このコンペは最後のsubmitを選択してから、約1カ月実際のデータに基づいて最終ランクが決まり、202位(204位までが銅メダル)で、本当にぎりぎりで最初から銅メダルを取ることができ、メダルを取る爽快感をこのときはじめて覚えました。これは運が良かったと思います。

3.2 銅メダルとれない時期 -そりゃ勝てない-

3.1の後、ASHRAE、Peking University/Baidu、Deepfake Detection Challengeに出たが、全く銅メダルはダメでした。このころを振り返って考えてみると、そんなにkaggleにやる気があったわけではなく、そりゃ取れないよなという行動をしています。

ASHRAE、Baiduに関しては、マジで記憶がなく、ほぼやっていないと思います。Deepfakeはけっこうやった気がしますが、完全に実力不足でした。

3.3 Competition Expert昇格 -まさかのteam merge expert-

今、振り返ったら、完全にThe team merge expertでした…。TReNDSコンペは社内の人が参加していて、チームに入れてもらっていましたが、自分は、M5 forecastingコンペに出ていたのもあって、ちょっとデータを触って、weight 0 で社内の人がソロで銅メダルを取っていました。。。kaggleいろいろなコンペ出ていますが、これが唯一、チーム組んでも何も貢献できなかったときでした。

これもkaggleの一面だと思いますが、お恥ずかしい。。

この後すぐ、一応M5 forecastingでソロで銅メダルを取り、一応名誉挽回 (?)といったところです。

4. Expert時代

M5 forecastingでソロで銅メダルを取った後、Riiidに社内チームで参加しました。ほぼほぼ1人でsubしていたのですが、これで4枚目の銅メダルを取りました。このコンペは面白かったです。

このあとは、もうめちゃくちゃでした。

  • Cassavaでめちゃくちゃリークしてて、shake downを経験。

  • Shopeeを触るも 距離学習って何 ?? 状態で、チンプンカンプンの状態で終了。

  • Coleridgh Initiativeコンペも、EDA書くも何が何だか…で終了。

ただ、このときくらいから、社内サークル内にコンペの解法をまとめてプレゼンしていたり、transformerって何?、距離学習って何?みたいなことを説明していました。これはあとあと、とても役に立ちました。サークルの代表だったので、定例で、ある意味強制的に、機械学習やったことない人にも、説明しないといけない環境だったので、ある程度説明するために勉強することが必要でした。この時聞いてくれたメンバーには感謝しています。

4.1 銀メダルの壁 - 立ちはだかる壁ランキング3位 -

そんなこんなで、そろそろ銀メダルが欲しいと思っていました。なかなかpublic leadersboardを駆け上がることができず、苦戦していました。そんな中始まった1回目のCommonLitコンペ。自然言語処理で、3年生から12年生までの教室で使用する文学文章の複雑さを評価するコンペでした。結論から言うと、public notebookを5個ensembleしただけで、shake upして、初めての銀メダルを取れてしまいました。自分で作ったモデルは全然精度が上がらず、ダメでした。ただ、100回以上subしていて、これまでで一番頑張ったコンペだったと言えました。

※ ちなみに、1回目のCommonLitコンペで初めての銀メダルを取って、2回目のCommonLitでGrandMasterになったので、CommonLitコンペは良い思い出です。

※ takoiさんの2nd solutionは、この後のコンペでも何回か参考にさせてもらいました。ありがとうございます。

4.2 まさかの素人が、一瞬public1位に。 - LightGBMしか使えない男 -

MLBコンペ(Table)。Tableで、MLBプレーヤーのデジタルエンゲージメント(おそらくtwitterやFacebookなどから選手の注目度や人気度を指標化したもの)を予測するコンペでした。hostとkaggle staffが解説したEDAをLightGBMで推論ができるように、編集したら、まさかの序盤public 1位になりました。うぉぉぉーーとなって、普段、仕事でもこんなに本気になることはなかったくらい、この順位をkeepするように、頑張った記憶だけあります。しかしながら、この時はスキルが伴わないませんでした。1dcnn、LSTMやTransformerなどのニューラルネットワークもできないし、Catboost、XGBoostもきちんと組むことができませんでした。結局、targetにlogを使ったりなどの工夫はしたけれど、全然およばず、ソロ銀で22位。けど、一度金圏を経験して、実力が足りないながらも金メダルを意識できたのは良かったし、前回とは異なり、特徴量はともかく、自分で作ったモデルではあったので、少し成長できた気がしました。

4.3 人生を変えた ? Petfinder2コンペ。 - 強くなったと思われるきっかけ1位 -

Petfinder2コンペ(画像)。画像コンペで犬と猫の写真のPawpularity(人気度)みたいなものを100点満点で予測するコンペでした。これを強くなったと思われるきっかけ1位にしてます。その理由としては、以下のとおり。

  • 休み中ずっとやっていた(友達と温泉旅行中もやっているやばいヤツだった。)
  • ソロ銀だけど、負けたのが、悔しくて、このコンペをきっかけに復習することを始めた。

恥ずかしながら、モデルをたくさん作ったものの、どのモデルを使ったらいいかとかの判断がこのときはできなかったです。なので、コンペ終わってから復習したChris Deotteさんdiscussionに、このとき悩んだことが全部書いてあって(Trust CVとか、Climb hillとか)、ここから復習することを開始しました。

ここは大きなターニングポイントで、このときから、

とにかく 一生懸命コンペやる → 復習する → outputする → それを次の武器にする ということをやりだしました。

おそらくこれが今でも、最強のコンボだと思っています。

4.4 金メダルへの壁 - 立ちはだかる壁ランキング2位 -

このpetfinder2コンペの前後では、ソロでも銀メダルは安定的に取れて(Google Brain、1回目のOptiver、1回目のFeedback prize)、銀メダルも6枚になりました。しかしながら、金メダルへの壁が本当に高かったです。この時は、2つのことを考えていたと思います。

  1. ソロではまだ金メダル取れる実力がない
  2. 社内のチームマージではモチベーションとかも違うし、金メダル取れそうにない。
    (このへんは仕事・家庭・プライベートもあるからしょうがないです)

そこで、社外でのチームマージを検討して、野良で同じ目的の仲間を探すことにしました。また、このときから、NLPに絞って、コンペに出るようにしたと思います。理由は、復習すると、強くてニューゲームができるからでした。あと、特筆すべきと思ったのは、いつもnakamaさんの神notebookに助けられました。初めはそれをbaseに作成していましたが、最後の方は自分で作ったのと何が違うんだろうと比較しながら、進めさせていただきました。本当にありがとうございました!!

4.4.1 初めての社外でのチームマージ - 金圏からのshake downで悔し涙 -

NBMEコンペ(NLP)。患者メモに含まれる特定の臨床概念を予測するコンペ。このコンペで初めて野良でチームを組みました。ソロで、金圏少し下までいったが、そろそろチームを組みたいと思っていました。金圏にいたharshitが、声をかけてくれて、チームを組みました。彼とは、今でもkaggle以外のプライベートのメールもするし、自分にとってはkaggleの中でのキーマンであることは間違いなかったです。このときのチームメンバーが、疑似ラベルでのtrainingを1epochだけやって、そのあと、本物のtargetでfine-tuneするという技を使っていて、それと、自分の過去コンペのSolutionを混ぜ合わせたモデルで一気にpublic2位まで上がりました。
https://x.com/ChuMajin/status/1517671292769796097?s=20

これはさすがにいけるだろう!と思っていました。しかしながら、日本にはゴールデンウィークというものがあって、ここから、日本人の方の追い上げもすごく、結果、public10位で終了。頼む !!!!! 神様 !!!! となっていたが、結果は残念ながら14位で銀圏に落ちてしまいました。締め切り前夜に思いついたアイデアがcvもpublic lbも上げたが、それはoverfitしていて、それがなければ取れていたとめちゃくちゃ後悔もしました。完全に実力不足。今やれば勝てたと思います。

4.4.2 初の金メダル !! - 前日にMagicに気づき徹夜 -

気を取り直して次のコンペへ。USPPPM(NLP)コンペ。特許の中のanchorというcolumn名のワードと、targetというcolumn名の類似度を予測するコンペ。
例えば、パッと思いついた私が考えた例だと、以下のような感じ(もちろん、anchorはペンだけではない)です。

anchor target score
ペン ボールペン 0.75
ペン 細長い棒 0.25
ペン シャープペンシル 0.75
ペン 消しゴム 0

このコンペでもharshitが上位にいて、チームに入れてもらいました。このコンペでは従来は、1個のanchorとtargetの組み合わせを[SEP]で繋いで、inputに入れていました。

ペン [SEP] ボールペン

しかしながら、このinputだと、transformerに入れたときに、ペンとボールペンの相関関係しか考慮されないという問題点があったのだと思います。そこで、以下のように、ペンに関連する他のtargetもくっつけて、transformerに入れるinputに入れてみるMagicを私が思いつきました。

ペン [SEP] ボールペン [SEP] ボールペン,細長い棒,シャープペンシル,消しゴム

そうすることで、他のワードとの相互作用も考えながら、学習が進むのではないかと期待しました。結果としては、CVとpublic LBがこのMagicによって爆上がりして(leakを疑うくらい)、一気に金圏内にいきました。これが締め切り前日で、徹夜で、全員モデル作り直せ!となったのは、今でも笑える経験です。

結果として、今回は、無事金メダルを取れ、チームではめちゃくちゃ盛り上がり、念願のCompetition masterになれました!!これは嬉しかったなー。
kaggle上のSolutionへのリンクはこちら

https://x.com/ChuMajin/status/1539037578992971777?s=20

4.4.3 金メダルの壁乗り越えた話まとめ

どうすれば金メダル取れますか ?

と、私はこのあとのKaggle Days編とかに出てくるGrand Masterの方にけっこう聞いていて、最近は逆にたまに聞かれるようになりました。

これをまとめていて、自分の場合は以下の感じだと思いました。

・ ソロ銀を安定に取れる実力

・ 同じ目的を持った人とチームマージ

・ 最後まで諦めない

以上で、取れる確率を上げて、それを繰り返せば良いのかもと聞かれたらそう答えるようにしようと思いました。
もちろん、そんなことに限らず、取れてしまえば良いのかもです。そういう人もいます。

5. Kaggle Days編 - 強くなれたと思えたきっかけランキング2位 -

このころから、kaggle days world championship(以下、kaggle daysと略します)に参加しました。強くなれたと思えたきっかけランキング2位にしています。kaggle daysを知らない人に簡単に説明すると、以下のような感じです。

- 1次予選(参加者計5321人)
    ・ オンラインで参加可能で、12回ある(3週間に1回くらい)
    ・ 毎回世界中のどこかでやっている設定になっているため、開催時間は朝~深夜などまばら
    ・ 4時間の短時間コンペ
    ・ お題は、table、画像、NLPなど様々
    ・ 重複を除くtop3が決勝に進める
    ・ チームを組んでも良い

- 決勝(参加は、77人、24チーム)
    ・ バルセロナで行う(飛行機代、宿代は申請すれば出る)
    ・ 8時間で2コンペ分。
    ・ totalの成績で勝者決定。

詳細は、kaggle daysとかで検索すれば、参戦記がたくさん出てくると思いますので、興味がある方は見てみてください!

5.1 1次予選 -まさかのソロ予選通過 -

kaggle daysの存在は、最初から知っていたわけではなく、X(旧twitter)で盛り上がっているのを見て、途中から参戦しました。私の場合、12回中8回参加していました。初めは、社内でチームを組んで出ていましたが、予定が合わなかったり、深夜にお誘いするのは申し訳なくて、最後の方は1人で出ていました。予選は、最初、4時間の使い方とか取り組み方が全くわからずで、ダメダメでしたが、徐々に成績は良くなりました。

私にとっては7回目(全体で11/12回目)で、ソロで私は4位になり、上位にすでにバロセロナ行きを決めている人がいたので、繰り上げで、決勝行きが決まりました。コンペのお題は、画像コンペで顔の特徴に基づいて、興味を持つであろう趣味を当てることでした。

以下の要因が大きかったです。

・日本では、深夜帯だったのと、もう最後の方で確定している方が多かったので、強つよの日本人があんまりいなかった

・画像系で前回6回目(全体で10/12回目)のコンペの復習がもろに活きた。

・大本は上述したpetfinder2の復習でのコード

通過したときの歓喜のtweetは以下。
https://x.com/ChuMajin/status/1547691491522641920?s=20

5.2 決勝戦の準備 - 自分の型を確立 ? -

このころから、決勝戦への準備を始めます。これが個人的には大きかったと思います。この時は、自分みたいなペーペーがkaggleすごくできるGMとかMasterの方たちと、チーム組まずに1人で決勝で戦わなければいけないというプレッシャーで、いろいろと準備しました。基本的には、予選の復習と、tableデータ、画像系、NLPと、それぞれ自分の型でコードを準備しておきました。これは、今でも仕事でも使っているので、重宝していますし、基礎的なことを勉強しなおすことができたのが大きかったと思っています。

5.2.1 table系コミュニティコンペでソロ優勝と準優勝

table系は以下chapter6.1で出てくるAMEXコンペで2枚目の金メダルの話と時系列が前後してしまうのですが、AMEXコンペの復習とkaggle daysの決勝の準備として出たコンペで、コミュニティコンペというkaggleの中でもメダルがもらえないある程度内輪の小規模なコンペであったものの、ソロで優勝できました(1位/176チーム)。
Fiveerというサービスや商品を5ドルから売買できるサービスがスポンサーで、商品として、サイト内で、1000$分購入できる権利をもらったのですが、結局まだ使っていません。小さい大会ながら、優勝は、自信がつきました。

https://x.com/ChuMajin/status/1570646121445486592?s=20

また、そのあとの1位と2位がGCP100$分もらえるコミュニティコンペでも準優勝(2位/48チーム)できました。31位からshake upして2位でした。

https://x.com/ChuMajin/status/1583886492300369921?s=20

5.2.2 画像系コミュニティコンペでソロ準優勝

これは、NFLコンペとかでもhostをしているRobさんが不定期で開催しているPogChamp#3で、とうもろこしの画像のclassificationをするコミュニティコンペでした。こちら、優勝すると、RTX3080がもらえるとのことで、締め切り2日前から挑戦しました。

こちらは、shake upしましたが、惜しくも、準優勝(2位/91チーム)でした。

それでも、mainのkaggleコンペではNLP系で金メダルを取り、小規模のコミュニティコンペでtable系優勝、画像系で準優勝(+画像系は予選もソロ通過)と、それぞれのジャンルで成績を残せたので、自信にはなりました!

5.2.3 マルチモーダル系の準備 - のちのソロ金につながる -

それでも、まだいろいろと準備していく中で、X(旧twitter)でこのころはまだ知らない人だったのですが、NSKさんが世界中を旅していて(自分もけっこう海外旅行行った方なので、話合うかな~と思っていました)、どうやら決勝戦に進むらしいのこんなtweetを発見。

https://x.com/naohachi89/status/1581178359379161088?s=20

やばい。マルチモーダルきたら、何にもできない…と思い、Shopeeコンペの復習をしておき、ArcFaceをここで習得しました。(これがのちのソロ金につながりました。)

5.3 決勝戦@バルセロナ - 楽しかったが、惨敗... -

決勝戦は、バルセロナで行われました。

5.3.1 日本人kagglerとの出会い

今まで、日本人kagglerの知り合いはほとんどいなくてX(旧twitter)で拝見する方だけでしたが、GMやら、Masterの人たちと向こうで実際に会って、話をすることができました。これもすごく大きかったです。特に、覚えているのは、charmさんnakamaさんRabotni(kuma|熊)さんのグループやshimacosさんに、金メダル取るためにはどうすればいいかを聞きました。意識の高さとか、取り組み方とか本当に学ぶことが多くて、めちゃくちゃ刺激を受けました。あまり、話ができなかった人も知ってはいるというのは大きくて、X(旧twitter)で何を発言しているかとかcheckしたり、出ていないけど、解法を見に行って、それを今自分がやっているコンペに活かすこととかもできました。今でも感謝しています。んでもって、今でもここで知り合った数人と適当に焼肉行ってたり、カレーさんのサッカーで一緒になったり、kaggler会でのイベントで一緒に話したりと一気に強い人のつながりが増えて、これがまた話すのが、勉強になるし、楽しいんですね。こういう人たちと。kaggle強いだけじゃなくて話も面白い人たちで、繋がれて本当に良かったです。

5.3.2 決勝戦 8時間で2つのコンペ 惨敗

1人で戦う気で行っていたのですが、どうやら向こうでチームを組んでいいらしいとなって、何人かDMとかくれて誘ってくれました。けど、会社に1人で行ってきますとか言ってしまったのと、一人で戦う準備してたから、断ってしまい、1人で戦うことにしました(誘っていただいてありがとうございました!)。結果としては、けっこう準備していったつもりでしたが、惨敗でした。。。コンペ全然わからずで、ほぼ最下位でした。恥ずかしい && 悔しい思いをしました。

https://x.com/ChuMajin/status/1586644920844140546?s=20

ただ、ここで悔しい思いをしたので、次頑張れたというのはあったと思います。今では良い思い出です!

5.3.3 追記 -レアルマドリード戦-

そのあとは、マドリッドに行って、サッカー見て帰りました!昔、ウイニングイレブンで10万程度課金勢(やばめ)だったので、それの影響でスタジアム回りたいとかなって、過去に何回か行きました。クリスティアーノロナウド好きだったのですが、このころにはもういなかったです 泣.

https://x.com/ChuMajin/status/1587090629124841473?s=20

6. Master編

6.1 AMEXコンペ - Gibaさんチーム参入 -

2枚目の金メダルは、kaggle daysの準備期間と被るのですが、AMEXコンペでした。AMEXコンペは、クレジットカードの利用者が将来デフォルト(債務不履行)になるかどうかを予測するtableコンペでした。これはkaggle daysの準備として、tableコンペ触りたいなと思って参加しました。

やっていて、しばらくしたら、GMのIsamuさんに声をかけていただいてチームを組ませてもらいました。この時のもう一人のメンバーはkaggle daysの予選で声をかけてくれたIoannisさんでした!しばらくして、petfinder2や、feedback1でソロ金2枚を取られていて私が昔からチームを組んでみたかったkuro_Bさんに、このときはじめて私から、声をかけてチームにはいってもらいました。

このときのAMEXコンペは、これまでないんじゃないかくらいmodelのアンサンブルを大量にしていました(最後は60個くらい?)。でも、このままじゃ金メダル取れなそう…となっていたら、Ioannisさんが、Gibaさんにちょうど締め切り1週間前に声をかけてくれて、ゲームが変わりました(Gibaさん、今金メダル63個も取られているんですね)。

Gibaさん加入後、AMEXのデータにノイズがあって、それをcleaningしてくれたGibaさんのデータを使って、全員で各自のmodelを組みなおしました。結果としては、cvもlbも向上して、順位を上げました!さらに、そのときは、 CMA (Covariance Matrix Adaptation)というアンサンブルの方法を使っていましたが、overfitしているかもしれないから、別のsubはLGBMのstackingを使おうと言ったのもGibaさんでした。結果としては、public23位の銀圏からshake upして13位で金メダルでした!

https://x.com/ChuMajin/status/1562594720165265411?s=20

6位のsubもあったので、少し後悔がありましたが、当時の自分としては2枚目の金メダルが取れてとても嬉しかったです。このとき、データのクリーニングと、stacking重要だなと学ぶことがとても多かったです。kaggle上のSolutionへのリンクはこちら

6.2 Feedback3 コンペ - 11日チャレンジでソロ金メダル届かず -

kaggle daysから帰ってきて、しばらくしてNLPコンペであるFeedback3コンペに出ました。これは、英語学習者(8年生から12年生、8年生で13-14歳くらいらしい)の小論文の自動採点を行うコンペで、採点基準が6個あるmulti regressionのコンペでした。コンペに参加する時間があまりなくて、締め切り11日前から取り組みました。これは、もう前述したCommonlitでのtakoiさん2nd solutionをめちゃくちゃ参考にして、たくさんのモデルをアンサンブルしました。でも、結果としては、shake upはしてくれたものの、金メダル届かずでした。さすがに11日では無理でした。

https://x.com/ChuMajin/status/1597742856684572673?s=20

このときのhakubishin3さん解法、かっこよくて、chrisさんが公開していたfinetuning無しで、アンサンブルする方法だけで強いモデル作っていたのはすごかったです。私はfinetuneありで、やったらダメだったので、採用しなかったのですが、finetune無しでやらなければいけなかったらしいです。それができていれば、いけたかもしれないけど、これは後の祭りなので、しょうがなかったです。kaggle上のSolutionへのリンクはこちら

6.3 LECR コンペ - 人生で一番苦しかったソロ金取った時の話 -

※ 以下は2024.3.1の関西kaggler会でメインで話した内容です。

ソロ金取った時の話です。これは本当にこれまでの人生の中で一番追い込まれて辛かった経験だと思います。

6.3.1 コンペの内容

Learning Equality – Curriculum Recommendationsというコンペでした。
channel(例えば、機械学習というジャンル)ごとに、目次みたいなものtopic(例えばobject detection)があって、そのtopicごとに参考になる教材content(例えば、udemyの動画とか、qiitaのurlとか)をグループ分けするというコンペでした。sample submissionは以下の感じです。

topic_id content_ids
topicA(例えばobject detection) contentA (例えばudemyのobject detectionの動画),contentB(qiitaの記事),contentC(youtubeのobject detectionの解説動画)
topicB contentD,contentE
topicC contentA,contentF,contentG

自分にとって、何が難しかったかというと、例えば、画像のclassificationとかで考えると、画像1枚に対して1つoutputがあるみたいな形で、inputとoutputの数は決まっていることが多いのですが、今回は、以下のように、input1つに対してoutputがばらばらであることと、content idはtopic1にもtopic3にも関連するみたいに重複が存在するということでした。

6.3.2 Architectureの組み方

上のような状態で、どう機械学習を組んでいったかというと、くじらコンペでの解法をみていたり、kaggle daysの準備でArcFaceをやっていたのもあって、Embeddingといえば、ArcFaceが効果的とかなり決めつけていたところから入りました。この構図をどうArcFaceに落とせば、学習できるかということをずっと考えていて、お風呂で思いつきました。

最終的には、↑のような構造にしました。1 iterationの中で、例えば、topicのタイトルをまず入れます。そして、2個のheadのArcFaceを用意しておいて(これはくじらコンペのSolutionを参考にしたら早く思いつきました。)、topic idだけでなく、突合せされたcontent idもlabelとして使って、それぞれのloss(Loss1,Loss2)を取りました。そして、contentのタイトルとかを入れて、同じarchitectureで同じように、2個のheadに入れてそれぞれのloss(Loss3,Loss4)を取りました。最後にこれらのlossを平均化してback propagationするという構成です。そうすることで、例え、contentが重複していたとしても、embeddingは間を取ってくれたり、近くにいてくれたりするということを期待しました。

このとき、public notebookは今は、RAGの活用でけっこう知っている方が多いと思いますが、Sentence Transformerのfine-tuneが流行していました。ArcFaceはpublic notebookではやってなかったと思います。しかし、結果、Solutionを見たときにおそらく、h2oチーム、Ahmetさん、このコンペでGMになられたs_shoheiさんのみがArcfaceを使っていて、この手法は合っていたんだと確信しました。

6.3.3 最終Solution

最終Solutionの概略図はこのような感じです。ArcFaceのところは一番左のピンクの枠の中になります。ここから、topicsのembeddingとcontentのembeddingを出力して、例えば、Cosine Similarityを取って、閾値で切ってあげれば、このコンペでの解法のbaseになります。ただ、もう一つの工夫点は、今、recommendコンペとかでもよく出てくる2nd stage以降のrerankを入れたところです。また、最後の閾値を切るところは、AMEXコンペで得たrank ensembleを使いました。kaggle上のSolutionへのリンクはこちら

6.3.4 何がつらかったのか ?

ここから、このコンペで何が辛かったのかをつらつら書いていきます。
まず、2023年の1月1日。元旦からkaggleやっているやついるのか?というのはあるんですが、ここにいるんですね(私)。

https://x.com/ChuMajin/status/1609603197060145152?s=20

元旦から順位変動が激しくて、世界中では俺だけでなく元旦からkaggleやる人がけっこういるんだと思いました!この時、金圏に入ったのを覚えています。
(Score 0.41)

2023.1.15 : 3位浮上

2023.1.22 : 2位浮上

https://x.com/ChuMajin/status/1617037449607401472?s=20

この時、バルセロナで知り合った人と焼肉を食べていて、「いつでも、1位いけるんですけどね。」とか、余裕をかましていました。なぜなら、ArcFaceの1st stageだけで、2nd stageは使っていなかったからです。のちのち、ArcFaceの1st stageの精度が良くなりすぎていたせいで、2nd stageはあまり効かなくなっていたことにはびっくりしました。。。

2023.1.31 : 1位浮上 (この時点でコンペは折り返し。残り1.5カ月)

https://x.com/ChuMajin/status/1620218528782778368?s=20

そして、この時に確かNBMEコンペ、USPPPMでともに戦ったharshitから一応俺らチーム組むけど、入るか?と声をかけてもらいましたが、ソロで行きますとお断りをしました。

2023.2.14(残り1カ月) : 2位に落ちる 確かまだアンサンブルしていないから大丈夫と捉えていた

2023.3.1(残り2週間) : 3位に落ちる この辺から怪しい雰囲気が…。そして、アイデアはかなり尽きてきた。

https://x.com/ChuMajin/status/1630679359194537985?s=20

何が怪しいかというと、後ろにbestfittingさんがどんどんあげてきていたのと、DFLコンペをやっていて、こっちのコンペには来ないと思っていたpsiさん率いるh2oチームが下の方に見えました。

そして、そのうち、Ahmetさんが急に上がってきて、抜かれてpublic1位に(そのまま優勝しました)。そのあとは、確か、私とbestfittingさんs_shoheiさんで上げたり下げたりで互いに食いついていけたのを覚えています。このころは私はひたすらサウナで限界を超えろと鼓舞していました(やばい)。実際にもう限界だと思っていたけど、それを超えれるようなアイデアを思いつけたのを覚えています。

2023.3.8くらい(残り1週間) たぶん、この辺で、コンペ開始して1週間くらいのpsiさん率いるh2oチームに抜かれて、わしの3か月はなんだったんだ・・・となりました。あと、しばらくやっていなかった人も戻ってきて、抜かれてしまいました。

2023.3.10くらい(残り4-5日) この辺で、「もうだめだ…」というネガティブな気持ちと、「いやいや、スコア上げるのに、こんなに苦労したんだから、他の人が簡単に上がることはない。大丈夫」というポジティブな気持ちが交互して精神的にやばくなります 笑。このときに、何かで見た「金メダル、取れなくても死ぬわけじゃない」という(確か、自分の記憶ではカレーさんの発言だと思っているのですが、引用元が見つからず)すごい名言に精神的には救われました 笑。ありがとうございます!

2023.3.12くらい(残り2-3日) もうLeadersboardが怖すぎて見れない。できるだけ見ないようにしていた。あと、Score0.702とか出て、もうこれ以上は無理というのと、ここまで出てれば、金は大丈夫だろうとか思いこむようにしました。

-------------------------------

そして、最終日 2023.3.14 30分前 : ぎりぎり金圏に残っていることを確認。どうなるんだーーーって思っていました。

-------------------------------

が、まさかの10分前・・・

-------------------------------

NBME,USPPPMでともに戦い、チームにまで誘ってくれたharshitのチームに抜かれ、金圏外に追いやられる…

2023.1.1から3か月半public金圏内にいたが、ついに最終日の締め切り10分前に最後13位で金圏内から落ちました。(↓は最後のpublic LB)

顔面が蒼白になりました。もう神頼み…

ってなって、8:59分。恐る恐るleadersboradを更新… (↓、private LB)

よっしゃーーーーーー って人生一くらいのやつが出ました!

https://x.com/ChuMajin/status/1635793287129993216?s=20

kaggleの神様ありがとう!ってなりました~。

部屋で一人だけど、狂気乱舞でした。人生でtop3くらいに嬉しかったです。

後日談ですが、他の人の解法を見たら、rerankの特徴量生成が甘く、もっとできていたら、楽に戦えたのだと思いました。

けど、ここでの一番の経験は、kaggleに限らず、人生全部かければいろいろなんとかなるという自信が持てたことでした。これは本当に貴重な経験でした。

6.4 火山コンペ - 2連続のソロ金! 初prize -

※ 以下は2023.6.23の関西kaggler会でメインで話した内容です。kaggle上のSolutionへのリンクはこちら

LECRコンペの後、Arcfaceを学んだので、実務でArcFaceを活かして、少し時間を使った後に、火山コンペに参加しました。このコンペはSemantic Segmentationで、Segmentationはやったことがなかったので、興味を持ちました。コンペ自体は、ベスチオ火山の噴火で炭化した巻物に何が書かれているかを読み取る(文字があるpixelを予測する)のが目的でした!

巻物をX線でScanしてその画像を深さ方向に65枚の画像に分けます(X線画像からは、インクが見た目ではわからない)。また、赤外線により、取得した画像の中の文字がある画素を正解とします(赤外線は見た目でわかる)。おそらく、赤外線は表面しかわからないのに、対して、X線は深くまで読み取ることができるので、それでモデルを作って、奥深くのものも読みたいということだと理解しています(間違っていたらごめんなさい!)

6.4.1 inference

まず、このコンペでは、trainデータに対して、なぜかtestデータが回転しており、文字が90度trainとは異なることに、Augmentationの入れ方とスコアの関係性などからわかりました。

この性質を考慮して、Augmentationではrotationを入れずに作成して、inferenceの時だけ、画像自体を回転して推論して、最後に逆方向に回転してもとに戻すということをやってみました。そうすると、回転無しだとpublic lb 0.58だったのに対して、有りだと0.74と爆上がりして一気に金圏内にいきました。

この回転している性質で優位性を保っていたと思うのですが、最終的には、hengck23さんに、discussionで取り上げられ、皆さんも同じ条件で行うことと最終的にはなります。

6.4.2 training

trainingに関しては、まず、tkさん神notebookが公開されたので、それを基に作りました。

自分が追加したところとしては、efficientnet_b7_nsなどの大きいモデルを使ったのと、データが少なすぎると思ったため、深さ方向でのstackを何個かに分けて、それらを全部訓練データとして使用しました。また、ラベル作成に用いた赤外線画像も入れてみたら、cvとpublic lbが上がったので、それも入れました。

CNNでうまくいったので、transformer系のSegmentationを探しており、過去コンペからSegFormerが強そうということを見つけました。しかしながら、ライセンスの問題で、商用利用がコンペの時点ではできないことがわかり、Discussionに投稿して、ダメだよね?と書いたところ、ホストが商用利用ではないから使っていいよ!ルールも書き換えたよ!ということになりました(詳細はこちら)。

6.4.3 final sub

しかしながら、このSegFormer。私にとって、このコンペでは悩みの原因の一つになりました。以下は、Single modelの最終sub前のcvとpublic LBの相関です。

この図からわかるように、オレンジのSegFormerはCVは良いのですが、public LBが悪い… となり、使うのが不安でした。皆さんならどうするでしょうか ?
trust CVをするなら使うし、でもやっぱり怖いからsubを分けるでしょうか ?
(publicは16%と小さいです。)

ちなみに、答えを先に言うと、privateでは以下のようになっていました。考察としては、public lbは16%程度ですごくすくなかったので、何かnoiseのようなものが影響していたのかな?と思っています。

この場合、やはり、trust CVが正解だったみたいです。

後だしじゃんけんになっちゃいますが、私の場合、どう判断したかというと、アンサンブルしたときのcvとlbの関係が以下でした。

灰色の箇所がアンサンブルした箇所で、これが青のCNNのSingle modelの直線上に乗りました!そのため、SegFormerを使う決断をして、結局うまくいきました(ずるい聞き方ですみません・・・)。考察としては、上述したnoiseが影響していて、シングルモデルではSegFormerは悪かったけど、CNNとのアンサンブルによりnoiseが消えたのかな ? と想像はしました。

6.4.4 結果

結果はpublic2位でpublic16%と少ないけど、もしかしたら、ワンチャン、ソロ優勝しちゃう??とか思っていましたが、現実は甘くないですね。private 6位でした。けど、2連続のsolo金と初のprize。そしてSemantic Segmentationは初めてだったので、上出来すぎでした。

6.5 CommonLit2 - そしてGMに -

※ 以下は2023.11.26のKaggle Tokyo Meetupで話した内容です。こちらにアーカイブが残っていますので、動画の方が良い方はこちらをお勧めします。

https://www.youtube.com/live/2RydQQDeIGU?si=Z4zNogFWAr8WzsJu&t=9333

金メダル4枚持ってくると、GMが明確な目標になりました。どのコンペに出ようかと思っていましたが、NLPであるCommonLit2に出ることにしました。後述するように、このコンペはめちゃくちゃshakeしそうなコンペで、本当は参加するのに、迷いました。そのとき、麻雀漫画 天牌の以下の言葉を思い出し、参加したのを覚えています(まぁ要はどんなコンペでも勝て!ということなんです)。

https://x.com/mj_meigen/status/144195521152692224?s=20

また、途中から、AMEXコンペでチームを組ませていただいたkuro_Bさんとチームを組みました!kuro_Bさんとは毎日議論して楽しい日々でした!最終的には彼のモデルをアンサンブルしたらスコアが爆上がりして、public3位にあげてくれました。正直、kuro_Bさんいなかったら、ここまでできなかったので、私にとってはベストチームでした(ありがとうございます)!

6.5.1 コンペ概要

3年生から12年生の生徒が書いた要約を自動的に評価するコンペでした。ターゲットは、Content(内容)とWording(文法)のそれぞれの点数の回帰問題で、指標はそれぞれのRMSEの平均値でした。

このコンペの初見は、

・・・ このコンペやばい

でした。なぜかというと、Train Dataには、4つの原文しかないが、テストデータには、122個の原文があったからです。

これは、private LBはかなりの数を外挿して求めているようなイメージを持ち、激しくshakeするんだろうな・・・と思いました。

6.5.2 Solution

kaggle上のSolutionへのリンクはこちら

6.5.2.1 Solutionまとめ

先に結論を言うと、私たちのSolutionは 1 fulltrain × 7 modelのアンサンブルでした。7 modelは4-foldで計算したcvを使ってhill climbで選出してcvを上げました。4-foldを1 fulltrainに圧縮することで、推論時間を稼ぎ、多くのモデルを入れました。これにより、cvだけでなく、robust性も上げることを目的として、それがうまく機能しました。

6.5.2.2 Single model

これまでのコンペではだいたい、特徴量1 [SEP] 特徴量2 みたいな形でinputを入れればうまくいったので、今回も、まずは、要約文 [SEP] 原文やその他情報 という形で入れてみましたが、これがうまくいきませんでした。そのため、public notebookでは、原文を使わずにdeberta-v3-largeなどに入れた後、2nd stageでlight GBMのようなもので処理をするという形がとられていました。

しかしながら、これだけだと、途中でcvもpublic LBも頭打ちになっているイメージがありました。

最終的に、うまくいったのは、以下の右の形で、上位Solutionを見ても、この形を使用している方が多かったです。

具体的に言うと、原文を使用するのですが、要約文のところのみをMean poolingして使用する方法でした。これがうまくいったのは、おそらく、要約文のtokenと原文のtokenの相関は原文をいれることにより、強化されたのと、原文のところのpoolingは、アノテーターは原文を見て採点しているわけではないので、意味をなさなかったのではないかと考えています。

そのほかにも、私たちは、原文を使用して、[CLS]のpoolingのみを使う、"Evaluating the summarized text and calculating content and wording score :"のようなオリジナルのプロンプトを文頭に入れて、そこのpoolingのみを使用することなどを使用してモデルを作成しました。

6.5.2.3 Seed ensembleの可視化

このコンペをやっていくにあたり、以下の疑問がありました。

・ 疑問1 discussionに1fulltrain(Seed ensemble無し)でsubして、seedを変えただけで、lb 0.482と0.459が得られたとあるが、どれくらいtestデータ(public/private)がばらつくのか ?

・ 疑問2 過去の他のチームのsolutionでは3個seed ensembleしていたが、どれくらいすればよいのか ?

これらの関係性を見るために、hold outしてSeedだけ変えてmodelを15個作成しました。

publicとprivateのばらつきに関する疑問1に対しての検証をまずは行いました。以下は、Seed ensembleをしない場合の仮想publicと仮想privateの関係です。

この図から、seed ensembleをしないで、1 modelでsubmissionするとかなりばらつくことがわかりました。

次に、何個Seed emsembleすればいいのかという疑問2に対してです。以下は、15個のseedから50パターンくらいシャッフルしてN個選択してSeed ensembleをしたときの仮想publicと仮想privateの関係です。

この図から15個平均したらほぼ収束することを確認しましたが、何個Seed ensembleすればよいというのは、最適値が出ず、すればするほど安定するというのは、わかりました。

また、Seed ensembleしない場合と比較すると、しない場合の重心よりも収束するポイントは良い方向(左下にいけばいくほど良い)にずれていることも確認しました。このことから、Seed ensembleすることで、飛び値のようなものを吸収したことを考え、Seed ensembleの効果を可視化することができたと思いました。

そして、最後に、この図は1つのmodelに対して、可視化した図ではありますが、他のモデルをアンサンブルしたときにこのふるまいはどのようになるのかを示したのが、以下の右の図です。

こちらの図より、ensembleすると、model1とmodel2の中間より、少し良い方向に緑のプロットのensembleの収束ポイントが移動していると思います。これがモデルアンサンブルの効果だったのかなと思います。
しかしながら、この図は私の意図とは少し違く、もう少し緑のプロットは左下にいってほしかったです。というのも、これだと、model2から見ると、model1をアンサンブルすると、仮想publicは良くなるが、仮想privateは悪くなってしまうからです。理想的には両方良くなってほしかったです。ただ、これは2modelを簡単にSimulationしたもので、実際の最後のsubmissionは上述したとおり、1 fulltrain× 7modelです。それを図示したのが、下の右下の図です。

右下の図を見ると、model1~7まですべてのケースより、左下にあり、頭の中で思い描いた通りに実際はなっていたことがわかります。また、上述では、Seed ensembleは何個すればよいのかという議論をしてきましたが、最後のsubでは実はSeed ensembleはしていません。これはこの可視化から考えると、Seed ensembleをしなくても、例えばmodel1なら、青のプロットからランダムに1個選ばれます。7個の異なったモデルも同様で、これらをアンサンブルすることで、自然とアンサンブル後はアンサンブルの収束ポイントに近づいていくのではないかと考えたためです(Seedアンサンブルをすると推論時間が足りないので、モデルアンサンブルの方が効果が大きいとも考えました)。

6.5.2.4 このコンペはどういうコンペ ?

これらの解析からこのtrainデータ4個の原文、publicは1個、privateは121個あるコンペは以下のような感じだと想定しました。

モデルが少ないと、cvが良くても、かなりばらつきが大きく飛び値などもありそう(上)。一方、モデルが多くて、cvが良ければ1つ1つがGrand truthに近づくだけでなくばらつきも小さそう。その結果、privateのスコアが良さそう。つまり、cvだけじゃなくて、robust性も大事だと思いました。これらのことから、1 fulltrain× 7 modelは面白い作戦かなと思い、この方針でいくことにしました。

6.5.3 結果

結果は今回はpublic3位で、火山コンペ同様もしかしたら、ワンチャン、優勝しちゃう??とか思っていましたが、実はshakeが激しいから、金圏から外れちゃうこともある??とか思っていました。とにかく金圏をkeepしてGMになりたかったです。

https://x.com/ChuMajin/status/1712109593076080954?s=20

closeの日は火山コンペの時から、早起きしてトイレや水回りの掃除をするようにしていました。この日は緊張からかもっと早く起きてしまったので、散歩がてら神社にお祈りに行ってきました。

そして、戻ってきて、kuro_Bさんとチャットしながら、発表を待ってました。やるべきことはやった感じでした。

んで、8:59分、以下の結果で、2人ではしゃぎました!予想通り、shakeが激しいことも確認したうえで、ほとんどshake downせずに4位prizeで終わりました!

https://x.com/ChuMajin/status/1712259209696624830?s=20

となり、無事Competition Grandmasterになれたのでした。

7 あとがき

ブログ初めて書いてみましたが、めちゃくちゃ長くなってしまいました…。

最初から読んでいただいた方は本当にありがとうございます。ペーペーからスタートして、kaggle内のSolutionやnotebook、また、kaggle外でも会話していろいろな人から勉強させてもらい(いろいろ登場人物出したかったが、もっと長くなりそうなので割愛…)、うぉーとか、うぉぉぉぉーーーとか言いながら金メダル取って、なんとかGMになれました。

また、kaggler会や、kaggle meetupでもいろいろ発表をさせてもらう機会を頂いたり、いろいろなkagglerと懇親会などで話をさせてもらったりするのですが、ほんと熱くて、面白い人集まっているし、刺激をうけるんですよね(開催スタッフの方、いつも質の高い集まり、ありがとうございます。)

なんだかんだ始めたkaggleですが、kaggleだけじゃなく、普段から熱くて向上心の高い仲間ができたり、会社生活では会えないような天才と思える人に会えたり、やってて良かったな~と思うばかりです。皆さんも良いkaggle lifeを!

Discussion