1. 程式人生 > >1. tf.nn.conv2d_transpose解決output_shape問題,解決需要固定輸出尺寸的問題

1. tf.nn.conv2d_transpose解決output_shape問題,解決需要固定輸出尺寸的問題

tensorflow 使用反捲積的時候有兩種方式,
一種使用tf.layers

tf.layers.conv2d_transpose(inputs, filters, kernel_size, strides=(1, 1), padding='valid', data_format='channels_last', activation=None, use_bias=True, kernel_initializer=None, bias_initializer=<tensorflow.python.ops.init_ops.Zeros object at 0x000000000BC10EF0>, kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None, trainable=True, name=None, reuse=None)

另外一種是使用tf.nn

tf.nn.conv2d_transpose(value, filter, output_shape, strides, padding='SAME', data_format='NHWC', name=None)

tf.layers是tf.nn上進一步的封裝,使用更為簡單。但是tf.layers.conv2d_transpose與tf.nn.conv2d_transpose相比,前者不需要指定輸出的尺寸,而後者是需要指定的。但是相對而言,個人認為tf.nn.conv2d_transpose較為靈活。例如,當只是使用tensorflow實現卷積操作,而卷積核固定為常數不需要更新時,tf.nn.conv2d_transpose則不能適用。
但是tf.nn.conv2d_transpose存在的問題是需要指定輸出的尺寸,我們知道tensorflow是一種靜態圖的方式。在網路建立時指定輸出尺寸,例如bacth_size等,會導致只能處理固定尺寸的輸入。
對於這種問題,有兩種解決方式:

tf.layers.conv2d_transpose實現反捲積

tf.layers.conv2d_transpose實現反捲積時,無需指定輸出尺寸,根據有靈活性。但是前提是,你的需求可以轉換為tf.layers.conv2d_transpose的形式來實現。例如,只是在網路中新增一個需要更新引數的反捲積層,實現網路搭建的目的,那麼使用tf.layers.conv2d_transpose實現反捲積就夠了。

tf.nn.conv2d_transpose實現反捲積

這個問題在github https://github.com/tensorflow/tensorflow/issues/833#issuecomment-278016198

討論過。為了不用指定output_shape,解決的方式是使用輸入變數的尺寸和卷積核的尺寸計算出輸出的卷積核的尺寸。畢竟一旦輸入確定,卷積核的尺寸確定,輸出的尺寸是可以被計算的。計算方式如下:

o = s ( i 1 ) + k 2 p o&#x27; = s\left( {i - 1} \right) + k - 2p

其中, o o&#x27; 為輸出尺寸 , i i 為輸入尺寸, k k 為卷積核尺寸, p p 為padding尺寸。

但是,面臨的關鍵的問題是,儘管可以通過輸入計算出來,但是,在建立Graph的時候,輸出的尺寸通常為None。因此關鍵在於如何獲取輸入的尺寸,github上給出了答案,我這裡總結為(為了更靈活,這裡使用外部padding)

inputs = tf.pad(inputs, tf.constant([[0, 0], [padding_size, padding_size], [padding_size, padding_size ], [0, 0]]), mode='reflect'))
out_size = stride * (tf.shape(inputs)[1] - 1) + kernel_size - 2*padding_size
outputs = tf.nn.con2d_transpose(inputs, kernel, output_shape=[tf.shape(inputs)[0], out_size, out_size, tf.shape(inputs)[3]])

這樣就再也不用擔心使用tf.nn.con2d_transpose時沒有辦法指定output_shape了。
如有錯誤,請大家不寧賜教。