轻松理解转置卷积(transposed convolution)或反卷积(deconvolution)「建议收藏」

轻松理解转置卷积(transposed convolution)或反卷积(deconvolution)「建议收藏」原文地址:Up-samplingwithTransposedConvolution本文暂时没有插入图像,以后修订在CNN中,转置卷积是一种上采样(up-sampling)的方法.如果你对转置卷积感到困惑,那么就来读读这篇文章吧.本文的notebook代码在Github.上采样的需要在我们使用神经网络的过程中,我们经常需要上采样(up-sampling)来提高低…

大家好,又见面了,我是你们的朋友全栈君。

本译文很大程度上保留了原文原貌,并添加了细节便于理解(各种指代)。

在CNN中,转置卷积是一种上采样(up-sampling)的常见方法.如果你不清楚转置卷积是怎么操作的,那么就来读读这篇文章吧.

本文的notebook代码在Github.

上采样的需要

在我们使用神经网络的过程中,我们经常需要上采样(up-sampling)来提高低分辨率图片的分辨率.

https://cdn-images-1.medium.com/max/2000/1*u5hMSBG7fZ7uo85ckmLiUw.png

上采样有诸多方法,举例如下.

  • 最近邻插值(Nearest neighbor interpolation)
  • 双线性插值(Bi-linear interpolation)
  • 双立方插值(Bi-cubic interpolation)

但是, 上述的方法都需要插值操作, 而这些插值的操作都充满了人为设计和特征工程的气息, 而且也没有网络进行学习的余地.

为何需要转置卷积

如果我们想要网络去学出一种最优的上采样方法,我们可以使用转置卷积.它与基于插值的方法不同,它有可以学习的参数.

若是想了解转置卷积有啥用, 可以看看它是如何运用于在一些有名的论文和项目中的.

  • DCGAN的生成器(generator)接受一些随机采样的值作为输入来生成出完整的图片. 它的语义分割(semantic segmentation)就使用了卷积层来提取编码器(encoder)中的特征, 接着,它把原图存储在解码器(decoder)中以确定原图中的每个像素的类别归属.

  • FYI.

转置卷积也被称作: “分数步长卷积(Fractionally-strided convolution)“和”反卷积(Deconvolution)”.
我们在这篇文章里面只使用转置卷积这个名字.其他文章可能会用到其他名字,你只需要知道这些名字指的都是转置卷积.

卷积是如何操作的

我们先通过一个简单的例子来看看卷积是怎么操作的.

假设我们有一个 4 × 4 4\times4 4×4的input矩阵, 并对它使用核(kernel)为3×3,没有填充(padding),步长(stride)为1的卷积操作. 结果是一个 2 × 2 2\times2 2×2的矩阵,如下图所示.

在这里插入图片描述

译者注: stride,kernel,padding等词以下记为英文.

卷积操作的本质其实就是在input矩阵和kernel矩阵之间做逐元素(element-wise)的乘法然后求和. 因为我们的stride为1,不使用padding,所以我们只能在4个位置上进行操作.

在这里插入图片描述

要点:卷积操作其实就是input值和output值的位置性关系(positional connectivity).

例如,在input矩阵的左上角的值会影响output矩阵的左上角的值.

更进一步, 3 × 3 3\times3 3×3的kernel建立了input矩阵中的9个值和output矩阵中的1个值的关系.

“卷积操作建立了多对一的关系”. 在阅读下文时,请读者务必时刻牢记这个概念.

卷积的逆向操作

现在,考虑一下我们如何换一个计算方向. 也就是说,我们想要建立在一个矩阵中的1个值和另外一个矩阵中的9个值的关系.这就是在进行卷积的逆向操作,这就是转置卷积的核心思想.

(译者注:从信息论的角度看,卷积是不可逆的.所以这里说的并不是从output矩阵和kernel矩阵计算出原始的input矩阵.而是计算出一个保持了位置性关系的矩阵.)

在这里插入图片描述

但是,我们如何进行这种逆向操作呢?

为了讨论这种操作,我们先要定义一下卷积矩阵和卷积矩阵的转置.

卷积矩阵

我们可以将卷积操作写成一个矩阵. 其实这就是重新排列一下kernel矩阵, 使得我们通过一次矩阵乘法就能计算出卷积操作后的矩阵.

在这里插入图片描述

我们将 3 × 3 3\times3 3×3的kernel重排为 4 × 16 4\times16 4×16的矩阵,如下:

在这里插入图片描述

这就是卷积矩阵. 每一行都定义了一次卷积操作. 如果你还看不透这一点, 可以看看下面的图. 卷积矩阵的每一行都相当于经过了重排的kernel矩阵,只是在不同的位置上有zero padding罢了.

在这里插入图片描述

为了实现矩阵乘法,我们需要将尺寸为 4 × 4 4\times4 4×4的input矩阵压扁(flatten)成一个尺寸为 16 × 1 16\times1 16×1的列向量.

在这里插入图片描述

然后,我们对 4 × 16 4\times16 4×16的卷积矩阵和 16 × 1 16\times1 16×1的input矩阵(就是16维的列向量,只是看成一个矩阵)进行矩阵乘法.
在这里插入图片描述
尺寸为 4 × 1 4\times1 4×1的output矩阵可以重排为 2 × 2 2\times2 2×2的矩阵.这和我们之前通过滑动窗口计算得到的结果一致.

译者注:太棒辣!好神奇!

在这里插入图片描述

一句话,一个卷积矩阵其实就是kernel权重的重排,一个卷积操作可以被写成一个卷积矩阵.

即便这样又如何呢?

我想说的是: 使用这个卷积矩阵,你可以把16( 4 × 4 4\times4 4×4的矩阵)个值映射为4( 2 × 2 2\times2 2×2的矩阵)个值. 反过来做这个操作,你就可以把4( 2 × 2 2\times2 2×2的矩阵)个值映射为16( 4 × 4 4\times4 4×4的矩阵)辣.

蒙了?

继续读.

转置过后的卷积矩阵

我们的目的是把4 ( 2 × 2 2\times2 2×2的矩阵)个值映射为16 ( 4 × 4 4\times4 4×4的矩阵)个值. 但是,还要注意:我们需要维护1对9的关系.

假设我们转置一下卷积矩阵 C C C ( 4 × 16 4\times16 4×16),得到 C T C^T CT( 16 × 4 16\times4 16×4). 我们可以将 C T C^T CT ( 16 × 4 16\times4 16×4)和一个列向量( 4 × 1 4\times1 4×1)以矩阵乘法相乘,得到 16 × 1 16\times1 16×1的output矩阵.

转置之后的卷积矩阵就建立了1个值对9个值的关系.

在这里插入图片描述

output矩阵可以被重排为 4 × 4 4\times4 4×4的.
在这里插入图片描述
我们已经上采样了一个小矩阵( 2 × 2 2\times2 2×2),得到了一个大矩阵( 4 × 4 4\times4 4×4). 转置卷积依然维护着1对9的关系: 因为权重就是这么排的.

注意:用来进行转置卷积的权重矩阵不一定来自于原卷积矩阵. 重点是权重矩阵的形状和转置后的卷积矩阵相同.

总结

转置卷积和普通卷积有相同的本质: 建立了一些值之间的关系. 只不过,转置卷积所建立的这个关系与普通卷积所建立的关系,方向相反.

我们可以使用转置卷积来进行上采样. 并且,转置卷积中的权重是可以被学习的. 因此,我们没有必要搞什么插值方法来做上采样.

尽管它被称作转置卷积, 但是这并不意味着我们是拿一个已有的卷积矩阵的转置来作为权重矩阵的来进行转置卷积操作的. 和普通卷积相比,intput和output的关系被反向处理(转置卷积是1对多,而不是普通的多对1),才是转置卷积的本质.

正因如此,严格来说转置卷积其实并不算卷积.但是我们可以把input矩阵中的某些位置填上0并进行普通卷积来获得和转置卷积相同的output矩阵. 你可以发现有一大把文章说明如何使用这种方法实现转置卷积. 然而, 因为需要在卷积操作之前,往input中填上许多的0,这种方法其实有点效率问题.

警告:转置卷积会在生成的图像中造成棋盘效应(checkerboard artifacts).本文推荐在使用转置卷积进行上采样操作之后再过一个普通的卷积来减轻此类问题.如果你主要关心如何生成没有棋盘效应的图像,需要读一读paper.

References

[1] A guide to convolution arithmetic for deep learning
Vincent Dumoulin, Francesco Visin

https://arxiv.org/abs/1603.07285

[2] Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks
Alec Radford, Luke Metz, Soumith Chintala

https://arxiv.org/pdf/1511.06434v2.pdf

[3] Fully Convolutional Networks for Semantic Segmentation
Jonathan Long, Evan Shelhamer, Trevor Darrell

https://people.eecs.berkeley.edu/~jonlong/long_shelhamer_fcn.pdf

[4] Deconvolution and Checkerboard Artifacts
Augustus Odena, Vincent Dumoulin, Chris Olah

https://distill.pub/2016/deconv-checkerboard/

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/151913.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 双管显示

    双管显示

  • java怎么调用.asmx_Java调用Webservice(asmx)的例子

    java怎么调用.asmx_Java调用Webservice(asmx)的例子importjava.util.LinkedList;importjava.util.List;importjava.util.Map;importjava.util.Vector;importjavax.xml.namespace.QName;importorg.apache.axis.client.Call;importorg.apache.axis.client.Service…

  • 9.7 StringTokenizer类

    9.7 StringTokenizer类StringTokenizer类:解析字符串单词和split方法不同的是,StringTokenizer对象不使用正则表达式做分隔标记有时候要分析字符串并将字符串分解成可独立使用的单词,这些单词称为语言符号。对于字符串“Iamstudent”,如果把空格作为该字符串的标记,那么该字符串有三个单词(语言符号)。对于字符串“I,am,student”,如果把逗号作为该字符串的标…

  • 极客日报第 26 期:华大基因辟谣“基因编辑58个婴儿”;苹果发布头戴式耳机AirPods Max

    极客日报第 26 期:华大基因辟谣“基因编辑58个婴儿”;苹果发布头戴式耳机AirPods Max文章目录互联网快讯程序员专属Github每日精选CSDN社区优质博文精选互联网快讯1、我国一项物联网安全测试技术成为国际标准从WAPI产业联盟获悉,我国自主研发的一项物联网安全测试技术(TRAIS-PTEST)日前由国际标准化组织/国际电工委员会(ISO/IEC)发布成为国际标准。据介绍,该标准是TRAIS-P国际标准的测试标准,它规范了无线射频识别(RFID)安全密码套件一致性测试方法。标准发布后,将从技术到产品测试两个层面共同构成国际标准体系。(新华社)2、百度百科:日均搜索超4亿人次据.

  • 用new创建数组

    用new创建数组用new创建数组用new创建数组的优势由于new创建的对象是在运行时确立的,所以有着具体情况具体分析的优点,那么什么叫做具体情况具体分析呢?我觉得c++primerplus的一个例子十分贴切——比如你在度假,已经做好每天的参观计划,可突然有一天天气不好或你心情不好,此时你就不想参观了,如果此时是在编译状态,系统是不允许的,你必须按照计划去参观,但运行时状态,系统是允许的,此时你就可以呆在酒店尽情的玩耍了。用new创建数组也有此优点,即数组长度可以根据情况而定。比如说创建10个元素的数组,可以如下代

  • Java中static关键字的作用与用法「建议收藏」

    Java中static关键字的作用与用法「建议收藏」一、static关键字的特点:static是一个修饰符,用于修饰类的成员方法、类的成员变量,另外可以编写static代码块来优化程序性能。1.static修饰成员方法static修饰的方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都必须依赖具体的对象才能够被调用。…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号