在FCN,U-net,GAN中都有使用转置卷积(Transposed Convolution)的过程,转置卷积不能单纯地理解为逆卷积(deconvolution)。
在CNN正向卷积过程是一个将图片变小的过程,转置卷积使得图片逐渐变大,直至与原图一样大。
如何理解转置卷积呢,可以先从将卷积的计算转换成矩阵的计算来开始。
好了,到这儿大致了解了转置卷积是什么,能干什么了。也就是由卷积后得到的小图经过转置卷积可以得到大一点的图(这比喻不太恰当,意会就好)。
下面是tensorflow中关于转置卷积的API
这儿再附上tf中关于padding参数的用法:
好了,最后实战一下,怎么用tf中的转置卷积:
import tensorflow as tf
# 正向卷积
# 输入尺度 [batch, height, width, in_channels]
inputx=tf.random_normal([100,255,255,3],dtype=tf.float32)
# kernel [height, width, in_channels, output_channels]
w=tf.random_normal(shape=[5,5,3,10],dtype=tf.float32)
# 卷积输出 (100, 126, 126, 10),注意:这儿用的是VALID
outputy=tf.nn.conv2d(input=inputx,filter=w,strides=[1,2,2,1],padding='VALID')
用卷积计算输出很容易,但是如果我现在想根据输出图片的大小,怎么设置卷积核的尺寸和strides呢?先贴代码
# 转置卷积
# 输入的value [batch, height, width, in_channels]
value=tf.random_normal(shape=[100,126,126,10])
# filter [height, width, output_channels, in_channels]
w=tf.random_normal(shape=[4,4,3,10])
# 转置卷积得出的结果
result=tf.nn.conv2d_transpose(value=value,filter=w,output_shape=[100,255,255,3],strides=[1,2,2,1],padding='VALID')
with tf.Session() as sess:
tf.global_variables_initializer().run()
# sess.run(outputy)
# print(outputy.shape)
sess.run(result)
print(result.shape)
其实有个很简单的思路,就是像计算卷积那样计算转置卷积。这句话是这么个意思,比如代码中我要得到255*255*3的一张图片(也就是经过转置卷积放大的图片),第一步我们要确定我们用什么padding方式,不同的padding方式确定不同的计算模式。代码中我们使用VALID模式,那么根据转置卷积的输入value是126*126*10的图片,根据计算公式
ceil((255−kernel+1)/stride)=126,其中ceil是向上取整
设kernel等于4,stride算出来正好是2。
如果设置padding是SAME呢,据公式
ceil(255/stride)=126
,窝草,这是算不出符合的整数stride的,这说明不能将126*126转置卷积到255*255,据推算在stride为2时候,要输出255*255的只能输入128*128的value到转置卷积里。
参考链接:http://blog.csdn.net/u013250416/article/details/78247818,
https://www.tensorflow.org/api_docs/python/tf/nn/conv2d_transpose,
https://www.tensorflow.org/api_docs/python/tf/nn/convolution,
《a guide to convolution arithmetic for deep learning》