谈谈关于转置卷积的理解

转载转置卷积的介绍,很详细且通俗易懂: https://blog.csdn.net/zju_huster/article/details/98616153

谈谈关于转置卷积的理解
为什么是转置卷积
卷积操作
反过来操作
卷积矩阵
转置卷积矩阵
总结

最近看到反卷积的概念,开始不太明白,然后查了些资料,总算搞明白了,顺便在此对结合自己的理解做一记录。
当我们使用神经网络生成网络图片时,经常需要将一些低分辨率的图片转换为高分辨率的图片,对于这种上采样操作,除了一些传统的插值方法,神经网络中通常采用**转置卷积(反卷积)**来实现。

为什么是转置卷积
转置卷积(Transposed Convolution)常常在一些文献中也称之为反卷积(Deconvolution)和部分跨越卷积(Fractionally-strided Convolution)。
如果想要我们的网络可以学习到最好地上采样的方法,可以采用转置卷积。这个方法不会使用预先定义的插值方法,它具有可以学习的参数。理解转置卷积这个概念是很重要的,因为它在若干重要的文献中都有所应用,如:

在DCGAN中的生成器将会用随机值转变为一个全尺寸的图片,这个时候就需要用到转置卷积。
在语义分割中,会使用卷积层在编码器中进行特征提取,然后在解码层中进行恢复为原先的尺寸,这样才可以对原来的图像中每个像素都进行分类。这个过程同样使用到了转置卷积。
卷积操作
首先我们回顾下卷积操作是如何工作的,并且用一个小例子来直观感受下。假设我们有一个4*4的矩阵,我们将在这个矩阵上应用3 * 3的卷积核,并且不添加任何填充(padding),步进参数(stride)设置为1,就像下图所示,输出为一个2 * 2的矩阵。

这个卷积操作在输入矩阵和卷积核中,对每个元素的乘积进行相加。因为我们没有任何填充和使用步长为1,所以得到2 * 2的矩阵。

这种卷积操作使得输入和输出之间存在着位置上的对应关系,举例来说,输入矩阵的左上方值会影响到输出矩阵的左上方的值。更具体而言,3 * 3的卷积核是用来连接输入矩阵的9个值,并且将其转变为输出矩阵的一个值。一个卷积操作是多对一的映射关系。

反过来操作
现在,我们假设要反过来操作。即输入矩阵的一个值对应输出矩阵的9个值,这是一个一对多的映射关系。这个就像是卷积操作的反操作,其核心就是使用转置卷积。举个例子,我们对一个2 * 2的矩阵进行上采样为4 * 4的矩阵。这个操作将会维护一个1对应9的映射关系。

因此就结论而言,卷积操作是多对一,而转置卷积操作是一对多,如下图所示。

但是具体如何操作呢?为便于接下来的讨论,我们需要定义一个卷积矩阵(convolution matrix)和相应的转置卷积矩阵(transpose convolution matrix)。

卷积矩阵
我们可以将一个卷积操作通过重新排列卷积核的方式表示成矩阵乘法。下图即为原式的卷积核:

我们对这个3 * 3的卷积核进行重新排列,得到了下面这个4 * 16的卷积矩阵:

这个便是卷积矩阵了,这个矩阵的每一行都定义了一个卷积操作。下图将会更加直观地告诉你这个重新排列是怎么进行的。每一个卷积矩阵的行都是通过重新排列卷积核的元素,并添加0补(zero padding)充得来的。
为了将卷积操作表示为卷积矩阵和输入矩阵的向量乘法,我们将输入矩阵4 * 4摊平(flatten)为一个列向量,形状为16 * 1,如下图所示

我们可以将这个4 * 16的卷积矩阵和1 * 16的输入列向量进行矩阵乘法,这样我们就得到了输出列向量。

这个输出的4 * 1的矩阵可以重塑为一个2 * 2的矩阵,而这个矩阵正是和我们一开始通过传统的卷积操作得到的一模一样。

由上可知,关键点在于这个卷积矩阵,你可以冲16(4 * 4)到4(2 * 2)是因为这个卷积矩阵尺寸是4 * 16的,所以,若果有一个16 * 4的矩阵呢,你就可以从4(2 * 2)到16(4 * 4)了,这不就是一个上采样操作吗?

转置卷积矩阵
我们想要从4到16,因此我们使用了一个16 * 4的矩阵,但是还有一件事情需要注意,我们是想要维护一个1到9的映射关系。
假设我们转置这个卷积矩阵C(4 * 16)变为C T C^TC
T
(16 * 4)。我们可以对C T C^TC
T
和列向量(4 * 1)进行矩阵乘法,从而生成一个16 * 1的输出矩阵。这个转置矩阵正是将一个元素映射到了9个元素。

这个输出可以reshape为(4 * 4)的矩阵:

    我们只是对小矩阵(2 * 2)进行上采样为一个更大尺寸的矩阵(4 * 4)。这个转置卷积矩阵维护了一个1个元素到9个元素的映射关系,因为这个关系正表现在了其转置卷积元素上。

需要注意的是:这里的转置卷积矩阵的参数,不一定是从原始的卷积矩阵中简单转置得到的,转置这个操作只是描述了转置卷积矩阵的形状而已,其内部的参数可以由随机初始化而来。

总结
转置卷积操作构建了和普通的卷积操作一样的连接关系,只不过方向相反而已。我们可以用它进行上采样。另外,这个转置卷积矩阵的参数是可以学习的,因此我们不需要一些人为预先定义的方法。即使它被称为转置卷积,它并不意味着我们将一些现存的卷积矩阵简单转置并使用其转之后的值。

    从本质上来说,转置卷积并不是一个卷积,但是我们可以将其看成卷积,并且当成卷积去使用。我 们 通 过 在 输 入 矩 阵 中 的 元 素 之 间 插 入 0 进 行 补 充 , 从 而 实 现 尺 寸 上 采 样 , 然 后 通 过 普 通 的 卷 积 操 作 就 可 以 产 生 和 转 置 卷 积 相 同 的 效 果 了 \color{red}{我们通过在输入矩阵中的元素之间插入0进行补充,从而实现尺寸上采样,然后通过普通的卷积操作就可以产生和转置卷积相同的效果了}我们通过在输入矩阵中的元素之间插入0进行补充,从而实现尺寸上采样,然后通过普通的卷积操作就可以产生和转置卷积相同的效果了。你在一些文章中将会发现好多都是这样解释转置卷积的,但是这个转置卷积需要通过插入0进行上采样,因此是比较低效的。

注意 : 转置卷积会导致生成图像中出现棋盘效应(checkerboard artifacts),这篇文章《Deconvolution and Checkerboard Artifacts》对应中文推荐了一种上采样的操作(也就是插值操作),这个操作接在一个卷积操作后面可以减少这种现象。如果你的主要目的是生成尽可能少棋盘效应的图像,那么这篇文章就值得你去阅读。

你可能感兴趣的:(deep,learning,深度学习,神经网络,卷积)