仙豆のレシピ

ちょっとしたことでも書いていく姿勢で

TensorFlowでjacobianを計算する

https://github.com/tensorflow/tensorflow/issues/675

で議論されていたけど実際の方法は載ってなかったのでメモ。
(まー見りゃわかるという話なんだろうけど初学者の自分はけっこう考えたので)

問題

入力

 x_1,x_2...x_n

に対してニューラルネットワークの出力層のk番目のニューロンの値を

 f_k(x_1,x_2...x_n)

としたときに、ヤコビアン

 \displaystyle
\begin{equation}
J_f=
\begin{pmatrix}
\frac{\partial f_1}{\partial x_1} & \cdots & \frac{\partial f_1}{\partial x_n} \\
\vdots & \ddots & \vdots \\
\frac{\partial f_m}{\partial x_1} & \cdots & \frac{\partial f_m}{\partial x_n}
\end{pmatrix}
\end{equation}

を計算する。( ヤコビ行列 - Wikipedia )

例としてMNIST用のプログラムを考える。このとき上の式のm=10、n=28x28=784
構造はTensorFlow Mechanics 101にある感じで

logits=inference(images_placeholder,keep_prob)

のように結果を得られるとする。

このとき

jacobian=[]
for i in range(10):
    calc_grad=tf.gradients(tf.slice(logits,[0,i],[1,1]),images_placeholder)
    jacobian.append(sess.run(calc_grad,feed_dict={
        images_placehoder:[image],
        keep_prob:1.0
    })[0][0])

のようにすればヤコビアンが得られる。

やっていることは単純で、logitsに各ニューロンの推論結果が入っているのでそれをtf.sliceで切り出して一つずつ微分している。
githubでの議論にもあったように、スライスしてやらないとyについての和が返ってきてしまう。

勉強し始めなので理解が正しいか不安だけど、いちおう思ったような結果は得られているっぽいのでとりあえず。

参考

TensorFlowでゆるゆりの制作会社を識別する - kivantium活動日記