卷积与反卷积

来源:互联网 发布:程序员美剧 编辑:程序博客网 时间:2024/05/18 01:42

以下属于个人见解和总结,不妥之处还望指教。
[Toc]

卷积(Convolution)

卷积定义:图像中的卷积,可以理解为在空间位置上,进行加权叠加。
原图
——[图片来源]

假设输入特征层feature map的大小为[batch,width,height,channel], 卷积核大小[k,k,inputn,outputn],步长为[1,s,s,1], padding大小为p, 则通过卷积后的图像大小,计算如下:

wnew=w+2pks+1
hnew=h+2pks+1

注:

  • inputn=channel, 卷积核深度等于输入特征层的深度
  • 卷积后的特征层的深度等于outputn,及卷积核的个数

计算机在做卷积操作的时候,实际上,是转化为矩阵乘法操作,假设输入矩阵为X,卷积核为C, 卷积后的矩阵为Y, 则

Y=CX

例如:其中假设X的大小为4x4, 卷积核大小为3x3, 没有padding和stride, 则输出为2x2的矩阵,其中X可以展开为一个16维向量, C可以写成稀疏矩阵, 如下:
X=x00x10x20x30x01x11x21x31x02x12x22xx2x03x13x23x33

转化为16维向量,
X=(x00x01x02x03x10x11x12x13x20x21x22x23x30x31xx2x33)

卷积核C,如下
C=c00c10c20c01c11c21c02c12c22

转化成稀疏矩阵为:
C=c00000c01c0000c02c01000c0200c100c000c11c10c01c00c12c11c02c010c120c02c200c100c21c20c11c10c22c21c12c110c220c1200c20000c21c2000c22c21000c22

从而,通过矩阵运算CX可以生成一个4维向量,再转化为一个2x2的矩阵。

进一步,我们可以理解到,神经网络在做inference正向传播的时候,利用上述公式CX进行计算,在做反卷积时候,利用公式CTY进行计算。

反卷积

这里写图片描述

假设输入特征层feature的大小为(w,h), 卷积核大小(kk), 步长为s, padding大小为p, 则通过反卷积后feature map的大小,计算公式如下:

wnew=w1s+k2p
hnew=h1s+k2p

例如,一张大小为5x5的图像, 经过(3x3)卷积核,
假设一:padding为1, stride为2,则经过卷积后图像的大小为

w=5+2132+1=3
h=5+2132=3

而,反卷积后的图像大小为
wnew=312+321=5
hnew=312+321=5

等于输入图像的大小。

假设二:stride为3,padding为1, 则经过卷积后图像的大小为

w=5+2133+1=2
h=5+2133+1=2

而在经过反卷积后图像变为
wnew=213+321=4
hnew=213+321=4

假设三:stride为2, padding为2,则经过卷积后图像大小为:

w=5+2232+1=4
h=5+2232+1=4

而在经过反卷积后图像变为
wnew=412+322=5
hnew=412+322=5

假设四:stride为3,padding为2, 则经过卷积后图像大小为:

w=5+2233+1=3
h=5+2233+1=3

而在经过反卷积后图像变为
wnew=313+322=5
hnew=313+322=5

注:当w+2pks不能整除的时候,反卷积得到的图像尺寸,会存在1个像素的差。

tensorflow中的卷积和反卷积操作

import numpy as npimport tensorflow as tfx1 = tf.constant(1.0, dtype=tf.float32, shape=[1,4,4,1])kernel = tf.constant(1.0, dtype=tf.float32, shape=[3,3,1,1])y1 = tf.nn.conv2d(x1, kernel, strides=[1,1,1,1], padding='SAME')y1_t = tf.nn.conv2d_transpose(y1, kernel, output_shape=[1,4,4,1], strides=[1,1,1,1], padding='SAME')sess = tf.Session()print('x1 = {}'.format(np.squeeze(sess.run(x1))))print('kernel = {}'.format(np.squeeze(sess.run(kernel))))print('y1 = {}'.format(np.squeeze(sess.run(y1))))print('y1_t = {}'.format(np.squeeze(sess.run(y1_t))))
输出结果为:x1 = [[ 1.  1.  1.  1.] [ 1.  1.  1.  1.] [ 1.  1.  1.  1.] [ 1.  1.  1.  1.]]kernel = [[ 1.  1.  1.] [ 1.  1.  1.] [ 1.  1.  1.]]y1 = [[ 4.  6.  6.  4.] [ 6.  9.  9.  6.] [ 6.  9.  9.  6.] [ 4.  6.  6.  4.]]y1_t = [[ 25.  40.  40.  25.] [ 40.  64.  64.  40.] [ 40.  64.  64.  40.] [ 25.  40.  40.  25.]]
原创粉丝点击