自分が学んだkaggleへの取り組み方、kaggle tips

本記事は、京都大学人工知能研究会KaiRAのAdvent Calender 2日目の記事です。
初めてkaggleのコンペに参加してから1年が経過したということで、1年前の自分に比べたらkaggleへの取り組み方もだいぶ分かってきたと思うので、学んだことをメモしておきたいかなと思いました。
(なお、私はまだkaggleよわよわな人間なので、参考にならない部分もあるかもしれません。)
機械学習の技術については検索すればたくさん出てくると思うので、知らない用語などがあれば、自分で検索するなどして調べてください。

チュートリアルはやったけど実際にどうやってコンペに参加したらいいのか分からない人向けです。
それではkaggleへの取り組み方、kaggle tipsを紹介していきたいと思います。

# kaggleで一般的に言えること
## kaggleに参加するときにはできるだけ他の用事を無くす
kaggleにまともに参加しようとすると、滅茶苦茶多くの時間取られます。(特に慣れていない分野のコンペだと。)
また、アイデアを考えようとしたら時間だけでなく自分の脳のキャパシティーも結構食うので、kaggleに参加するときには他の用事をできるだけ減らしましょう。
もしチームを組んでいたらチームメイトに迷惑を掛けてしまうこともあります。(自分への戒め)

## DiscussionとCodeをしっかりと読む
kaggleのコンペに参加するときには、そのコンペの分野にあまり詳しくないことも多いと思います。
もしそのコンペの分野に詳しかったとしてもそのコンペのデータ特有の何らかの特徴などが共有されていることがあります。
また、kaggleは長期のコンペが多いので、長期のコンペでは技術だけでなく情報戦もとても大事に感じます。
なので、DiscussionとCodeは全部しっかりと読みましょう。
初めてだと時間がかかってしまうかもしれませんが、ここはしっかり時間を掛けましょう!
2、3周どころか何周しても良いです。(自分への戒め)

Discussionのタブの右上らへんにベルのようなマークがあって、そこでdiscussionのfollowをすることができます。
Discussionに新たなトピック、コメントなどが現れたらメールに通知が来ます。
後でコメントが削除されたとしても、やってきたメールでコメントを見ることもできるので、出来ればDiscussionのfollowをしておくとよいでしょう。
ちょっとしたときにkaggleのことを考えるきっかけにもなってくれます。

## kaggleのDiscussionやCodeにある情報が情報の全てだと思い込まず、最近の動向やライブラリをチェックする
特に初めてだとDiscussionやCodeにある情報が情報の全てだと思い込みがちです。
ですが、そんなことは無いので、そのコンペの分野の最近の発展などをインターネットで調べてみることをお勧めします。
もしかしたら有効な手法が見つかるかもしれません。

## ベースラインを作った後は対照実験をする
まずはベースラインを作りましょう。
その後有効な手法を探していくのですが、一気に色々手法を変えてしまうと、どの手法が有効なのかが分からなくなってしまいます。
なので、1つだけ手法を変えて対照実験を行います。

## 機械学習の論文の結果を信じすぎない
機械学習の論文では大体精度が向上した、みたいなことが書いてありますが、データによっては精度が向上しないことも結構多いです。
自分の実装にバグがないかをチェックしてもうまくいかなかったらその手法は潔く諦めましょう。

## DiscussionやCode、自分が思いついたアイデアなどの情報をまとめておく
Googleドキュメント、notion、scrapboxなど何でもいいですが、DiscussionやCode、自分が思いついたアイデアなどの情報をまとめておくと良いです。
kaggle日記を付けると良い、みたいなことを言っていらっしゃる方もいますね。

他にも、kaggleの場合は与えられたデータの設定が複雑なことがあります。
そのような場合に、自分でまとめて状況を整理しないと自分の頭がパンクしそうになることがあります。
(これはkaggleのコンペに慣れていない場合ですが…)

後から見直したら役に立ちそうなアイデアがあることもあります。


# 最初から独創的な発想をする必要はない
最初はDiscussionやCodeのアイデアで良さそうなものを取ってくれば良いです。
独創的な発想をしようと苦労する必要はありません。
前処理とかで非常にトリッキーな変換をしているkaggleのコンペ解法があるかもしれませんが、それはモデルに与えるデータを出来るだけ分かりやすく(自然な形に)するために変換がトリッキーになってしまっているだけだと自分は思っています。
独創的な発想をしようとして生まれたものではないのだと思います。

## ニューラルネットワークのモデルの細かいアーキテクチャーやハイパーパラメーターをいじりすぎない
ニューラルネットワークのモデルのアーキテクチャーやハイパーパラメーターは多少目につくところは変えても良いと思います。
ですが、ニューラルネットワークの細かいモデルの構造やハイパーパラメーターを変更しても精度が大幅に向上するということは少ないです。
(ただし、明らかに過学習してるときやモデルの複雑性が足りていなさそうなとき、モデルの細かな違いに関する考えがあるときは当然検討します。)
しかし、最終盤になってやることがなくなった場合やコードを書く時間があまりとれない場合はハイパーパラメーターのチューニングをしてみても良いかもしれません。

## 色々なモデルを試してみる
色々情報を仕入れてきて、期待できそうなモデルがあれば試してみましょう。
モデルの細かいアーキテクチャーはあまり精度に寄与しませんが、モデルの種類を大きく変えれば精度を大きく上げることができる可能性があります。
事前学習済みモデルを使うのであれば尚更です。
また、同じアーキテクチャでもパラメータ数の大きいモデルの方が良い精度を出しやすい傾向があります。(ただし、その分学習を成功させるのは難しい)

## データの前処理、後処理は良く検討する
データの前処理、後処理を変えると大きく精度が向上することがあります。

人間にとって分かりやすいデータは機械学習のモデルにとっても分かりやすいデータだと思っておくとよいでしょう。
あと、モデルが得意な入力を渡してあげることも大事です。(例えば、線形モデルには線形のデータを与える、ニューラルネットワークには正規分布っぽいデータを与える、分かりやすい分布をしているをしている特徴量を作る、など。)
ここは完全に私独自の解釈なのですが、私は、データの前処理、後処理はデータを自然な形に変形する営みなのではないかと思っています。
イメージ的には変にぐにゃぐにゃ曲がっている分布を、シャキッときれいな形に直す感じです。

質の悪いデータを取り除くことでモデルの精度を向上させることができる場合もあります。

モデルの出力の分布もしっかりと見ておきましょう。
モデルの出力を見たらどういうデータが苦手なのかが分かってモデルの改善ができる可能性があります。

データの前処理、後処理でうまくいくと思っていた手法がうまくいかないことがあります。
そのような場合は自分のコードにバグがないかをチェックして、バグが無さそうであれば潔く諦めましょう。
アンサンブルでバリエーションを出すのに使うことができる可能性はあります。

## アンサンブルをする
アンサンブルができるときにはアンサンブルをしてみましょう。(ただし、これはコンペの序盤に行うことではなく終盤に行うこと。序盤や中盤に、いろんなモデルを試したり、色々な前処理、後処理を試したりします。)
特に、異なる種類のモデルだと精度が向上しやすいです。

テーブルデータのコンペの場合は、トップはモデルの種類、前処理、後処理を何十種類組み合わせたりしています。

## バリデーションの戦略を考える
細かい話はしませんが、モデルがどれぐらい汎化しているのかを調べるのにクロスバリデーション(CV)というのをしたりします。
CVをどのように行うかは、モデルの汎化性能を測るうえで重要です。

それとは別に、kaggleのリーダーボード(LB)の情報でモデルが汎化しているかを調べることができます。
きちんとモデルをPrivate LBのデータにfitさせることができなければ、順位を大きく下げてしまう原因になります。
モデルがどれぐらい汎化しているのかを測る戦略として主に3つあるようです。(関東kaggler会から情報を仕入れさせていただきました。)

- Trust CV:CVを信じる
- Trust LB:LBを信じる
- Trust Methodology:手法を信じる

- Trust CVが基本です。モデルの精度を測るのにLBより多くのデータを使えるからです。
- Trust LBは、testデータとtrainデータが異なる時によくやります。あと、Public LBスコアの計算に用いるtestデータの数が多ければこの戦略を採用しやすくなります。
- Trust Methodologyは、CVもLBも信じたらよいのか分からない場合にやります。ノイズに強い手法を用いる、などの手法があります。

場合によってはCVでモデルの汎化性能を測りつつ、LBに提出するモデルは全データで学習する場合もあるようです。(特にデータ数が少ないとき)

# リーク(data leakage)に気を付ける
リークとは、モデルが知るはずのないデータを用いてモデルを学習してしまうことです。
これをしてしまうとモデルの汎化性能を大きく落としてしまう原因になるので気を付けましょう。
target encodingはリークの起こりやすい手法なので、できるだけ避けた方が賢明です。
(ただし、target encodingが有効な場合も時々あるので、target encodingをする場合は気を付けて行いましょう。)

リークが起きる可能性がある時にはバリデーションの方法を工夫することによってリークが起きる可能性を無くすことができる場合もあります。
例えば時系列データの場合や似たデータが複数個ある場合にバリデーションをするときにはリークが起きる可能性がありますが、バリデーションの工夫をすればリークが起きる可能性を無くすことができます。

さっきのは自分が起こしてしまうリークですが、kaggleのコンペのホストがリークをしてしまうことがあります。
例えば、データに与えられたidに意味があることや、人為的にデータを切り取ってきているのでデータの最初や最後の部分に意味がある、など。
人工的に作られたデータではホスト側のリークが起こりやすいので、気を付けてみると良いかもしれません。
ホスト側のリークはモデルの精度を上げる大きなチャンスかもしれません。(実務にはあまり役に立たないかもしれませんが…)

## kaggleのアクセレレーターのquotaは毎週土曜日9:00にリセットされる
kaggleのアクセレレーターのquotaは毎週土曜日9:00にリセットされるので、それを見越して行動をしておくとよいです。
submitするときにCodeの実行が必要なコンペに参加する場合で、NotebookでGPUを使用している場合は、quotaが無ければNotebookの実行を行うことができず、submitをする前にはコードの実行が必要なのでsubmitができなくなってしまいます。(submit自体にはquotaは必要ありません。)注意しましょう。

## ニューラルネットワークの学習の中断、再開をしたいときにはmodelだけでなく、optimizerも保存する
optimizerにはlearning rateなどのパラメータが保存されていますので、optimizerも保存しておかないと学習をうまく再会することができないかもしれません。
(pytorch lightningなどを使っていればこのことを知らなくても問題なく学習の中断、再開を出来るのかもしれませんが…)

# Google Colaboratoryを使う場合
## kaggle APIを使うとデータセットのダウンロードなどが便利
ここでは使い方は述べませんが、kaggle APIを使うとkaggleから直接Google Driveにデータセットをダウンロードできます。
データセットの容量を大きくなってくると便利です。

## Google Driveは遅いのでGoogle Colaboratoryを使う場合はディスクにデータをコピーしておく
Google Driveは遅いので、訓練に必要なデータをGoogle Colaboratoryのディスクにデータをコピーしておくとモデルの学習をより速く行うことができます。
(これは人から聞いた情報です。私自身は検証できていないです。)

## ランタイムの再起動をしただけではpipのパッケージ環境やディスクの環境は変わらない
kaggle notebookにおいてランタイムの再起動を行うと、ノートブックに関するすべての環境が初期化されますが、Google Colaboratoryではそうではないです。
どこまで初期化されるのかを明確に調べてはいませんが、おそらくPythonの変数が初期化されています。
pipのパッケージ環境やディスクの環境は変わらないです。
デバッグするときには気を付けましょう。

## Google Colaboratory Pro+でセッションが切れていると思ったら実は切れていないことがある
Google Colaboratory Pro+に登録するメリットとしては、バックグラウンド実行ができることが挙げられます。
この機能を使うときにはノートブックをバックグラウンド実行しておいてあとで実行経過を見るために接続し直すということがあるはずです。
自分の場合はノートブックにもう一度アクセスしたら、何故か実行が止まっている表示になっていることがあって焦りました。
メニューからランタイム->セッションの管理を押すと、現在動いているセッション一覧が現れますので、もしかするとその一覧に自分が実行しているノートブックがあるかもしれません。

当然ながら、(colab pro+で24時間以内であっても)普通に接続が切られることもあるので、定期的にモデルを保存するようにしましょう。

# 最後に
いかがだったでしょうか？
kaggleで知っておいた方が良いことを書いたつもりです。

kaggleはコードを書く練習、データ分析の考え方、機械学習の手法を学ぶことができるとても良いプラットフォームです。
kaggleのコンペに参加していると辛いときがあると思いますが、それでも踏ん張って頑張ると必ず何らかの学びになると思います。
私の場合は、情報が大量にある中で情報を整理し、思考をまとめる能力、アイデアが思いつかない中でも頑張ってアイデアを絞り出す能力を鍛えられたのではないかと思っています。

皆さんも是非kaggleに参加してみてください。
読んでいただき、ありがとうございました。