script day.log

大学生がなんとなく始めた、趣味やら生活のことを記録していく。

Google Colaboratoryを使った GPU学習環境の実験

今回はGoogle Colaboratoryを使って、
DeepLearningのGPU学習環境が出来るとtwitterで見たので、実験しました。

とりあえず単純にMNISTのCNNやります。
提供されるマシンスペックは次の通りらしいです。

n1-highmem-2 instance
2vCPU @ 2.2GHz
13GB RAM
33GB Free Space
idle cut-off 90 minutes
maximum 12 hours

stackoverflow.com

さあ、始めましょう。
はじめに新規ノートブックの作成を行います。
ノートブックを新規作成よりPython3の新しいノートブックを選びます。

次にランタイムよりランタイムのタイプを変更、ノートブックの設定を開き、
ハードウェアアクセラレータにGPUを選択し、保存します。

新しくセルを作り、下記を入力し、実行する。

import tensorflow as tf
tf.test.gpu_device_name()

下記が出力されれば、GPUアサインされています。

'/device:GPU:0'

CPU/GPUのパフォーマンスを比較してみます。

import tensorflow as tf
import timeit

# See https://www.tensorflow.org/tutorials/using_gpu#allowing_gpu_memory_growth
config = tf.ConfigProto()
config.gpu_options.allow_growth = True

with tf.device('/cpu:0'):
  random_image_cpu = tf.random_normal((100, 100, 100, 3))
  net_cpu = tf.layers.conv2d(random_image_cpu, 32, 7)
  net_cpu = tf.reduce_sum(net_cpu)

with tf.device('/gpu:0'):
  random_image_gpu = tf.random_normal((100, 100, 100, 3))
  net_gpu = tf.layers.conv2d(random_image_gpu, 32, 7)
  net_gpu = tf.reduce_sum(net_gpu)

sess = tf.Session(config=config)

# Test execution once to detect errors early.
try:
  sess.run(tf.global_variables_initializer())
except tf.errors.InvalidArgumentError:
  print(
      '\n\nThis error most likely means that this notebook is not '
      'configured to use a GPU.  Change this in Notebook Settings via the '
      'command palette (cmd/ctrl-shift-P) or the Edit menu.\n\n')
  raise

def cpu():
  sess.run(net_cpu)

def gpu():
  sess.run(net_gpu)

# Runs the op several times.
print('Time (s) to convolve 32x7x7x3 filter over random 100x100x100x3 images '
      '(batch x height x width x channel). Sum of ten runs.')
print('CPU (s):')
cpu_time = timeit.timeit('cpu()', number=10, setup="from __main__ import cpu")
print(cpu_time)
print('GPU (s):')
gpu_time = timeit.timeit('gpu()', number=10, setup="from __main__ import gpu")
print(gpu_time)
print('GPU speedup over CPU: {}x'.format(int(cpu_time/gpu_time)))

sess.close()

下記のような出力が得られると思います。

Time (s) to convolve 32x7x7x3 filter over random 100x100x100x3 images (batch x height x width x channel). Sum of ten runs.
CPU (s):
8.584801190000007
GPU (s):
0.8974968620000254
GPU speedup over CPU: 9x

では、kerasの実行環境を用意しましょう。

!pip install -q keras
import keras

下記の出力が得られる。

Using TensorFlow backend.

ここからが本題です。
データセットの準備を行います。

from keras.datasets import mnist
mnist.load_data()

次に学習を行います。

from __future__ import print_function
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import RMSprop
	
batch_size = 128
num_classes = 10
epochs = 20
	
# the data, shuffled and split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()
	
x_train = x_train.reshape(60000, 784)
x_test = x_test.reshape(10000, 784)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
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(Dense(512, activation='relu', input_shape=(784,)))
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(num_classes, activation='softmax'))
	
model.summary()
	
model.compile(loss='categorical_crossentropy',
optimizer=RMSprop(),
metrics=['accuracy'])
	
history = model.fit(x_train, y_train,
batch_size=batch_size,
epochs=epochs,
verbose=1,
validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

問題なく実行されれば、以下のような出力が得られるでしょう。

60000 train samples
10000 test samples
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_1 (Dense)              (None, 512)               401920    
_________________________________________________________________
dropout_1 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 512)               262656    
_________________________________________________________________
dropout_2 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_3 (Dense)              (None, 10)                5130      
=================================================================
Total params: 669,706
Trainable params: 669,706
Non-trainable params: 0
_________________________________________________________________
Train on 60000 samples, validate on 10000 samples
Epoch 1/20
60000/60000 [==============================] - 3s 53us/step - loss: 0.2428 - acc: 0.9256 - val_loss: 0.1074 - val_acc: 0.9653
Epoch 2/20
27392/60000 [============>.................] - ETA: 1s - loss: 0.1097 - acc: 0.9663

60000/60000 [==============================] - 3s 49us/step - loss: 0.1041 - acc: 0.9685 - val_loss: 0.0861 - val_acc: 0.9745
Epoch 3/20
60000/60000 [==============================] - 3s 48us/step - loss: 0.0753 - acc: 0.9771 - val_loss: 0.0678 - val_acc: 0.9805
Epoch 4/20
60000/60000 [==============================] - 3s 48us/step - loss: 0.0586 - acc: 0.9816 - val_loss: 0.0747 - val_acc: 0.9800
Epoch 5/20
60000/60000 [==============================] - 3s 49us/step - loss: 0.0490 - acc: 0.9846 - val_loss: 0.0684 - val_acc: 0.9816
Epoch 6/20
60000/60000 [==============================] - 3s 49us/step - loss: 0.0428 - acc: 0.9875 - val_loss: 0.0697 - val_acc: 0.9808
Epoch 7/20
 7040/60000 [==>...........................] - ETA: 2s - loss: 0.0356 - acc: 0.9895

60000/60000 [==============================] - 3s 48us/step - loss: 0.0390 - acc: 0.9887 - val_loss: 0.0754 - val_acc: 0.9826
Epoch 8/20
60000/60000 [==============================] - 3s 49us/step - loss: 0.0345 - acc: 0.9895 - val_loss: 0.0770 - val_acc: 0.9844
Epoch 9/20
60000/60000 [==============================] - 3s 48us/step - loss: 0.0298 - acc: 0.9911 - val_loss: 0.0807 - val_acc: 0.9835
Epoch 10/20
60000/60000 [==============================] - 3s 49us/step - loss: 0.0275 - acc: 0.9921 - val_loss: 0.1040 - val_acc: 0.9800
Epoch 11/20
60000/60000 [==============================] - 3s 48us/step - loss: 0.0284 - acc: 0.9921 - val_loss: 0.0987 - val_acc: 0.9808
Epoch 12/20
 3712/60000 [>.............................] - ETA: 2s - loss: 0.0217 - acc: 0.9925

60000/60000 [==============================] - 3s 48us/step - loss: 0.0225 - acc: 0.9936 - val_loss: 0.0959 - val_acc: 0.9829
Epoch 13/20
60000/60000 [==============================] - 3s 49us/step - loss: 0.0231 - acc: 0.9935 - val_loss: 0.0934 - val_acc: 0.9834
Epoch 14/20
60000/60000 [==============================] - 3s 49us/step - loss: 0.0225 - acc: 0.9938 - val_loss: 0.0895 - val_acc: 0.9842
Epoch 15/20
60000/60000 [==============================] - 3s 49us/step - loss: 0.0211 - acc: 0.9939 - val_loss: 0.1082 - val_acc: 0.9833
Epoch 16/20
60000/60000 [==============================] - 3s 48us/step - loss: 0.0202 - acc: 0.9946 - val_loss: 0.1097 - val_acc: 0.9832
Epoch 17/20
 3584/60000 [>.............................] - ETA: 2s - loss: 0.0216 - acc: 0.9953

60000/60000 [==============================] - 3s 49us/step - loss: 0.0187 - acc: 0.9951 - val_loss: 0.1067 - val_acc: 0.9831
Epoch 18/20
60000/60000 [==============================] - 3s 49us/step - loss: 0.0210 - acc: 0.9949 - val_loss: 0.1048 - val_acc: 0.9832
Epoch 19/20
60000/60000 [==============================] - 3s 49us/step - loss: 0.0187 - acc: 0.9952 - val_loss: 0.0997 - val_acc: 0.9852
Epoch 20/20
60000/60000 [==============================] - 3s 48us/step - loss: 0.0179 - acc: 0.9954 - val_loss: 0.1143 - val_acc: 0.9842
Test loss: 0.1142890711386806
Test accuracy: 0.9842

これで終了なのですが、Google Colaboratory非常に便利ですね。
無料だし、セットアップする必要が無いので、初学者のスタートアップや
ハンズオンには非常に使いやすいものとなっています。