TensorFlow

conv2d_transpose の動作を確認する

背景

通常の畳込み(convolution)は、入力された画像の解像度を下げるが、逆にこれを上げるものとして、transposed convolution(以前は deconvolution とも呼ばれていた)がある。TensorFlow だと tf.layers.conv2d_transpose 等でこれを行うが、動作の詳細がわからずもやもやしていた。

最もわかりやすい解説

【保存版】chainerのconvolutionとdeconvolution周りを理解する

これが一番わかりやすかった。具体例をあげて詳しく書いてあるので、もうこれだけ見てもらえれば十分。はい解散。

…というのもちょっと寂しいので、私は TensorFlow で検証してみた。わかりやすくするため、数値は思い切り単純なものにしてある。各自数字を変えて試してみるとよいかもしれない。もし間違いがあればご連絡ください。

検証コード

import tensorflow as tf

with tf.Session() as sess:
    inputs = tf.ones([1, 3, 3, 1])
    outputs = tf.layers.conv2d_transpose(inputs, 1, [2, 2], 
        strides=[1, 2], padding='valid',
        kernel_initializer=tf.constant_initializer([[1, 0], [0, 0]]))
    sess.run(tf.global_variables_initializer())
    value = sess.run(outputs)
    print(value)

実行結果

[[[[1.]
   [0.]
   [1.]
   [0.]
   [1.]
   [0.]]

  [[1.]
   [0.]
   [1.]
   [0.]
   [1.]
   [0.]]

  [[1.]
   [0.]
   [1.]
   [0.]
   [1.]
   [0.]]

  [[0.]
   [0.]
   [0.]
   [0.]
   [0.]
   [0.]]]]

解説

確かに【保存版】chainerのconvolutionとdeconvolution周りを理解するの通りの動作になっている。

もともとの inputs が、

\begin{bmatrix}
1 & 1 & 1 \\
1 & 1 & 1 \\
1 & 1 & 1 \\
\end{bmatrix}

これに対して、

outputs = tf.layers.conv2d_transpose(inputs, 1, [2, 2], 
        strides=[1, 2], padding='valid',
        kernel_initializer=tf.constant_initializer([[1, 0], [0, 0]]))

で指定される transposed convolution 操作を行う。

inputs の周辺には、まず幅1でゼロパディングが施され、その上 strides=[1, 2] なので、幅方向に大きさ2のストライドを掛ける1。すると以下のように。

\begin{bmatrix}
0 & 0 & 0 & 0 & 0 & 0 & 0 \\
0 & 1 & 0 & 1 & 0 & 1 & 0 \\
0 & 1 & 0 & 1 & 0 & 1 & 0 \\
0 & 1 & 0 & 1 & 0 & 1 & 0 \\
0 & 0 & 0 & 0 & 0 & 0 & 0 \\
\end{bmatrix}
\tag{1}

kernel_initializer=tf.constant_initializer([[1, 0], [0, 0]])) で指定される行列は以下のもの。

\begin{bmatrix}
1 & 0 \\
0 & 0 \\
\end{bmatrix}

これについて、2つの対角線でそれぞれひっくり返した(transpose2)行列は以下の通り。

\begin{bmatrix}
0 & 0 \\
0 & 1 \\
\end{bmatrix}
\tag{2}

結局、行列(1)に対して、行列(2)で通常の convolution を掛ければよい。

答えは、

\begin{bmatrix}
0 & 1 & 0 & 1 & 0 & 1 \\
0 & 1 & 0 & 1 & 0 & 1 \\
0 & 1 & 0 & 1 & 0 & 1 \\
0 & 0 & 0 & 0 & 0 & 0 \\
\end{bmatrix}

となって上のプログラムの実行結果と一致する。


  1. これは普通の convolution で言うところのストライドとは異なる。が、transposed convolution ではこれをストライドと呼ぶらしい。 

  2. Transposed matrix といえば、「転置行列」。ただ、これは転置行列とは異なり、右下→左上の対角線に関してもひっくり返している。数学的には、なんと呼ばれる行列なのだろうか?