机器学习19:反卷积算法

article/2025/9/19 23:07:01

机器学习19:反卷积算法(转载和整理)

         在整理全卷积网络的过程中,被反卷积的概念困扰很久,于是将反卷积算法单独整理为一篇博客,本文主要转载和整理自知乎问题如何通俗易懂地解释反卷积?中的高票答案。

1.反卷积概述:         

          应用在计算机视觉的深度学习领域,由于输入图像通过卷积神经网络(CNN)提取特征后输出的尺寸往往会变小,从而导致有些情况例如在图像的语义分割过程中,我们需要将图像恢复到原来的尺寸以便进行进一步的计算,这个采用扩大图像尺寸,实现图像由小分辨率到大分辨率的映射的操作,叫做上采样(Upsample)。

          上采样有3种常见的方法:双线性插值(bilinear),反卷积(Transposed Convolution),反池化(Unpooling),我们这里只讨论反卷积。

           这里指的反卷积,也叫转置卷积,它并不是正向卷积的完全逆过程,反卷积是一种特殊的正向卷积,先按照一定的比例通过补0来扩大输入图像的尺寸,接着旋转卷积核,再进行正向卷积。

 

2.反卷积的数学推导:

        (1)正向卷积的实现过程:

                 假设输入图像尺寸为 4*4,元素矩阵为:

                 卷积核 kernal尺寸为3*3,元素矩阵为:

                 步长 strides=1,填充 padding=0,即 i=4,k=3,s=1,p=0,则按照卷积计算公式 o=\frac{i+2p-k}{s}+1,输出图像的尺寸为 2*2。其中:

        (2)用矩阵乘法描述卷积:

                 把输入图像的元素矩阵展开成一个列向量 X:

                 把输出图像 的元素矩阵展开成一个列向量 Y:

                对于输入的元素矩阵X和输出的元素矩阵Y,用矩阵运算描述这个过程为:Y=CX
                通过推导,我们可以得到稀疏矩阵C:

                 反卷积的操作就是要对这个矩阵运算过程进行逆运算,即通过 C和Y得到 X,根据各个矩阵的尺寸大小,我们能很轻易的得到计算的过程,即为反卷积的操作:

                 但是,如果代入数字计算会发现,反卷积的操作只是恢复了矩阵 X的尺寸大小,并不能恢复 X的每个元素值。

        (3)反卷积的输入输出尺寸关系:

                 在进行反卷积时,简单来说,大体上可分为以下两种情况: 

                  1)Relationship 1:(o+2p-k)%s=0

                         此时反卷积的输入输出尺寸关系为:o=s(i-1)-2p+k

                         如下图所示,我们选择一个输入尺寸为3*3,卷积核kernal尺寸为3*3,步长strides=2,填充padding=1,即i=3,k=3,s=2,p=1,则输出的尺寸为o=5。


                  2)Relationship 2:(o+2p-k)%s!=0

                       此时反卷积的输入输出尺寸关系为:o=s(i-1)-2p+k+(o+2p-k)%

                      如下图所示,我们选择一个输入尺寸为3*3,卷积核kernal尺寸为3*3,步长strides=2,填充padding=1,即i=3,k=3,s=2,p=1,则输出的尺寸为o=5+1=6。

3.在tensorflow中实现反卷积:

          下面用一组实验更直观的解释一下在 tensorflow 中反卷积的过程:

          令输入图像为:

          卷积核为:

          1)case 1:
               如果要使输出的尺寸是 5*5,步数 strides=5,tensorflow 中的命令为:

transpose_conv = tf.nn.conv2d_transpose(value=input, filter=kernel, output_shape=[1,5,5,1], strides=2, padding='SAME')

               当执行 transpose_conv 命令时,tensorflow 会先计算卷积类型、输入尺寸、步数和输出尺寸之间的关系是否成立,如果不成立,会直接提示错误,如果成立,执行如下操作:

               1.现根据步数 strides对输入的内部进行填充,这里strides可以理解成输入放大的倍数,即在输入的每个元素之间填充 0,0的个数n与strides的关系为:

                例如这里举例的strides=2,即在输入的每个元素之间填1个0:

              因为卷积类型为 same,所以此时i=5,k=3,s=1,p=1。

              2. 接下来,用卷积核kernal对填充后的输入进行步长strides=1的正向卷积,根据上文的正向卷积输出尺寸公式得到输出尺寸是5*5,反卷积公式中我们给出的输出尺寸参数也是为5,两者相同,所以可以进行计算,结果为:

              与 tensorflow 的运行结果相同。

          2)case 2:
              我们将 case 1 中的输出尺寸改成6,其他参数均不变,tensorflow 中的命令为:

transpose_conv = tf.nn.conv2d_transpose(value=input,     filter=kernel,     output_shape=[1,6,6,1],   strides=2,         padding='SAME')

              卷积类型是 same,我们首先在外围填充一圈0:

              这时发现,填充后的输入尺寸与3*3的卷积核卷积后的输出尺寸是5*5,没有达到输出的6*6,这就需要继续填充 0,tensorflow 的计算规则是优先在左侧和上侧填充一排 0,填充后的输入变为:

              接下来,再对这个填充后的输入与3*3的卷积核卷积,结果为:

              与 tensorflow 的运行结果相同。

4.从工程角度解释反卷积:

          如果读深度学习框架的源码可以看到,反卷积前向和后向传播的实现,恰好就是对应卷积的后向和前向传播,这里简单看下caffe反卷积层的前向实现的源码deconv_layer.cpp:

          可以看到核心计算部分其实是调用了继承自卷积层的反向传播函数base_conv_layer.cpp:

          可以看到卷积的反向传播实现就是一个gemm+col2im,所以只要理解了卷积的反向传播的计算过程,那么反卷积的前向计算过程也就懂了。下面结合卷积运算过程的示例图解释下其前向和反向传播的计算流程:

          首先看到卷积的FP(前向传播)计算流程,假设给定卷积输入大小是 Cin * Hin * Win, 卷积输出通道数为Cout,卷积核空间大小 K * K,则权值大小是 Cout * Cin * K * K,卷积运算的一个加速方法是转换成矩阵乘法,就是把输入通过 im2col 操作转成 (Cin * K * K ) x (Hout * Wout)大小的矩阵,然后和同样把每个输出通道对应的权值拉成向量,就可以做矩阵乘法了,可以看到乘法结果就是卷积输出结果。

          卷积的反向传播是给定输出梯度反求输入梯度,已知输出梯度大小和卷积输出特征图一致,输入梯度大小和输入特征图一致,如果是3x3且步长为2的卷积且padding 为1,那么输出特征图大小相当于是输入的一半,那么反向传播看起来就像是把输出梯度变大到输入梯度大小的过程,就与反卷积所做的工作一致了。

          卷积的反向传播转换成矩阵乘法之后,其求导结果和全连接层求导结果类似,相当于把权值转置然后和输出梯度做乘法,得到输入梯度的中间结果。

          如图所示卷积反向传播(BP)部分的中间结果大小是 (Cin * K * K ) x (Hout * Wout),前向卷积过程中的im2col操作的逆操作为col2im,使用col2im操作使中间结果的每一列 Cin * K * K 大小的向量reshape成 (Cin, K,K)的 tensor,然后向输入梯度对应通道的对应位置上回填累加。这里首先会把输入梯度每个位置初始化为0,回填的时候是根据步长滑动回填窗口,与卷积前向时根据步长滑动卷积窗口相同。然后就完成了把输出梯度变大到输入梯度大小的过程了。

          理解了卷积的前向和后向计算之后再来看反卷积就很容易理解了,下图最下面一行反卷积的前向过程和卷积的反向过程对照来看:

          这里简单绘制一个计算流程图展示卷积的反向传播和反卷积的前向传播过程,假设卷积和反卷积核大小都是3x3,步长为2,卷积输入大小是4x4,现在假设需要卷积输出或反卷积输入大小是2x2,则根据卷积输出大小计算公式(( input + 2 * pad - kernel )/ stride + 1 )则需要pad 1,则现在看下如何从2x2大小的输入反推输出4x4,为了方便理解,假设权值都是1,卷积输出梯度或者反卷积输入值都是1,输入和输出通道都是1:

          中间结果矩阵大小为9x4,然后把每一列reshape成 3x3 大小然后往6x6输出上累加,最后再crop出中间部分,就得到结果了。下面用mxnet简单验证下结果:

import mxnet as mxdata_shape = (1, 1, 2, 2)
data = mx.nd.ones(data_shape)deconv_weight_shape = (1, 1, 3, 3)
deconv_weight = mx.nd.ones(deconv_weight_shape)# deconvolution forward
data_deconv = mx.nd.Deconvolution(data=data, weight=deconv_weight, kernel=(3, 3),pad=(1, 1),stride=(2, 2),adj=(1, 1),num_filter=1)
print(data_deconv)# convolution backward
data_sym = mx.sym.Variable('data')
conv_sym = mx.sym.Convolution(data=data_sym, kernel=(3, 3), stride=(2, 2), pad=(1, 1), num_filter=1, no_bias=True, name='conv')
executor = conv_sym.simple_bind(data=(1, 1, 4, 4), ctx=mx.cpu())
mx.nd.ones((1, 1, 3, 3)).copyto(executor.arg_dict['conv_weight'])
executor.backward(mx.nd.ones((1, 1, 2, 2)))print(executor.grad_dict['data'])

          从下图结果可以看到打印出的反卷积前向结果和卷积的反向结果与上面计算流程图中的结果一致:

 

5.参考资料:

     (1) 作者:梁德澎
                链接:https://www.zhihu.com/question/48279880/answer/838063090

      (2)反卷积和上采样+卷积的区别?​www.zhihu.com

      (3)作者:孙小也
                链接:https://www.zhihu.com/question/48279880/answer/525347615

      (4) SIGAI:反向传播算法推导-全连接神经网络​zhuanlan.zhihu.com

      (5)关于im2col的解释可参考博客:caffe im2col 详解​blog.csdn.net


http://chatgpt.dhexx.cn/article/KiJUcsVM.shtml

相关文章

卷积和反卷积详解

反卷积(deconvolution),也叫转置卷积,分部卷积(fractionally-strided convolution),在论文中也叫upconv。 1. Pytorch中2D卷积和反卷积的函数 class torch.nn.Conv2d(in_channels, out_channe…

什么是反卷积(快速理解)

什么是反卷积 参考博客 我们知道输入图像通过卷积神经网络(CNN)提取特征后,输出的尺寸往往会变小,而又是我们需要将图像恢复到原来的尺寸以便进行进一步的计算,整个扩大图像尺寸,实现图像由小分辨率到大分辨…

反卷积(Transposed Convolution, Fractionally Strided Convolution or Deconvolution)

反卷积(Deconvolution)的概念第一次出现是Zeiler在2010年发表的论文 Deconvolutional networks 中,但是并没有指定反卷积这个名字,反卷积这个术语正式的使用是在其之后的工作中( Adaptive deconvolutional networks for mid an…

反卷积详解

一.概述 反卷积又称转秩卷积(Transposed Convolution),上采样(Upsampled )。 其作用举例如下: 1.当我们用神经网络生成图片的时候,经常需要将一些低分辨率的图片转换为高分辨率的图片。 2.在语义分割中,会使用卷积层在编码器中…

反卷积通俗详细解析与nn.ConvTranspose2d重要参数解释

文章目录 反卷积的作用卷积中padding的几个概念No PaddingHalf(Same) PaddingFull Padding 反卷积反卷积中的Padding参数反卷积的stride参数反卷积的output_padding参数 反卷积总结参考资料 反卷积的作用 传统的卷积通常是将大图片卷积成一张小图片,而反卷积就是反…

反卷积(Transposed conv deconv)实现原理(通俗易懂)

什么是卷积 卷积就是把卷积核放在输入上进行滑窗,将当前卷积核覆盖范围内的输入与卷积核相乘,值进行累加,得到当前位置的输出,其本质在于融合多个像素值的信息输出一个像素值,本质上是下采样的,所以输出的…

Mysql的基本使用——Mysql教案(一)

文章目录 Mysql的基本使用1. Mysql的安装2. Mysql基本操作数据库操作表操作SQL操作练习资源课堂练习 查询(SELECT)去重(distinct)别名(AS)限制查询数(limit)排序(ORDER BY)条件查询(WHERE)普通查询多条件的查询语句模糊查询BETWEEN AND 内连接查询(inner join)外连接查询(outer…

链表-双链表

双向链表应用实例 双向链表的操作分析和实现 使用带 head 头的双向链表实现 管理单向链表的缺点分析: 单向链表,查找的方向只能是一个方向,而双向链表可以向前或者向后查找。单向链表不能自我删除,需要靠辅助节点 ,而双向链表&…

八股文之mysql

1、MySQL性能优化解决思路 SQL优化 表结构优化 程序配置优化 架构设计优化 硬件和操作系统优化 SQL语句优化 索引失效情况 最左前缀匹配原则 索引下推 表结构优化 将字段很多的表分解成多个表 对于字段较多的表,如果有些字段的使用频率很低,可以将…

数据库-MySQL

1.数据库基础概念 1.查看数据库-SQLsever学习基础概念 2.MySQL数据类型 1.MySQL支持多种数据类型,大致可分为四类 1.数值类型2.日期和时间类型3.字符串(字符)类型4.二进制类型 1.数值类型 1.整数类型 1.TINYINT(小整型数&#xff…

【爆肝题解】❤️24❤️新手也能理解并学会的剑指offer题目❤️❤️剑指 Offer 24. 反转链表

本文章是❤️剑指 offer(第2版)❤️的内容,该专栏还有多篇优质内容在等待你观看,现在点击右上角点击这个————🚀订阅专栏🚀 🔆坚持刷算法 💎每天进步一点点 🚀冲冲冲冲…

mysql 表结构反转,【数据结构】单向链表的反转/倒置的一种实现方法

【背景】 单向链表由于其存储灵活,所有的元素位置是通过额外开辟的指针作为指向的,于是在复习过程中,不由得想象一下如何将链表进行反转。 参考网上的教程,大多是用改变指针的指向进行实现,当然也有利用递归栈的特殊性…

Mysql数据库面经

目录 1、SQL1.1 介绍一下数据库分页1.2 介绍一下SQL中的聚合函数1.3 表跟表是怎么关联的?1.4 说一说你对外连接的了解1.5 说一说数据库的左连接和右连接1.6 SQL中怎么将行转成列?1.7 谈谈你对SQL注入的理解如何解决SQL注入1.8 将一张表的部分数据更新到另…

MySQL进阶

一、索引 1.1 索引概述 MySQL官方对索引的定义为:索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据…

MySQL经典100问

目录 常规篇 1、说一下数据库的三大范式? 2、只查询一条数据,但是也执行非常慢,原因一般有哪些? 3、count(*)、count(0)、count(id)实现方式的区别? 4、误删数据怎么办? 5、drop、truncate 和 delet…

Mysql常见面试题

文章目录 1. SQL1.1 介绍一下数据库分页1.2 SQL中怎么将行转成列?1.3 谈谈你对SQL注入的理解1.4 WHERE和HAVING有什么区别? 2. 索引2.1 说一说你对MySQL索引的理解2.2 如何创建及保存MySQL的索引?2.3 如何判断数据库的索引有没有生效&#xf…

mysql 表结构反转_数据结构-单链表反转的三种方式

单链表是一种线性数据结构,由当前节点数据和指向下个节点的指针组成,因为是单向的,所以称为单链表 单链表的反转: 例如:1—>2—>3—>4 反转成:4—>3—>2—>1 首先定义一个链表的节点&…

mysql 双向链表_23张图!万字详解「链表」,从小白到大佬!

链表和数组是数据类型中两个重要又常用的基础数据类型。 数组是连续存储在内存中的数据结构,因此它的优势是可以通过下标迅速的找到元素的位置,而它的缺点则是在插入和删除元素时会导致大量元素的被迫移动,为了解决和平衡此问题于是就有了链表…

面试必备 | 不可不会的反转链表

反转链表这题真的是面试非常喜欢考的了,这题看起来简单,但是能用两种方法一遍 bug free 也是不容易的,面试的时候可以筛下来一大批人,无论是对 junior 还是 senior 面试都很爱考。 今天齐姐就带你梳理清楚思路,思路清楚…

C/C++基础题124.反转链表

Hello: Person person = new Person(); person.Name = “xueyubin”; person.WeChat = “18309212110”; person.HeaderPhoto=“戴眼镜、黑眼圈、格子衫、牛仔裤、双肩包”; person.Sex = “男”; String major[] = { ‘C’,“C++”, “Linux”,“MySQL” }; person.IWantSay(“…