初心者のkaggleの始め方ベストプラクティス～画像処理編～

今回は僕が、kaggleコンペに初めて本腰を入れて取り組んだ中で考えた,初心者なりのkaggle画像コンペの取り組み方のベストプラクティスをご紹介いたします。

タイトル通り、この記事は画像処理(DeepLearning)が対象であり、タイタニックの様な分析系のコンペを対象にはしておりません。

これからkaggleに挑む(挑んでいる)人の助けになれば幸いです。
kaggleって何？って人は[このスライド](http://www.currypurin.com/entry/2018/02/26/001207)がとてもためになります。
<font color=red>執筆の励みになりますので、よろしければLGTMくださいm(__)m</font>

## この記事の対象者
kaggleコンペに初めて取り組んでいる方、もしくは取り組みたい方
DeepLearningをコンペで使いたい方

# 初心者なりのkaggle(画像処理コンペ)への取り組みベストプラクティス

## 基礎を固めよう
何事も最初が肝心です。
コンペを始める前に基礎を固めることによって、kaggleに取り組んでいる間の勉強(作業)効率が全く違ってきます。

例えば、画像を推論(predict)する際には、一枚一枚for文で回して予測結果を出力することもできますが、バッチ処理をして推論する方が、処理時間が大幅に異なります。


DeepLearningを勉強する上で、おすすめは以下の本です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307982/aad9352e-eb37-a8b1-ad66-c79caaab61c1.png)

初心者としては、一度これをしっかり手を動かしてやることで基礎が身につきます。


## 実際にコンペに取り組んでみる(codeの共有が許可されているもの)

基礎が身についたら、さっそく実践してみましょう。
kaggleを初心者が学ぶ上で活用すべき機能は`notebook`と`discussion`です。

notebookはコンペティションごとに公開されているjupyter notebook形式の記事です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307982/7fdb522b-2c16-7856-407a-dfb8f1b3751a.png)
↑のように様々な人が、どのようにコードを書いているのかが見れるので、とても勉強になります。
また、公開されているnotebookをForkする(自分のnotebookとしてコピーして使うこと)こともできます。notebook形式ですので、もちろん自分で動かして結果を試すこともできます。

discussionはコンペごとに設けられる掲示板のようなものです。
「このような分析をするとこんな感じの結果が出たよ！」とか「このエラーが解決できない」といったいろんな情報や質問をkaggle参加者の間で議論します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307982/b74d6f68-bfaa-e864-3f92-8b554322a7d1.png)


中にはとても有用な情報が飛び交っていたりします。ですので、コンペ期間中には、積極的に活用してスコアを上げていきましょう。

またコンペが終結した後には、「第~位を取った手法」のように、自分たちの分析手法を公開してくれている参加者もいます。

上に挙げたnotebookとdiscussionはどちらも英語で書かれたものがほとんどです(たまにちらほら中国語も)。最近はchromeやedgeの翻訳機能も素晴らしいです。
英語だからって構える必要はありません。
どんどん翻訳していきましょう。

さて、実際のコンペに取り組む際には、いくつか注意しておいた方がいいことがあります。

A. 既に終わっているコンペを選ぶこと
B. ある程度データセットの大きさが小さいものを選ぶこと(10GB以内)
C. コードのシェアが許可されているコンペを選ぶこと

Aに関しては、すでに終わっているコンペだと、様々な議論や有益なnotebookが多数公開されているからです。

この段階での目標は
- 公開されているnotebookを実際に動かしてみて、submissionまでやってみる
- discussionなどでどのような情報が共有されているかを確認する

の2つです。
ですので、いきなり開催中のコンペに参加するよりも、終わっているコンペの方が、短期間で実力を伸ばすことができます。

Bに関しては、自分で試行錯誤するときに、あまりにデータセットの数が多いと苦労するからです。kaggleのnotebookで計算を行う分には問題がないのですが、kaggleのnotebookはGPUが30時間しか使えなかったり、動作が不安定であるなどの問題があるため、あまりお勧めできません。

google colaboratoryか自前のパソコンでやるにしても、10GBを超えるデータセットはメモリ的にもディスク容量的にも、扱いが大変です。

Cに関しては後述しますが、質問などをする際に、シェアが禁止されているコンペだとコードや情報をシェアできないという制約がついてしまいます。

おすすめのコンペはkaggler-jaの[wikiサイト](https://kaggler-ja-wiki.herokuapp.com/kaggle%E5%88%9D%E5%BF%83%E8%80%85%E3%82%AC%E3%82%A4%E3%83%89#%E5%88%9D%E5%BF%83%E8%80%85%E3%81%8A%E5%8B%A7%E3%82%81%E9%81%8E%E5%8E%BB%E3%82%B3%E3%83%B3%E3%83%9A)で紹介されています。参考にしてみて下さい！

## 教えてもらえる環境を整える
(<b>質問などで自分の書いたコードやコンペの情報を他人に共有する場合は、コンペの規約に違反していないかを十分に確認してください。</b>)
やっぱり初心者なので、経験者から教えてもらえると、伸びが全然違います。

でも、身の回りにkaggleの経験者がいる人なんてほとんどいないですよね💦
僕もそうでした。
ですが、心配いりません。世の中には素晴らしいサービスや団体があるのです。

まずご紹介したいのが、日本人kagglerのslackワークスペース
[こちらの記事](https://qiita.com/wakame1367/items/b2d1287ac773ee6bafd0)でも紹介されていますが、beginners-helpというチャンネルで質問することで、高確率で経験者からの回答を得ることができます。

僕も何度もこのslackワークスペースにお世話になりました。(何としても、もっと実力をつけて恩返ししたい所存です🔥)

続いて紹介したいのが、[TechTrain](https://techbowl.co.jp/techtrain)
というサービスです。こちらのサービスですが、30歳以下という制限はありますが、なんと<b>無料で30分間も現役エンジニアの人と面談ができ質問をすることができる</b>激熱なサービスです。
(なんか宣伝みたいになってしまったのですが、本当に素晴らしいサービスだと思うので気にしません)

僕も、コンペの中でうまくいかないことがたくさんあり、5回ぐらいお世話になりましたが、的確に質問に答えてくださりました。

他にも、実際の仕事内容やインターンについても相談に乗っていただけたので、とてもお勧めです。

## 開催中のコンペに参加してみる
さて、いよいよあなたのkaggleライフの始まりです！
開催中のコンペの中から、開始からある程度時間がたっており、活発なコンペを選んで参加してみましょう。

参加した後にやることは以下の通りです。
1. とにかく早くベースラインを構築する
2. (必要があれば) 計算環境を準備する
3. 検証環境を用意する
4. notebookやdiscussionの中から有用そうな手法をまねる
5. 最終手段:アンサンブル

### 1.とにかく早くベースラインを構築する
<b>一番大事なことです</b>。コンペに参加したら、ある程度voteが多いnotebookを写経(notコピペ)してsubmissionまで行って、ベースライン(基礎となるスコア)を出しましょう。

初心者が1からコードを書いてsubmitまでもっていくのは本当に大変な労力です。
pandasやnumpyに結構習熟している必要があるためです。
ですので、最初は丸パクリでも大丈夫なので、経験豊富なkagglerの手法を学びましょう。

### 2.(必要であれば)計算環境を構築する
ベースラインを作った後は、ハイパーパラメーターの調整や特徴量エンジニアリングなど、様々な試行錯誤をする必要があります。
しかし、先ほども説明したように、手持ちのコンピューターの計算能力低いと、試行錯誤するにしてもとても時間がかかってしまいます。

ですので、GPUやTPUが使える、kaggleのnotebookやgoogle colabの使用が検討されますが、両者ともGPUやTPUの使用には制限があり、多数の検証をするには苦しいのが現状です。

そこで、僕がおすすめしたいのはgoogle colaboratoryのpro版です。
これは最近でたサービスなのですが、google colaboratoryの制限がかなり緩和されます。月額約1000円の課金で、GPU環境が手に入るのですから、ちょっとした投資と思って課金することをお勧めします。

使い始めて1か月半ほどですが、印象としては、ほぼ無制限にGPUが使えるという感じです(使用方法によっては制限がかかるらしいですが。)

## 3. 検証環境を用意する
さて、ベースラインもできたし、いろんなパラメーターや手法を試してどんどんスコアを上げていきたいのですが、1つだけ注意点があります。

それは、<b>kaggleのsubmission回数には制限がある</b>ということです。

僕の参加したコンペでは1日の最大提出回数が5回となっていました。
つまり、自分の試した手法が正しいかを判断する機会が1日にたったの5回しか無いということなのです。

これでは十分な試行錯誤をすることができません。
そこで、検証環境を用意します。

scikit-learnの `train_test_split` と `confusion_matrix`を使用します。

まず最初に`train_test_split`を使い、<b>訓練データを疑似的な訓練データとテストデータ</b>に分けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307982/9c55e1b0-02d6-b443-2a2f-4ce2a5e1d2bf.png)


そして、訓練では疑似的な訓練データのみを使ってモデルを訓練します。
訓練が終わった後に、疑似的なテストデータを使ってモデルの正答率を検証します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307982/3e507c9b-a1dc-50ed-e01e-d8c8d0a96b94.png)


こうすることで、submitしなくても、自分が作ったモデルの性能がわかります。

続いて、`confusion_matrix`を用いて、混合行列を作成します。
混合行列については[こちらの記事](https://note.nkmk.me/python-sklearn-confusion-matrix-score/)がわかりやすいです。

詳しい説明は省きますが、混合行列を作成することで、モデルがどのクラスとどれを間違えているのかを知ることができます。

![inspectionResnetv2_ep15_steps_per_epoch2.png0.31332357247437775.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307982/40857574-d484-16cd-9e30-d6dbc77bc787.png)

↑は僕が実際にやってみた例です。
0番にまちがえて推論してしまった例が他に比べて多いことや、0番と推論すべきところを2番に間違えているのだな。ということがわかります。

間違いの種類が分かれば、データとにらめっこしたり、1枚1枚推論することで、どのような特徴量をとらえられていないのかがわかるので、画像の前処理やパラメーター変更などの助けになります。

## 4. notebookやdiscussionの中から有用そうな手法をまねる
実際にnotebookやdiscussionを漁り、様々な方法をトライしていきます。
以下では、僕がdiscussionやnotebookで「？」となった用語をまとめてみます。

|俗称|意味|
|---|---|
|fold K(Kは数字) |[k分割交差検証法](https://toukei-lab.com/cross-validation)|
|lr|学習率(learning rate)のこと。均一な学習率ではなく、epochごとに学習率をチューニングしてあげることで、モデルの精度が結構変わります。[参考](https://qiita.com/MIPPS/items/0d2b0af81671808e19f5)|
|EDA|Exploratory Data Analysisの略。どんなデータがあるのかを実際に見たり、各種統計量などを整理することです。|
|fine tune|ファインチューニング,学習済みモデルの一部の層を学習させず(frozen)、少ないデータで学習させること|
|~~net|たいていの場合は学習済みモデルのこと|
|data augmentation(水増し)|モデルに入力する画像を加工して、枚数を増やすテクニック。少ない訓練画像でもモデルの精度を上げるために必須です。[このページ](https://gcbgarden.com/2018/02/20/data-augmentation-tf/)が参考になります。|
|Pseudo labeling|半教師あり学習のこと。[この記事](https://qiita.com/koshian2/items/f4a458466b15bb91c7cb)がわかりやすいです。|
(随時更新していこうと思います。)

こうして試行錯誤していくのはいいのですが、注意すべきことが2つあります。
1つ目は、乱数のseedは固定すること
2つ目は、試行錯誤の証をちゃんと記録を残しておくこと

1つ目に関しては、乱数のseedを固定することで、同じ手法で同じパラメーターを使えば全く同じ結果を得ることができます。
終盤はスコアが0.001上がるか下がるかで、順位に差がつくこともあります。ちゃんとした評価をするためにも乱数のseedは固定するようにしましょう。

2つ目に関しては、試したい手法やパラメーターはたくさんありますが、使える時間や計算資源は有限なので、ムダなことをしないためです。
特にいろいろ手法を試していくと、どの手法でどれぐらいの結果が出たのかがごっちゃになってきます。
僕はnotionというアプリで記録してましたが、単純にスプレッドシートとかでもいいかもしれませんね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307982/cb3c660e-e6e1-a651-451e-e307f6213898.png)


## 5. 最終手段　アンサンブル
最後の手段として、アンサンブルという手法があります。
これは、様々なモデルで学習した結果を加重平均して、結果を出すことです。

大体の場合、アンサンブルを行うことでスコアはよくなります。
しかし、この方法には最初はなるべく頼るべきではありません。
なぜなら、アンサンブルによってスコアが60から80に上がるといった劇的な変化はまず、見られないからです。

一つのモデル単体で頑張って、最後の最後に、奥の手としてアンサンブルを使うようにしましょう。
## 試行回数を増やす

Kaggle自体の枠組みに慣れてきたら、次は試行回数を増やして、より良いモデルや手法を見つけていきましょう。成功確率というのは、一定の努力をちゃんとすればある程度までは上げることができると思います。例えば、Kaggleにおいて良さそうな論文や手法が紹介されているのをくまなくチェックすることで大まかな方向性を外して、確率の低い実験を沢山するということがなくなると思います。
しかし、それ以上はセンスだったり経験がものを言うと思います。
なので、結果を出すためには試行回数を増やす必要があります。試行回数の増やし方について下記記事で紹介していますので、参考にしてみてください。

https://qiita.com/ryuichiastrona/items/e213c6a11f5b43821aab
## 次のレベルへ
以下は現在、僕が勉強していてためになると感じた本や記事です。

[ゼロから作るDeepLearning3](https://www.amazon.co.jp/%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E4%BD%9C%E3%82%8BDeep-Learning-%E2%80%95%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF%E7%B7%A8-%E6%96%8E%E8%97%A4-%E5%BA%B7%E6%AF%85/dp/4873119065)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307982/a6b7d2e6-7bb3-62d2-278e-30a4445dc99f.png)


冒頭に紹介した本のシリーズ第3段
DeepLearningではTensorFlowやPytorchと行ったフレームワークを用いることが多いですが、初心者の私達はその全体像をよく知りません。この本で学習することで、フレームワークの実装に詳しくなれます。

しかし、何も知らずにこれをやると結構難しいと思います。少なくとも、Pythonのオブジェクト指向と、第1弾の内容を理解した上で学習を始めるといいと思います。

[kaggleで勝つデータ分析の技術](https://www.amazon.co.jp/Kaggle%E3%81%A7%E5%8B%9D%E3%81%A4%E3%83%87%E3%83%BC%E3%82%BF%E5%88%86%E6%9E%90%E3%81%AE%E6%8A%80%E8%A1%93-%E9%96%80%E8%84%87-%E5%A4%A7%E8%BC%94-ebook/dp/B07YTDBC3Z/ref=mp_s_a_1_1?dchild=1&keywords=kaggle%E3%81%A7%E5%8B%9D%E3%81%A4%E3%83%87%E3%83%BC%E3%82%BF%E5%88%86%E6%9E%90%E3%81%AE%E6%8A%80%E8%A1%93&qid=1591276388&sprefix=kaggle&sr=8-1)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307982/74273903-cfe6-701b-a08c-0e76d24ab85b.png)


機械学習全般について書かれています。
最初からこれをやろうとして、僕は挫折しました。一回コンペを経験したあとに、一度サラッと読み、その後は辞書的に使うのをおすすめします。

kaggleに必要な様々な手法が網羅されており、実装のコードが載っていたり、著者の個人的な意見が含まれており、大変ためになる本です。


## おまけ（Pythonで画像を扱うときのPILとOpenｃｖの注意）
Pythonで画像を扱う場合は、PillowかOpenCVというライブラリを使うことが多いと思います。
どちらを使っても基本的に問題はないのですが、OpenCVで画像を扱うときは、BGRで画像が読み込まれることに注意が必要です。
なぜなら、DeepLearningモデルで学習でRGB画像を使ったのに、テスト画像に対して、BGR画像を入力として入れてしまい、全く精度が出ないということが起こり得るからです。

RGB、BGRって何？というかたは[このページ](https://your-3d.com/python-rgb/)を一読することをすることをお勧めします。


## 終わりに
今回参加したコンペは植物の葉っぱを4分類するというコンペでした→[リンク](https://www.kaggle.com/c/plant-pathology-2020-fgvc7/rules)
今回のコンペでは、大学の課題などであまり時間が取れず、1317エントリー中442位という不甲斐ない結果に終わってしまいました。

しかし、この記事に書いたように多くのことを学ぶことができました。
質問に答えてくださった、slackワークスペースkaggler-jaの皆様や、tech-trainのメンターの方々に本当に感謝です。

次回はさらに実力をつけてメダル獲得を目指していきたいと思います。
記事内に間違いや改善点などございましたら、コメントにてご指摘いただけると嬉しいです。