メモリの少ないグラフィックボードで MNIST を動かす
先日、GeForce GT 730 を乗せた自作 PC の TensorFlow 周りの環境を整えました。
しかし、予想通り、環境構築に満足してしまって、肝心の TensorFlow をゴリゴリ書いたりはしてませんでした。
ところが、思いがけずインターンに参加させてもらえることになり、そこで TensorFlow を書く機会があったので、この環境を使ってみました。
その際に、低メモリグラボで TensorFlow を動かしていった方法を記録します。
ResourceExhaustedError
TensorFlow のチュートリアルの Deep MNIST for Experts を実行すると、ResourceExhaustedError
が発生します。
これは、
accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0})
この行が原因で起こります。
feed_dict
の x
に与えている mnist.test.images
が、float32
型で 10000*28*28*32
個の要素を持つので、ざっと見積もっても 250880000*4
byte で、約 1 GB あるためです。
これでは、GT 730 のメモリサイズ 1 GB に、まず乗せられません。
また、グラボのメモリ上に先に乗せたモデルがすでに 812 MB 程度のメモリを占領しています。
sess.run(init)
をして、nvidia-smi を実行すると、実際にはトータルメモリサイズが 979 MiB (= 1026 MB) で、使用中のメモリが 802 MiB (= 840 MB) となっており、空きメモリが十分不足していることがわかります。
accuracy の feed_dict を分割
これを解消するためには、accuracy
に与える feed_dict
を分割して、得られた値をうまく整えてやれば良いと考えました。
まず、分割しない accuracy
の計算は
correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
です。ここで行われていることは、1 行目で
- モデルの出力と正解ラベルが同じであれば True に
- 入力データ (
feed_dict: x
) に対して行われるので戻り値は boolean の配列
2 行目で
- これを
tf.float32
にキャスト (True
なら 1、False
なら 0 に) tf.reduce_mean
で配列の平均値を取っている
なので、1 行目の操作は、個々のデータに対して行っても何ら変化はなく、2 行目の reduce_mean を分割して行えば良いわけです。
やってるのは、ただ平均を取ることなので、以下のよう for で総和してテストデータの数で割りました。
num_test = len(mnist.test.labels) sum_accuracy = 0 for i in range(0, num_test, 50): sum_accuracy = sum_accuracy + accuracy.eval(feed_dict={x: mnist.test.images[i:i+50], y_: mnist.test.labels[i:i+50], keep_prob: 1.0}) print("test accuracy:", sum/(num_test/50))
結果として、エラーは吐かなくなり、得られる値も CPU だけで計算した場合と大きな差異がないことから、正しいと考えられます。
もちろん、この実装は遅くなります。しかし、動かないのと遅いのとでは、天と地ほどの差があるので、良しとします。
実際、遅くなったといっても、MacBook で動かすのに比べると、4 倍以上早くなることを確認しました。
- MacBook Pro の場合
- GT 730 を積んだ自作 PC の場合
他にも、numpy にある reduce_mean を使う方法も考えられると思います。上記のコードは、最も単純な実装と言えるでしょう。
また、むやみやたらに for を使ってコードを読みにくくするよりは、GPU と CPU の使い分けをするようなコードを書いた方が、TensorFlow らしいコードの書き方のような気もします。
まとめ
以上で、メモリの少ないグラフィックボードで TensorFlow のチュートリアルの Deep MNIST for Experts を動かすことができました。
その代わり、少し速度を犠牲にする結果となりましたが、それでもノート PC で実行するよりは十分早く、期待する結果が得られました。
今後は、もっと良い書き方も模索してきたいと思います。