要注意转置卷积有点类似卷积的反向传播,并不是等价于反向传播。因为转置卷积只是恢复了原图的size而没有恢复其值。
卷积
如下上图所示输入是5∗55*55∗5的,卷积核是3∗33*33∗3,然后pading是0,stride是1。卷积过程如第二幅图所示。根据计算公式(W−F+2P)/S+1(W-F+2P)/S+1(W−F+2P)/S+1,有(5−3+2∗0)/1+1(5-3+2*0)/1+1(5−3+2∗0)/1+1可以看到卷积之后结果是3∗33*33∗3的feature map。
下面我们使用矩阵来表示这个过程,我们首先将image矩阵和feature map矩阵写成列向量形式:
[1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,1,1,0,0,1,1,0,0,1]T\begin{bmatrix} 1 , 1, 1, 0,0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0 ,1 ,1, 0, 0 ,1 \end{bmatrix}^T[1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,1,1,0,0,1,1,0,0,1]T
输入的size是(26,1)表示为X,多出来的1是用于bias计算用的。
[4,3,4,2,4,3,2,3,4]T \begin{bmatrix} 4, 3,4, 2, 4, 3, 2, 3, 4 \end{bmatrix}^T [4,3,4,2,4,3,2,3,4]T
feature map的size是(9,1)表示为Y
由于我们通过公式(W−F+2P)/S+1(W-F+2P)/S+1(W−F+2P)/S+1,已经知道输出Feature map的size为(9,1),所以我们将卷积核展开成size为(9,26)的稀疏矩阵:
[101000100010100000000000000101000100010100000000000000101000100010100000000000000001010001000101000000000000001010001000101000000000000001010001000101000000000000000010100010001010000000000000010100010001010000000000000010100010001010]\begin{bmatrix} 1 &0 &1 & 0 & 0 &0 &1 & 0 &0 &0 &1 &0 &1 & 0 & 0 &0 & 0& 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 &0 \\ 0& 1 &0 &1 & 0 & 0 &0 &1 & 0 &0 &0 &1 &0 &1 & 0 & 0 &0 & 0& 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0&0& 1 &0 &1 & 0 & 0 &0 &1 & 0 &0 &0 &1 &0 &1 & 0 & 0 &0 & 0& 0 & 0 & 0 & 0 & 0 & 0 &0 \\ 0&0&0&0&0&1 &0 &1 & 0 & 0 &0 &1 & 0 &0 &0 &1 &0 &1 & 0 & 0 &0 & 0& 0 & 0 & 0 & 0 \\ 0&0&0&0&0&0&1 &0 &1 & 0 & 0 &0 &1 & 0 &0 &0 &1 &0 &1 & 0 & 0 &0 & 0& 0 & 0 & 0 \\ 0&0&0&0&0&0&0&1 &0 &1 & 0 & 0 &0 &1 & 0 &0 &0 &1 &0 &1 & 0 & 0 &0 & 0& 0 & 0\\ 0&0&0&0&0&0&0&0&0&0&1 &0 &1 & 0 & 0 &0 &1 & 0 &0 &0 &1 &0 &1 & 0 & 0 &0 \\ 0&0&0&0&0&0&0&0&0&0&0&1 &0 &1 & 0 & 0 &0 &1 & 0 &0 &0 &1 &0 &1 & 0 & 0 \\ 0&0&0&0&0&0&0&0&0&0&0&0&1 &0 &1 & 0 & 0 &0 &1 & 0 &0 &0 &1 &0 &1 & 0 \end{bmatrix}⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡100000000010000000101000000010000000001000000000100000100010000010101000001010000000001000100000100010100010101010101010001010001000001000100000000010100000101010000010001000001000000000100000000010000000101000000010000000001000000000⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤
可以看见卷积核展成稀疏矩阵是有明显规律的。这个稀疏矩阵称为C。因此卷积的过程就可以表示为:
CX=YCX=YCX=Y
可以知道维度(9,26)的矩阵与维度为(26,1)的矩阵点乘得到维度为(9,1)的feature map。 那么对于转置卷积来说,其操作目的就是要使feature map还原到其原来的图像的size。所以用Y点乘C的转置刚好就回到图像的size:
CTY=XC^TY=XCTY=X
也就是维度(26,9)与维度(9,1)点乘结果刚好为(26,1),再去掉偏置项,就回到原图size。转置卷积的过程就是这样,只不过,只是还原其size,没有还原其值。这个在Gan中常用到,这是因为Gan需要把图还原到真实的size。
为甚说有点类似卷积的反向传播,这是因为卷积网络反向传播时,梯度会从feature map这边映射会原图,所以有点类似于反向传播,但是不等同。
这里我们使用Pytorch来举个栗子:
我们有一张图片是size为(280,280)的png,灰度图像,通道数为1,转为矩阵后size为(1,280,280)。我们先对其进行卷积,然后在进行转置卷积,看看效果:
import torch
from PIL import Image
import torch.nn as nn
import numpy as np
pic=Image.open('test1.png')
pic_array=np.asarray(pic)
print('pic_array.shape:',pic_array.shape)
pic_array_re=pic_array.reshape(1,1,280,280)
print('pic_array.shape_re:',pic_array_re.shape)
pic_tensor=torch.Tensor(pic_array_re)
print('pic_tensor.shape:',pic_tensor.shape)
Cov=nn.Conv2d(1,1,4,1,0) #(inchannels,out_channels,kernel_size,stride,padding)
pic_cov=Cov(pic_tensor)
print('pic_cov.shape:',pic_cov.shape)
Cov_tran=nn.ConvTranspose2d(1,1,4,1,0)
pic_cov_tran=Cov_tran(pic_cov)
print('pic_cov_tran.shape:',pic_cov_tran.shape)
输出结果为:
pic_array.shape: (280, 280)
pic_array.shape_re: (1, 1, 280, 280)
pic_tensor.shape: torch.Size([1, 1, 280, 280])
pic_cov.shape: torch.Size([1, 1, 277, 277])
pic_cov_tran.shape: torch.Size([1, 1, 280, 280])