机器学习19:反卷积算法

2023-11-07

机器学习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 mx

data_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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

机器学习19:反卷积算法 的相关文章

  • MySQL提权篇

    一 Mysql提权必备条件 1 服务器安装Mysql数据库 利用Mysql提权的前提就是服务器安装了mysql数据库 且mysql的服务没有降权 Mysql数据库默认安装是以系统权限继承的 并且需要获取Mysql root账号密码 2 判断
  • 14:00面试,14:06就出来了,问的问题有点变态。。。

    从小厂出来 没想到在另一家公司又寄了 到这家公司开始上班 加班是每天必不可少的 看在钱给的比较多的份上 就不太计较了 没想到5月一纸通知 所有人不准加班 加班费不仅没有了 薪资还要降40 这下搞的饭都吃不起了 还在有个朋友内推我去了一家互联
  • 【生成式网络】入门篇(二):GAN的 代码和结果记录

    GAN非常经典 我就不介绍具体原理了 直接上代码 感兴趣的可以阅读 里面有更多变体 https github com rasbt deeplearning models tree master pytorch ipynb gan GAN 在

随机推荐

  • Kafka消费者Relance机制和分区机制

    kafka消费者Relance rebalance就是说如果消费组里的消费者数量有变化或消费的分区数有变化 kafka会重新分配消费者消费分区的关系 比如consumer group中某个消费者挂了 此时会自动把分配给他的分区交给其他的消费
  • MySQL如何删除#sql开头的临时表

    1 现象 巡检时发现服务器磁盘空间不足 通过查看大文件进行筛选是发现有几个 sql开头的文件 且存在超过100G及10G以上的文件 2 原因 如果MySQL在一个 ALTER TABLE操作 ALGORITHM INPLACE 的中间退出
  • MMdetection系列之Config配置文件(V3更新后)

    1 了解配置 MMDetection 和其他 OpenMMLab 存储库使用MMEngine 的配置系统 模块化 继承性设计 便于进行各种实验 2 配置文件的查看 在配置系统中采用模块化和继承性设计 便于进行各种实验 如果你想查看配置文件
  • Gin框架结合gorm使用

    Gin框架结合Gorm使用 目录 Gin框架结合Gorm使用 前言 一 介绍 二 使用步骤 1 创建项目 2 开始main go 3 router的初始化 4 controller的初始化 5 services的初始化 6 models的初
  • 比较对象相等性的四种方法

    比较对象相等性的四种方法 System Object定义了3个不同的方法 来比较对象的相等性 ReferenceEquals 和两个版本的Equals 再加上比较运算符 实际上是有四种比较相等的方式 在编程中实际上我们只需要这两种比较 c
  • 使用vue-cli脚手架创建vue项目

    本文主要介绍使用的是安装vue cli脚手架并使用vue cli脚手架来创建vue项目 1 前置条件 需要安装npm 和nodejs 查看npm 和nodejs版本是否符合要求 如果版本不符合要求 有可能会导致安装失败 查看npm版本 np
  • 数学(3) 各种数学分布,高斯,伯努利,二项,多项,泊松,指数,Beta,Dirichlet

    打算这里记录各种数学分布 随时更新 正态分布 正态分布又名高斯分布 若随机变量X服从一个数学期望为 mu 标准差为 sigma的正态分布 则记为 X N 2 X 65374 N mu sigma 2 其中期望 mu决定了分布位置 标准差 s
  • Linux-eth0 eth0:1 和eth0.1关系、ifconfig以及虚拟IP实现介绍

    eth0 eth0 1 和eth0 1三者的关系对应于物理网卡 子网卡 虚拟VLAN网卡的关系 物理网卡 物理网卡这里指的是服务器上实际的网络接口设备 这里我服务器上双网卡 在系统中看到的2个物理网卡分别对应是eth0和eth1这两个网络接
  • Android开机自启动C程序调试

    Android开机自启动C程序调试 本次记录是关于如何在rk3566的Android11版本下将led时钟显示添加成开机自启动的C程序 首先 当然是在sdk中会被执行到的 rc文件中将我们所需要执行的C程序添加为服务 可以在init rc或
  • 剑指 Offer 58 - II. 左旋转字符串(java+python)

    字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部 请定义一个函数实现字符串左旋转操作的功能 比如 输入字符串 abcdefg 和数字2 该函数将返回左旋转两位得到的结果 cdefgab 示例 1 输入 s abcdefg k
  • python-爬虫初识-自动登录(二)

    目录 一 BeautifulSoup模块详细介绍 二 自动登录github 一 BeautifulSoup模块详细介绍 BeautifulSoup是一个模块 该模块用于接收一个HTML或XML字符串 然后将其进行格式化 之后遍可以使用他提供
  • 自定义一个类加载器

    为什么要自定义类加载器 类加载机制 http www cnblogs com xrq730 p 4844915 html 类加载器 http www cnblogs com xrq730 p 4845144 html 这两篇文章已经详细讲解
  • HKPCA Show携手电巢直播开启“云”观展!掀起一场电子人的顶级狂欢!

    近日 国际电子电路 深圳 展览会 HKPCA Show 已于深圳国际会展中心圆满举办 本次展览划分七大主题专区 面积超50 000平方米 展位超2500个 汇聚众多行业知名 有影响力的参展商 引用现场观众的一句话讲 这种规模的电子展览会真是
  • 北欧--2022年Python爬虫心得

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 前言 网络爬虫也称为 蜘蛛 它可以在海量的互联网信息爬取需要的信息 简单地说它是模拟人类请求网站的行为 即自动请求网页 抓取数据 然后从中提取有价值的数据 具体步骤如下 首先
  • oracle主键约束删除,oracle删除主键查看主键约束及创建联合主键

    oracle删除主键查看主键约束及创建联合主键 1 主键的删除 ALTER TABLE TABLENAME DROP PRIMARY KEY 执行上面的SQL可以删除主键 如果不成功可以用 ALTER TABLE TABLENAME DRO
  • C/C++访问MySQL数据库

    C C 访问MySQL数据库 VS2019配置 打开mysql的安装目录 默认安装目录如下 C Program Files MySQL MySQL Server 8 0 确认 lib 目录和include 目录是否存在 打开VS2019 新
  • 如何将自己的项目jar包打包成docker 镜像

    首先将自己的项目打包成jar 并在自己本地先用java jar xxx jar启动下 看是否可以启动 随后将自己的jar包同级目录创建一个Dockerfile文件 并用notepad打开 文件无后缀 FROM kdvolder jdk8 V
  • linux下手动安装编译的通用步骤

    手动安装编译的通用步骤 在自己的下载目录中 1 在官网下载压缩包 wget xxx 2 解压文件 tar zxf xxx 3 开始编译安装 查看解压的目录下的文件 是config还是autogen之类的 来决定使用 autogen sh还是
  • 如何使用memset函数

    如何使用memset函数 memset用处 memset使用方法 memset用处 memset函数是主要用于初始化字符串的一个函数 也可以用于初始化自定义类型数组 结构体数组和其他类型数组 memset使用方法 memset函数原型如下
  • 机器学习19:反卷积算法

    机器学习19 反卷积算法 转载和整理 在整理全卷积网络的过程中 被反卷积的概念困扰很久 于是将反卷积算法单独整理为一篇博客 本文主要转载和整理自知乎问题如何通俗易懂地解释反卷积 中的高票答案 1 反卷积概述 应用在计算机视觉的深度学习领域