Google Colaboratoryを使ってMNISTデータの学習などをやってみる①


# はじめに

前から気になっていたGoogle Colaboratoryを使ってみることにしました。
最初とはいえ、多少は実践的なことをしたいので、MNISTデータを使ったCNNモデルの作成と、LIMEを使った説明可能性をやってみたいと思います。

Colaboratoryを使う際の全般的な解説は以下をご参照ください。
[【秒速で無料GPUを使う】深層学習実践Tips on Colaboratory](https://qiita.com/tomo_makes/items/b3c60b10f7b25a0a5935)

#Google DriveにColaboratoryを接続する
私はGoogle Driveに趣味のファイルをあげているので、ここを作業するベースの場所とします。

Google Drive の「+New」をクリックした、「Connect more apps」を選びます。

<img width="400" alt="000_最初の新規作成.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225870/9041aa0e-f4e1-3625-edb5-32302c92871c.png">

そして、Colaboratoryを検索して、「Connect」をクリックし、Google DriveからColaboratoryを使えるようにします。
<img width="446" alt="001_Colaboratoryの接続.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225870/00807c21-2da8-0927-5b3d-9ae0aed56025.png">

そうすると、ファイルを新規作成する「+New」からColaboratory用のファイルを選択できます。
新規の空白のipynbファイルを早速作ります。
<img width="396" alt="002_Make_New_Colaboratory.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225870/b139367d-c8b1-136b-2603-00ca30ed6073.png">

ランタイムのタイプをGPUに変更することを忘れないようにしましょう。
<img width="382" alt="003_ランタイムのタイプ.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225870/c3d0ea2d-264a-da41-8f29-3547517317d0.png">

<img width="331" alt="004_GPU選択.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225870/3697efa1-e22a-657f-a553-b04c81a230bd.png">


# CNNのコードを書く

このファイルに、
[Keras公式 CNN MNISTのページ](https://keras.io/examples/mnist_cnn/)にあるコードを記載します。
まずはkerasのインポート、MNISTデータへの前処理、そしてCNNモデルの定義まで。

```
from __future__ import print_function
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K

batch_size = 128
num_classes = 10
epochs = 12

# input image dimensions
img_rows, img_cols = 28, 28

# the data, split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()

if K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])
```
公式ページのコードのままだと、モデルの構造が出力されないので、以下のコードを追加しました。

```
model.summary()
```
このようなモデルができています。
<img width="386" alt="005_model_summary().png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225870/88cec364-9cf5-89b7-9236-65282a2e3a1f.png">

早速実行させてみましょう。学習の履歴をあとで表示できるよう、Keras公式ページのコードに少しだけ手を加えています。

```
%%time
history = model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(x_test, y_test))
```
次のような結果が得られました。
<img width="664" alt="010_Coraboratory_学習時間.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225870/b6fc0414-c77c-97a6-6910-85dacb2646fc.png">

1分弱で計算が終わっています！
あとはモデルの精度検証と、学習履歴の表示です。

```
# モデルの評価
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
```

Test loss: 0.027914887178201026
Test accuracy: 0.9934

テストデータに対する精度は99.34%出ていますね。

```
import matplotlib.pyplot as plt
# 学習の履歴をグラフ化
plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('Accuracy')
plt.legend(['train', 'test'], loc='upper left')
plt.show()
```

![011_history_plot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225870/a1720c65-3b2f-57ed-a051-925d07bad974.png)

テストデータに対しても最初のエポックからそれなりの結果が出ていますね。

# 私のローカルPCとの比較
それにしても、無料でGPUが使えて、この速度で計算できるのはすごいです。
ちなみに、同じコードを私のPC（XPS13,　Intel CORE i5なので比較対象とし貧弱ですが、、）での結果は
<img width="569" alt="021_my_local_PC.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225870/93b88c83-f2cf-3cfd-c800-4acfedf6a5f3.png">

__私のPCでは約1時間20分もかかってます。Colaboratoryは80倍速いです！__
軽いデータで、深層学習を色々試すならColaboratoryを使うのが時間の節約です。

今回はここまで。
次回はモデル式を保存したり、LIMEを適用したりしたいと思います。