Google Colaboratoryを用いてKaggle画像コンペに挑戦する際のポイント

# 背景
**画像コンペやってみてぇなぁ・・・**
みなさん一度はこう考えたことはあるかと思います。

しかし、画像コンペに取り組む際に一つのハードルがそう
**GPU環境の用意**です！！！

GCPやAWSに契約するとお金がかかります。
でもコンペに取り組む場合、より良い環境構築も非常に重要な要素です。

**お金は節約したい・・・でも画像コンペやりたい・・・・**

そんな願いを両方実現するべくに、今回はGoogleColaboratory(以下、Colabと略します。)という
無料のGPU環境でKaggleの画像コンペに挑む際の注意点をまとめてみました。

# 概要
 - いきなりですが、実際に取り組んだ結果、

**Colabだけだとやっぱりしんどいのでは**

　という結論です。(おい

※2021/4/1追記：最近はColabでの制約が減ったり、ColabProの登場など、Colabで十分戦える、という情報をよく見ます。あくまで、2019/12頃の話です。

 - ただ、短い計算のみでの使用や、多少不便な部分を我慢すればいけなくもないかも、という感じです。

 - 僕はメインの計算は有料のクラウドを用い、PostProcessing（後処理）の計算のみColabで行うことで、少しでもクラウド代を節約してます。

 - より良い方法があったら是非是非教えてください！

# GoogleColaboratoryとは
Googleが提供する計算環境です。無料でGPUの使用ができます。素敵。
https://colab.research.google.com/notebooks/welcome.ipynb?hl=ja

# GoogleColaboratoryでのGPUの立ち上げ方
１　ファイル→「Python3の新しいノートブック」をクリック
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390595/d75189e0-3e4a-7a54-9695-8101959ae9f5.png" width=50%>


２　ランタイム→「ランタイムのタイプを変更」
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390595/8d09e267-8d44-2fe6-2700-f76820887422.png" width=50%>

3 ハードウェアアクセラレータを「GPU」に変更し、「保存」
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390595/89dd65a7-827b-c65f-c475-08c1fa239f0b.png" width=50%>

4 !nvidia-smi とセルに入力し、実行するとGPUがセットされていることがわかります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390595/b3a67d88-7015-9cfe-8037-bcf11a7dd0ee.png" width=50%>

# GoogleColaboratoryにて画像コンペに取り組む際のポイント

本題です。下記にポイントをまとめました！

 - 何も動作しないと90分で接続切れを起こす。
 - インスタンスを作成してから12時間で強制的にインスタンス削除
 - Kaggle APIの導入をしておくとsubmitが楽チン
 - Google Driveをマウントすることで、計算結果の保存が可能

それぞれ詳しく見ていきます。

### 何も動作しないと90分で接続切れを起こす。

Colabさんは90分間アクセスがないと認識すると
勝手に接続を切ってしまいます。
これは長時間の学習が必要な画像コンペでは結構な痛手です。
ただし、回避法があります。

回避法については下記記事の説明が非常にわかりやすかったため紹介します。
簡単に記載すると
 - 自動的にアクセスしにいくスクリプトを作成
 - 画面上でマウスを自動的にちょっと動かしてくれるアドオンを利用
のどちらかで接続切れを防ぐ方法です。

Google Colaboratoryの90分セッション切れ対策【自動接続】
https://qiita.com/enmaru/items/2770df602dd7778d4ce6

### インスタンスを作成してから12時間で強制的にインスタンス削除

これが、Colabだけだと画像コンペにずっと取り組み続けるのが辛いと思う一番の理由です。

まず初めにインスタンスとは、計算用の仮想環境のことを表します。
Colabにログインすると自動的にインスタンスが生成されるようです。

つまり、"インスタンスを作成" = "Colabを立ち上げた瞬間"です！
下記画面が立ち上がった瞬間に、インスタンス終了(１２時間後)までのカウントダウンが始まります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390595/e4b826f5-0da4-3178-ad6b-3157dcc2e8f8.png" width=70%>

**このカウントダウンはGoogleのアカウントをログアウト、再ログインを行ったり、
ページを更新しても改めてカウントされなおすことはありません。**

自分が調べた限りでは、このカウントダウンを手動で最初からやりなおす方法はなさそうでした・・・

つまり、
「よーし、Colabで画像コンペがんばるぞっ！まずはちょっとコード書くかな・・・」

～なんやかんやで４時間経過～

「おーしっ、コード書けたっ！この学習モデルを回したらどうなるのか、
　楽しみだっ！よしっ！学習開始ッ！！！！！！」

～８時間後～

「もうちょっとで計算が終わるっ！！！計算結果は！！！？？？」
「ってインスタンス落ちとるやないかーーい！！！！！！」

ってなります。

このパターンが多かったため、僕はColabでは限界がある（効率が悪い）かなと思いました。
ただし、比較的短い計算であったり、上記の不便さに慣れてくると、
Colabでも十分戦える可能性があると思っています。

僕の場合、PostProcessingのような短い計算はColabで行い、
メインの計算はお金を払ってクラウドで計算する、という方法を取っていました。

経験的に、hold outでの計算であれば12時間以内に収まりますが、
k-foldを行うと12時間を突破するかなという所感です。

### Kaggle APIの導入をしておくとsubmitが楽チン

Google ColaboratoryにKaggle APIを導入しておくと、
submitやデータのダウンロードが楽になります。下記にその手順を示します。

#### 1 kaggle.jsonの入手＆upload

まず、kaggle APIを使うために必要なkaggle.jsonを入手します。
下記のように、Kaggleのページから「My Account」をクリックします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390595/1b26cf16-2b59-1a3e-9d53-1b3887d897c4.png" width=30%>

下記の「Create New API Token」をクリックすると、「kaggle.json」がダウンロードできます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390595/2f22c1e6-8471-0e6c-7a6c-e06d2a04177e.png" width=100%>

下記コマンドを実行します。

```python
from google.colab import files
files.upload()
```

すると、下記のようなファイルアップロードの画面になります。
「ファイル選択」のボタンをクリックし、先ほどダウンロードしたkaggle.jsonのアップロードを行います。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390595/b2727b09-c9b7-3a2a-872b-a42d41f02118.png" width=70%>


#### 2 kaggle.jsonをインスタンス内の適切な位置にコピー
下記のコマンドを実行し、kaggle.jsonをインスタンス内の適切な位置にコピーします。
その後、kaggle.jsonのパーミッションを変更することで、操作する権限を付与しています。

```python
!rm -r ~/.kaggle

!mkdir -p ~/.kaggle
!cp kaggle.json ~/.kaggle/

!chmod ~/root/.kaggle/kaggle.json
```

#### 3 Kaggle APIを使って、コンペのデータをダウンロードする。

下記のようなコードを用いて、コンペのデータをダウンロードします。

```python
!kaggle competitions download -c understanding_cloud_organization
```

この例では、Kaggleの画像コンペ「Understanding Clouds from Satellite Images」の
データがダウンロードされます。このコマンドはコンペの「Data」タブに記載されています。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390595/0720c6d5-35be-41ca-e348-85dead1c75af.png" width=100%>

https://www.kaggle.com/c/understanding_cloud_organization/data

それぞれ、該当のコンペのコマンドに置き換えてください。

このAPIの最も便利な部分はsubmitがNotebook上で行えることかと思います。
例えば、df_submissionというデータフレームに関して、

```python
df_submission.to_csv('/content/drive/My Drive/Kaggle/submission_case0.csv', index=None)
```

と、CSVに吐き出してあげて（パスは個人毎に異なります。）

```python
!kaggle competitions submit -c understanding_cloud_organization -f '/content/drive/My Drive/Kaggle/submission_case0.csv' -m case0
```

ってやるとNotebook上からsubmitができます！便利！
-m に書いたコメントは、submit画面のメッセージとして反映されます。

### Google Driveをマウントすることで、計算結果の保存が可能

インスタンスは12時間で強制削除されてしまいますが、GoogleDriveをマウントすることで
個人のstorageに計算結果を出力できるため、より効率的な作業が可能となります。

これはマウントによって、ColabさんとGoogleDriveを繋ぎ
Colab上からGoogleDriveの保存領域を直接操作できる状態になるためです。便利。

下記では、そのマウント方法を記載します。

まずは下記コードを実行します。

```python
from google.colab import drive
drive.mount('/content/drive')
```

すると下記のような画面が出てきます。
URLの部分をクリックします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390595/c313cc6f-45e9-13ab-5b37-11c32258ba8a.png" width=70%>

すると、下記のような画面が現れます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390595/b9bea366-e431-ebc6-0126-c442445618b1.png" width=50%>
使用するアカウントをクリックします。
すると下記画面が現れるため、「許可」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390595/d4a75484-afe4-a579-810d-f8938558e06e.png)

画面にキーが表示され、コピーするボタンが表示されるので、
そのキーを最初の画像の「Enter your authorization code」に入力すると、ドライブがマウントされます。

# 最後に
恐らく、自分が記載した方法より良いColabの活用方法があるかと思います！
もしご存知の方いたら是非教えて下さい！