はじめに
先日、Mechanisms of Action (MoA) コンペが終了した。
メダルを狙って参加したコンペであったが、結果は538位/4373でありブロンズすら取得できずに終わってしまった。
コンペの中盤まではパブリックスコアでシルバー圏内を維持していたものの、最後1-2週間で詰めきれず、悔いが残る結果となった。
あの時ああすれば良かった、こうすれば良かったなど、挙げればいくらでもあるが、つまるところ、Kagglerとしての経験の不足、データサイエンティストとしての己の手札の少なさである。貧弱なスキルで勝ち抜けるほど、Kaggleは甘くなかったということだ。
コンペを振り返り、思ったところを場当たり的に書いていこうと思う。解説を書くといったことはしないのであしからず (いちおうコンペのリンクくらいは貼っておく)。
アンサンブルの前にsingle-modelを育てたほうがいい
コンペ開始から2ヶ月ほど経った頃、俺は3個のNNモデルをアンサンブルし、パブリックスコアを大幅に伸ばした。
なまじこの時のスコアが良かったばかりに、ここから2週間程度はモデルのハイパーパラメータ、アンサンブルウェイトの調整に終始し、データと向き合うということをしなかった。
個々のモデルを伸ばすことを試みようとしなかった。アンサンブルは非常に強力だが、それに頼りきりでは勝てない。EDAを充分に行い、1つ1つのモデルを伸ばしてこそ、アンサンブルがより活きるのだと思う。
パブリックスコアは当てにならない
コンペを通して苦しんだことであったのだが、MoAではtrainingデータを使って出したCVスコアと、submissionして出したパブリックスコアが大きく乖離していた。また、CV (Cross Validation) スコアとパブリックスコアとの相関も大きくなく、CVは上がったのにパブリックスコアは下がるといったことが往々にしてあった。俺はそれでもなんとかパブリックスコアを伸ばそうとした。
パブリックスコアとプライベートスコアのプロットを示す。ある程度相関はあるものの (決定係数0.72程度)、パブリックでベストのsubmissionでは、むしろプライベートスコアは悪化していることがわかる。
これについては、Chris Deotte氏が素晴らしいDiscussionを投稿してくれている。単純な話で、パブリックスコアの算出に用いられたデータと、我々に与えられたtraingデータの分布が大きく異なっていたのだった。
今回のコンペにおいては、リーダーボードの順位を上げようとハイパーパラメータを色々変えるのは、むしろ悪手だったといえる。そうすることによって、オーバーフィッティングを招いてスコアが下がってしまっては目も当てられない。実際のところはわからないが、感覚としてはshakeup/downは大きかった。
パブリックスコアを伸ばすことに拘泥するな。パブリックは、全体のうちの25%でしかない。4-foldのうちの1-foldだ。その浮き沈みに一喜一憂するな。と、戒めを込めてここに書き残しておく。
CV戦略超大事
信頼できる指標が必要だ。適切なCV戦略を構築することに腐心せよ。
特にMoAコンペではimbalanceなデータセットが与えられていた。206個のラベルのうち、出現頻度上位のラベルは数百回以上出現するのに対し、1回しか出現しないラベルも多数見られた。こういったimbalanceなデータを扱う場合には、特にCV戦略は重要であるように思う。俺は単純にStratified kfoldを使用していたのだが、コンペ中盤にdrug_idが解禁されてから投稿されたChris Deotte氏のkfoldは、上位勢がこぞって採用しており、俺も使っていれば多少は変わったかもしれないと思っていたりする。
drug_idの頻度に着目したStratified Foldであり、慧眼というほかない。実はこのkfoldを一瞬試しはしたのだが、CVとパブリックがともに恐ろしく下がったので怖くなってやめたのだ。だがこれは、おそらく俺のモデルがrobustでなかったことを示唆していた。ここで一回立ち止まってればなあ...
GPUが足りない
MoAのデータ量は、画像コンペと比較するとかなり少なかったが、それでもCPUだけで学習を回すのは時間的にもったいなく、GPUを使うのが時間的にベターだった。俺は自前でGPUを用意できなかったので、コンペ中はずっとKaggleのカーネルを使っていた。GPUを1週間に利用できるのは42時間以内という制限があるのだが、submit時に実行される時間もGPU使用時間に換算されるため、時間としては到底足りなかった。
たいてい1週間の4-5日あたりをすぎるとGPU利用制限に引っかかり、そこからはCPUでなんとか頑張るということを繰り返していた。終了1ヶ月を切った追い込みの時期になると、その制約が重い足枷のように感じられ、たいへん不便な思いをした。
画像コンペは言わずもがなだが、MoAのようなテーブルコンペに挑戦する場合でも、GPU環境は自前で用意できることが望ましい。AWSでもGCPでもなんでもいいが、とにかく時間制約のない計算資源を確保すること。コンペの開催期間は限られているので、その間に試行できる学習回数はなるだけ多いほうが良い。
最後まで諦めない
コンペ終了1週間前ともなると、参加者は皆ガチり始め、リーダーボードの順位はとても大きく変動した。MoAの場合、0.01830でシルバー圏内に入れていたくらいだったのが、最後の数日の間で、0.01825でもブロンズに入れるか怪しいラインにまで、メダルのボーダーが変動した。
俺はというと、パブリックスコアを伸ばすことに苦戦し続け、0.01830から0.01829に伸ばすのがやっとだった。リーダーボードの順位はシルバー圏内から一気にブロンズ圏外まで大きく下がった。試行を重ねるも上がらない自分のパブリックスコア、大幅に上がるボーダーに絶望し、戦意を半ば喪失していた。だから最終日も深く考えず、思考停止気味にプライベートスコアが一番高いsumbissionを提出した。
だが、充分に勝ち目はあった。コンペが終わってからわかったことだが、プライベートではメダル圏内に食い込んでいるsubmissionはいくつもあったのだ。それらを提出していれば、ブロンズメダルを獲れていた。前述したとおり、パブリックスコアは必ずしもプライベートスコアを反映していない。だからこそshakeup/downが起こるのだし、Trust CVなる金言が生まれるのだ。最後まで諦めず、CVと照らし合わせてfinal submissionを決めるべきだった。ベストなsubmissionを出していればメダルが獲れていたと思うと、後悔が大きい。
戦いの中で成長する
今回俺はKaggleにソロで初挑戦したわけだが、挑戦前と比べるとかなり成長できたと思う。
他人と競い合うことは大きかった。
実装の結果がスコアとして数値化され、しかもそれが他人と比較されるからこそ、0.00001でも高く精度を改善しようと努力できた。どこぞの馬の骨に負かされるのは悔しいものだ。悔しいから、他人をぶち倒したいと思ったから頑張ることができた。そうして3ヶ月間、データをこねくり回し、モデルをいじくり倒し、Discussionに齧りついたことで、多くのものを得ることができた。
一人で学習し、シコシコとコードを書いているだけでは人は成長できない。俺のような怠惰な人種の場合は特に。
今後どうしたいか
とりあえずソロで再びKaggleに挑戦したい。MoAでメダルを獲れなくて、正直はらわたの中はかなり煮えくり返っているので、これを解消するために速やかにに次のコンペを決める必要がある。
具体的に何に出るかは決めていないが、おそらくテーブルコンペになるだろう。画像処理、自然言語処理は計算資源的にハードルが高い。
次回の記事
MoAの上位勢のNotebookの解説記事を書いてみたい。