こちらで、Google ColaboratoryでTPUが使えるようになったと知り、早速試してみました。
元のコード等はこちら。
設定
Googleドライブのマウント
以前書いたコードのまま実行しようとしたところ、エラーに。
E: Unable to locate package google-drive-ocamlfuse
調べてみるとこちらに情報が。
そっか、簡単になっていたのね。
from google.colab import drive
drive.mount('/content/drive')
この修正に関連して、パスが変わった(「drive/xxx」→「drive/My Drive/xxx」)ので、そこだけはコードを変更します。
とりあえずそのまま実行
Kerasのパスとか変更しなくてはいけないことはわかっているが、エラーになる体験もしてみたいので、そのまま実行。
Downloading data from https://github.com/fchollet/deep-learning-models/releases/download/v0.5/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5
87916544/87910968 [==============================] - 7s 0us/step
Train on 162 samples, validate on 18 samples
Epoch 1/1000
162/162 [==============================] - 248s 2s/step - loss: 0.6976 - acc: 0.5617 - val_loss: 0.6406 - val_acc: 0.7222
Epoch 2/1000
64/162 [==========>...................] - ETA: 2:13 - loss: 0.5129 - acc: 0.7812
おや?変な動きだけど、エラーにはならない...というか、すごく遅い!
一旦止めて、もう一度やり直してみる、が遅い状況は変わらず。
コードを修正する
ということで、「keras」を「tensorflow.keras」に置き換えて、実行し直しています。
Train on 162 samples, validate on 18 samples
Epoch 1/1000
162/162 [==============================] - 239s 1s/step - loss: 0.7062 - acc: 0.5309 - val_loss: 0.7075 - val_acc: 0.5556
Epoch 2/1000
64/162 [==========>...................] - ETA: 2:15 - loss: 0.5428 - acc: 0.8281
はて?変わらず遅いままだぞ??
※実行速度もほとんど変わっていない
TPUの恩恵を受けているどころか、GPUよりも遥かに(140倍!)遅い...
修正漏れ発見
じっくりと確認してみたところ、他にも修正が必要なところがあることがわかりました。
from tensorflow.contrib.tpu.python.tpu import keras_support
# 途中省略
# TPU
tpu_grpc_url = "grpc://"+os.environ["COLAB_TPU_ADDR"]
tpu_cluster_resolver = tf.contrib.cluster_resolver.TPUClusterResolver(tpu_grpc_url)
strategy = keras_support.TPUDistributionStrategy(tpu_cluster_resolver)
model = tf.contrib.tpu.keras_to_tpu_model(model, strategy=strategy)
再度実行してみたところ、今度はエラーが発生。
ValueError:
Layer <tensorflow.python.keras.engine.input_layer.InputLayer object at 0x7febf3fdfef0> has a variable shape in a non-batch dimension. TPU models must
have constant shapes for all operations.
You may have to specify `input_length` for RNN/TimeDistributed layers.
Layer: <tensorflow.python.keras.engine.input_layer.InputLayer object at 0x7febf3fdfef0>
Input shape: (None, None, None, 3)
Output shape: (None, None, None, 3)
InceptionV3(tensorflow.keras.applications.inception_v3.InceptionV3)を使用しているのですが、ちゃんとinput_shapeを明記してあげないといけないようです。
base_model = InceptionV3(weights='imagenet', include_top=False, input_shape=(299,299,3))
しかしまだエラーが。
AssertionError: batch_size must be divisible by strategy.num_towers (52 vs 8)
はて、指定しているバッチサイズは「64」なんだけど...
あ、学習データが90枚×2種類で180枚、64バッチで学習させるから、余りが52ってことか?
では合計128枚(64枚×2)にして、64バッチにして...へ?ダメ???
ではでは合計160枚にして、16枚評価用にして、バッチサイズを72にすると...
INFO:tensorflow:Querying Tensorflow master (b'grpc://10.104.87.194:8470') for TPU system metadata.
INFO:tensorflow:Found TPU system:
INFO:tensorflow:*** Num TPU Cores: 8
INFO:tensorflow:*** Num TPU Workers: 1
INFO:tensorflow:*** Num TPU Cores Per Worker: 8
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:CPU:0, CPU, -1, 13775578281952910176)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:XLA_CPU:0, XLA_CPU, 17179869184, 11472039453562412302)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:XLA_GPU:0, XLA_GPU, 17179869184, 16699149825347599599)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:0, TPU, 17179869184, 12947970202392715099)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:1, TPU, 17179869184, 5831191770111493889)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:2, TPU, 17179869184, 12266886104312379857)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:3, TPU, 17179869184, 12195656273203857672)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:4, TPU, 17179869184, 5342099664455282737)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:5, TPU, 17179869184, 4909200579248859706)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:6, TPU, 17179869184, 6257043378114727165)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:7, TPU, 17179869184, 11756941070616601390)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU_SYSTEM:0, TPU_SYSTEM, 17179869184, 2180101584340784034)
WARNING:tensorflow:tpu_model (from tensorflow.contrib.tpu.python.tpu.keras_support) is experimental and may change or be removed at any time, and without warning.
Train on 160 samples, validate on 16 samples
Epoch 1/1000
INFO:tensorflow:New input shapes; (re-)compiling: mode=train, [TensorSpec(shape=(9, 299, 299, 3), dtype=tf.float32, name='input_20'), TensorSpec(shape=(9, 1), dtype=tf.float32, name='dense_3_target_10')]
INFO:tensorflow:Overriding default placeholder.
INFO:tensorflow:Remapping placeholder for input_2
INFO:tensorflow:Cloning SGD {'lr': 0.009999999776482582, 'momentum': 0.8999999761581421, 'decay': 0.0, 'nesterov': False}
INFO:tensorflow:Get updates: Tensor("loss_1/add:0", shape=(), dtype=float32)
INFO:tensorflow:Started compiling
INFO:tensorflow:Finished compiling. Time elapsed: 93.16143774986267 secs
INFO:tensorflow:Setting weights on TPU model.
72/160 [============>.................] - ETA: 2:56 - loss: 0.6279 - acc: 0.5556INFO:tensorflow:New input shapes; (re-)compiling: mode=train, [TensorSpec(shape=(2, 299, 299, 3), dtype=tf.float32, name='input_20'), TensorSpec(shape=(2, 1), dtype=tf.float32, name='dense_3_target_10')]
INFO:tensorflow:Overriding default placeholder.
INFO:tensorflow:Remapping placeholder for input_2
INFO:tensorflow:Cloning SGD {'lr': 0.009999999776482582, 'momentum': 0.8999999761581421, 'decay': 0.0, 'nesterov': False}
INFO:tensorflow:Get updates: Tensor("loss_2/add:0", shape=(), dtype=float32)
INFO:tensorflow:Started compiling
INFO:tensorflow:Finished compiling. Time elapsed: 52.98347616195679 secs
144/160 [==========================>...] - ETA: 30s - loss: 0.6840 - acc: 0.5000 INFO:tensorflow:New input shapes; (re-)compiling: mode=eval, [TensorSpec(shape=(2, 299, 299, 3), dtype=tf.float32, name='input_20'), TensorSpec(shape=(2, 1), dtype=tf.float32, name='dense_3_target_10')]
INFO:tensorflow:Overriding default placeholder.
INFO:tensorflow:Remapping placeholder for input_2
INFO:tensorflow:Cloning SGD {'lr': 0.009999999776482582, 'momentum': 0.8999999761581421, 'decay': 0.0, 'nesterov': False}
INFO:tensorflow:Started compiling
INFO:tensorflow:Finished compiling. Time elapsed: 43.58580756187439 secs
160/160 [==============================] - 327s 2s/step - loss: 0.6705 - acc: 0.5500 - val_loss: 0.8207 - val_acc: 0.5000
(以下、省略)
(何故か)動いた!
が、始まるまでが遅い!!(苦笑)
TPU用のバイナリに変換するのが遅い模様。
識別してみたが...
一枚づつ識別しようとしたら、また
AssertionError: batch_size must be divisible by strategy.num_towers (1 vs 8)
のエラーが...
あぁ、めんどくさい(爆)
感想
簡単に動かせるかと思ったら、結構ハマるポイントがありました。
モデルによってはもっとありそうな感じです。
もう少しいじってみたいと思います。