Kaggle初心者が「初心者」から抜け出して一歩先に行くために何をすればよいのか。実際のコンペでの実践事例を示しながら、ランクを上げていくためのノウハウを紹介する。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
この連載では、近年話題のコンペティションプラットフォーム「Kaggle」について、リクルート所属のKaggle Master 4人がKaggleの仕組みや取り組み方、初心者から一歩先に行くためのノウハウについて解説を行います。
第1回では、これからKaggleを始めようと思っている方向けに、Kaggleの仕組みや実際にコンペティションに出場した後の取り組み方、初心者におすすめのコンテンツについて解説を行いました。第2回では、ランクを上げていくために筆者が「実際に何をしていたか」について、実際の事例を交えながら解説していきます。
コンペティションに参加してまず着手すべきことは、何よりも内容の理解とルールの確認です。特に重要なページは、Description(コンペティション概要)、Rules(ルール)、Data(データ説明)、Evaluation(評価指標)、Code Requirements(コードの要件、※コンペティションの形式次第では存在しない場合もある)です。その他に、コンペティションによってはDiscussionの中にコンペティション主催者と会話できるスレッドも立っている場合があり、ここでもルールやデータの性質などに関する重要な議論が交わされることが多いので、必ず確認するようにしましょう。
特に、最近の自然言語処理系コンペティションや画像系コンペティションの場合、事前学習済みモデルを使える場合も多く、それによって最終的な成績が大きく変わることもあります。この際、コンペティションのルールによっては利用する事前学習済みモデルをDiscussionで書いておかなければ、ルール違反となる場合もあるので注意してください。
コンペティションの概要やルールについて十分に理解できたら、次はEDA(探索的データ解析、前回の記事を参照)を実施しながら必要最低限のベースラインを作ることが多くなります。この際、コンペティションによっては複雑なデータの前処理が必要なこともあるので、Notebook中のベースラインを参考にするとよいでしょう。ただし注意点として、コードの中身を理解せずにコピペだけでベースラインを作ってしまうと、その後に改善することが困難になってしまいます。そのため、できる限りベースラインのコードを理解し、時には自分なりに使いやすいようにアレンジ、リファクタリングしながらベースラインを作るのがおすすめです。
無事にベースラインができたら、早速サブミットしてみましょう。サブミットして、参考にしたNotebookと同程度のスコアが出ていればひとまず安心です、お疲れさまでした!(これは長い戦いの始まりに過ぎませんが……)
「ベースラインができたら、次は改善です!」……といきたいところですが、もしここで時間に余裕があったらひと手間を加えて自分なりのパイプラインを作ると、この後の改善がしやすくなります。仮にパイプラインを作っておかないと、以下のような場面で困ることになります。
パイプラインを作っておかないと、このような困りごとが生じてしまい、結果として改善のサイクルが遅くなってしまうことにもなりかねません。
それでは、パイプラインにはどのような要素が含まれるとよいでしょうか? 明確な正解はありませんが、以下のような要素を取り入れている傾向が見られます。
次に、Kaggle初心者が陥りがちなコンペティションの落とし穴について、実例を挙げながら説明します。これから説明する、Kaggleでありがちな落とし穴を回避することもランクを上げていく上で重要です。
まずは、「Private LeaderboardのTestデータとTrainデータの分布の違いに注意」することです。
前回の記事でも説明した通り、コンペティションの期間中はPublic Leaderboard(以下、Public LB)、最終的にはPrivate Leaderboard(以下、Private LB)での評価が行われます。ここで大事になるのは、学習に使うTrainデータと、Public LBおよびPrivate LBの計算のために使うTestデータの間にどの程度の相関がありそうかを事前に把握しておくことです。特に、Public LBのTestデータ(以下、Publicデータ)とPrivate LBのTestデータ(以下、Privateデータ)の質に予期せぬ違いがある場合、Public LBの順位とPrivate LBの順位が大きく異なるなどということも発生します。
「TalkingData AdTracking Fraud Detection Challenge」は、Testデータを使って未来の情報をうまく取り入れる特徴量の作成方法が重要となるコンペティションでした。特徴量としてIPアドレスやOS、アプリ、デバイスの情報とクリックした時刻が与えられており、Trainデータ、Publicデータ、そしてPrivateデータは時間軸に沿って分割されているシンプルなデータセットです。このコンペティションでは、多くの参加者が未来の情報をモデルに入れるために、「あるIPアドレスが次にクリックするまでの時間」などの特徴量を作成していました。
しかし、このようにして作った特徴量には一つの落とし穴がありました。それは「Privateデータにのみnullが多く発生する」ということです。例えば下記の表1のような[ip]と[click_time]からなるログが与えられていた場合、「あるIPアドレスが次にクリックするまでの時間」は[next_click_ip]列のようになります。この表から各IPアドレスについて、時間軸の最後に出現したものについては[next_click_ip]がnullになることが分かります。
ip | click_time | next_click_ip |
---|---|---|
18787 | 2017-11-06 14:34:52 | 60 |
18787 | 2017-11-06 14:35:52 | 8 |
18787 | 2017-11-06 14:36:00 | 892 |
18787 | 2017-11-06 14:50:52 | null |
19000 | 2017-11-06 14:32:02 | 510 |
19000 | 2017-11-06 14:40:32 | null |
表1 時系列データから未来の情報を特徴量として作成した例 |
今回は、Privateデータが時系列の後半に設定されていたために、「Trainデータではnullがあまり発生しないが、Privateデータには比較的多くnullが発生する」という現象が生じていました。これに対処するには特徴量を計算するウィンドウを日や時間で区切る必要があったのですが、それに気が付かなかった参加者はPrivate LBで順位を大きく落としてしまったようです。私(羽鳥)もその一人です。
次に、「Microsoft Malware Prediction」の例を挙げてみたいと思います。このコンペティションは、Malware(マルウェア)に感染したWindows PCを判別するコンペティションでした。データとしてはマシンのIDやデフォルトブラウザの種類といった基本的なものから、「ファイアウォールが有効か」などの比較的詳細な情報までが与えられていました。
結論からいえば、このコンペティションはKaggleの歴史に残る大規模なshake down(※shake:Public LBとPrivate LBの順位が乖離すること。shake downはPublic LBと比較してPrivate LBで大きく順位を下げることを指す)を生み出しました。私(羽鳥)もそれに巻き込まれた一人です。驚くべきことにPrivate LB TOP 5の参加者はPublic LBから全員1000位以上順位を上げており、反対にPublic LBで金メダル圏内にいた参加者はPrivate LBでほとんど消え去ってしまいました。
その理由の一つは、PublicデータとPrivateデータの分布の違いにあったようです。Public LBでも上位に入り、Private LBでも6位に入ったCPMPさんの解法では、図1のように赤い線のTrainデータと青い線のTestデータで分布が違う状態だったので変数を手作業でビニング(=変数を幾つかのビン、つまり一定の区間ごとでまとめる手法)したそうです。
この結果、図2のようにTrainデータとTestデータの分布の違いが軽減され、adversarial validation(TrainデータとTestデータの分布の差を測る手法)のスコアが0.98程度から0.7程度まで小さくなったようです。このようにしてTrainデータとTestデータ全体の性質を似たものにすることで、Trainデータを使ったlocal validationのスコア、LBのスコア、Privateのスコアが相関することになり、結果的にshake downを防ぐことができたようです。
次に、「Public LBにoverfit(過剰適合)してしまうことの危険性」について、2つの実例を交えながら共有します。
1つ目のケースは、「2019 Data Science Bowl」というコンペティションです。
まずは、Public LBのサンプルサイズが小さかったことが挙げられます。Testセット7000サンプルの内訳は、Publicデータ1000件、Privateデータ6000件です。つまりPublic LBで使われるサンプルはPrivate LBと比べて1/6サイズとなり、Public LBにoverfitしてしまうとPrivateデータの分布次第では予測が外れやすくなってしまいます。
また、本コンペティションでは適切なvalidationも必要でした。子どものアセスメントのログを基に、テストに対する回答状況を予測するコンペティションでは、TrainデータのログはTestデータと比較して過去のアセスメントログが多く含まれる構造になっており、TrainデータをTestデータの分布に近くすること(truncated validationなどと呼ばれていました)で再現する処理を実装する必要がありました。
さらに、本コンペティションで使われていたQuadratic Weighted Kappaという指標は、Publicデータの分布次第で大きく変化してしまう不安定なものでした。このような特性から、Testデータのサンプリングによって精度が大きくブレることを示したNotebookも公開されていました。
2つ目のケースは、「OSIC Pulmonary Fibrosis progression」で、肺画像を用いて患者の将来の肺活量を推定するコンペティションでした。このコンペティションもPublicデータが極端に少なく、Trainデータが176患者であったのに対し、Publicデータは5患者しかありませんでした。
それに加えて、Trainデータの目的変数に外れ値が複数存在していました(外れ値を分析するDiscussion)。Privateデータにも同様に外れ値が存在している可能性があることから、Public LBの順位はほぼ参考にならないものとなってしまっていました。そのような現状にも関わらず、多くの公開NotebookがPublic LBにoverfitしており、それを参考にした参加者が大きなshakeを演出してしまう結果となりました。
さらに問題なのが、Publicデータのみで利用可能な変数が配布されていたことです。この変数を利用することでPublic LBの順位を大きく上げることができますが、Private LBでは利用できない変数のため大きくスコアを下げてしまいます。
以上の2つの実例を踏まえると、コンペティション設計によってはPublic LBの順位を見る必要がないケースが多々あることが分かります。
次は、「Privateデータに対して推論を実施しない公開Notebookに注意」です。
「Mechanisms of Action (MoA) Prediction」のようなCode Competition形式(第1回参照)のコンペティションで配布されるTestデータはPublicデータのみで、サブミット時にのみPrivateデータ全量について予測が行われます。したがって、Privateデータにも推論が実施されるNotebookをサブミットする必要があります。しかし、手元で作成した予測結果でPublic LBのスコアだけをすぐに確認したいときに、事前にPublicデータに対する推論結果のみをサブミットするテクニックがあります。図4がその実装例です。
この実装では、事前にPublicデータに対する予測結果(CSVファイル)をデータセットにしておき、図4では、そのデータセットをベースにsubmission.csvファイルを作成しています。この実装では、全てを固定値(3)で埋めた後で、Publicデータに対する予測結果に更新しています。Privateデータについては固定値のままとなります。
このテクニックを使えばすぐにスコアを確認でき、速やかにバグの有無を確認することができますが、これをFinal Submissionに選んではいけません。
前述の通り、Code Competition形式ではPublicデータしか配布されていません。よって、事前に計算した予測結果を提出する上記の方法では、Privateデータに対する予測が行われていないことになります。
コンペティションの期間中、スコアの高い公開Notebookが上記のテクニックを利用しており、それをベースにした自分のNotebookを作成した場合に、テクニックの利用を忘れてそのままFinal Submissionをしてしまうと、結果的に大幅なshake downをすることになります。実際、Code Competition形式のコンペティションの場合、毎回上記のようなミスを犯す参加者が一定数います。
単純なことですが、仕組みやルールの理解はランクを上げていくための基礎になるので、取り組み前にルールを熟読すること、期間中のDiscussionをしっかりと追うことの2点を意識することをおすすめします。
最後は落とし穴というよりも実践に向けた注意点になりますが、「予測時の仕様を意識してモデリングする」です。
「Riiid」コンペティションは、英語学習者の過去の回答履歴を学習することで将来の回答の正解/不正解を予測するコンペティションで、Time-series APIというものを用いる特殊な仕組みとなっていました。具体的には、学習用データは他のコンペティションと同様に事前に渡されるものの、予測用データは公開されず、かつ他のNotebookコンペティションとも異なり、予測対象のデータがTime-series APIから逐次時系列順に渡され、それに対して予測するという形式でした。
このため、提出前の実験時にもその点を意識して設計する必要がありました。この形式は業務などで機械学習モデルを運用する際の状況に近いこともあり、極めてフェアであると筆者は考えます。今後も、このような形式のコンペティションに参加する際には「予測時の入力/状況に対応できるモデルになっているか」を強く意識して取り組む必要がありそうです。
次回は「他のチームと差をつける」をテーマに、私たちが上位を狙うにあたって意識していたポイントや戦略についてお話しする予定です。
「Kaggle入門」
Copyright© Digital Advantage Corp. All Rights Reserved.