研究室の輪読で「PythonとKerasによるディープラーニング」という本を読んでた時の備忘録というか、なんというか。
1系と2系の違い
色々と基礎的な部分からしっかり書いてあって良書なのだが、中身のプログラムは Tensorflow 1系である。
現在Tensorflowは2系を使う場合がほとんどだと思う。
1系と2系の大きな違いは、1系ではGraph Mode 、2系ではEager Modeがデフォルトになっているという点。
Eager Modeとはいわゆる Define by Run のモードのことであり、ネットワークを構築しながらデータを流し込んでいくモードのこと。インタプリタみたいなイメージ。
その逆、というか、もう一方が Define and Run であり、これは Tensorflow では Graph Mode となってる。こちらは、ネットワークを全て構築したのちにコンパイルしてデータを流し込むというモード。
元々、Define by Run といえば、Chainer とか PyTorch とかだった。
Define and Run では一旦全ての計算グラフを書き出してコンパイルするのに対して、Define by Run ではコンパイルを行わず逐次的に計算グラフを構築していくため、Define by Run の方が自由度が高いという利点がある。
もちろん Define and Run の方が速度的には有利なのだが、自由度の高い方が色々と便利でウケがいいのか、Tensorflowも 2 系からは Define by Run がデフォルトとなったのだ。
勾配計算のやり方(半分未解決)
1系と2系のこの差によって、勾配計算のやり方が変わってくるみたい。
Graph Modeがデフォルトの 1系 の以下のような勾配計算をそのまま 2 系に移植すると、、
from tensorflow.keras import backend as K
#省略
grads = K.gradients(african_elephant_output, last_conv_layer.output)[0]
「tf.gradients is not supported when eager execution is enabled. Use tf.GradientTape instead.」というエラーが出てくる。
要するに 2 系のEager Mode では、tf.gradients はサポートしてないということみたい。tf.GradientTape を変わりに使えと。
しかし、この tf.GradientTape がいまいち理解できない。。
結局以下のように、Graph Modeに切り替えるというやり方で勾配計算を行った。
glaph_mode = tf.Graph()
with glaph_mode.as_default():
grads = K.gradients(african_elephant_output, last_conv_layer.output)[0]
これで一応できるけど、Eager Modeのままではどうやってやるんだろうか。。
GradientTape をしっかり理解しないといけなさそう。