pytorch中的卷积操作详解

pytorch中的卷积操作详解首先说下pytorch中的Tensor通道排列顺序是:[batch,channel,height,width]我们常用的卷积(Conv2d)在pytorch中对应的函数是:torch.nn.Conv2d(in_channels,out_channels,kernel_size,stride=1,padding=0,dilation=1,groups=1,bias=Tr…

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

首先说下pytorch中的Tensor通道排列顺序是:[batch, channel, height, width]

我们常用的卷积(Conv2d)在pytorch中对应的函数是:

torch.nn.Conv2d(in_channels, 
                out_channels, 
                kernel_size, 
                stride=1, 
                padding=0, 
                dilation=1, 
                groups=1, 
                bias=True, 
                padding_mode='zeros')

 

其中,in_channels参数代表输入特征矩阵的深度即channel,比如输入一张RGB彩色图像,那in_channels=3

           out_channels参数代表卷积核的个数,使用n个卷积核输出的特征矩阵深度即channel就是n

           kernel_size参数代表卷积核的尺寸,输入可以是int类型如3 代表卷积核的height=width=3,也可以是tuple类型如(3, 5)代表卷积核的height=3,width=5

           stride参数代表卷积核的步距默认为1,和kernel_size一样输入可以是int类型,也可以是tuple类型

           padding参数代表在输入特征矩阵四周补零的情况默认为0,同样输入可以为int型如1 代表上下方向各补一行0元素,左右方向各补一列0像素(即补一圈0),如果输入为tuple型如(2, 1) 代表在上方补两行下方补两行,左边补一列,右边补一列。可见下图,padding[0]是在H高度方向两侧填充的,padding[1]是在W宽度方向两侧填充的:

pytorch中的卷积操作详解

          注意:如果要实现更灵活的padding方式,可使用nn.ZeroPad2d方法。

          bias参数表示是否使用偏置(默认使用)

          dilation、groups是高阶用法这里不做讲解,如有需要可以参看官方文档


 在卷积操作过程中,我们知道矩阵经卷积操作后的尺寸由以下几个因数决定:

  1. 输入图片大小 W×W
  2. Filter大小 F×F
  3. 步长 S
  4. padding的像素数 P

 经卷积后的矩阵尺寸大小计算公式为:

      N = (W − F + 2P ) / S + 1

但在实际应用中,有时会出现N为非整数的情况(例如在alexnet,googlenet网络的第一层输出),再例如输入的矩阵 H=W=5,卷积核的F=2,S=2,Padding=1。经计算我们得到的N =(5 – 2 + 2*1)/ 2 +1 = 3.5 此时在Pytorch中是如何处理呢,先直接告诉你结论:在卷积过程中会直接将最后一行以及最后一列给忽略掉,以保证N为整数,此时N = (5 – 2 + 2*1 – 1)/ 2 + 1 = 3,接下来我们来看个简单的实例:

(1)首先使用torch中的随机函数生成一个batch_size为1,channel为1,高和宽都等于5的矩阵

(2)接着我们定义一个卷积核,input_size=1, output_size=1, kernel_size=2, stride=2, padding=1

(3)然后我们使用该卷积核对我们生成的随机矩阵进行卷积操作

(4)打印各参数的数值

import torch.nn as nn
import torch


im = torch.randn(1, 1, 5, 5)
c = nn.Conv2d(1, 1, kernel_size=2, stride=2, padding=1)
output = c(im)

print(im)
print(output)
print(list(c.parameters()))

通过计算我们知道输出矩阵尺寸应该为N =(5 – 2 + 2*1)/ 2 +1 = 3.5,

但实际的打印信息如下: 

# im
tensor([[[[-0.2146,  0.3375,  2.7877,  0.2052, -0.4651],
          [-0.2261,  0.0116, -0.6255,  1.2523, -1.0565],
          [-1.9227, -0.2575, -0.7725,  0.5658,  0.0717],
          [ 0.8153, -1.3656, -0.1844,  0.1573, -0.2235],
          [ 0.0184, -0.0475,  0.2359,  0.0127,  2.0665]]]])

# output
tensor([[[[-0.0467, -1.1766, -0.0450],
          [ 0.5063,  0.1971, -1.0401],
          [-0.0748,  0.4769, -0.8986]]]], grad_fn=<ThnnConv2DBackward>)

# conv2d:parameters
[Parameter containing:
tensor([[[[-0.4872,  0.0604],
          [-0.3968, -0.3317]]]], requires_grad=True), Parameter containing:
tensor([-0.1179], requires_grad=True)]

通过分析,我们可以知道真正的输出矩阵尺寸是3×3,那内部具体是如何操作的呢,

(1)首先进行padding的填充,size:7 x 7

[0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000],
[0.0000, -0.2146,  0.3375,  2.7877,  0.2052, -0.4651,  0.0000],
[0.0000, -0.2261,  0.0116, -0.6255,  1.2523, -1.0565,  0.0000],
[0.0000, -1.9227, -0.2575, -0.7725,  0.5658,  0.0717,  0.0000],
[0.0000,  0.8153, -1.3656, -0.1844,  0.1573, -0.2235,  0.0000],
[0.0000,  0.0184, -0.0475,  0.2359,  0.0127,  2.0665,  0.0000],
[0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000]

(2)通过计算发现输出为非整数,为了得到整数,将最后一行以及最后一列删除掉,size:6 x 6

[0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000],
[0.0000, -0.2146,  0.3375,  2.7877,  0.2052, -0.4651],
[0.0000, -0.2261,  0.0116, -0.6255,  1.2523, -1.0565],
[0.0000, -1.9227, -0.2575, -0.7725,  0.5658,  0.0717],
[0.0000,  0.8153, -1.3656, -0.1844,  0.1573, -0.2235],
[0.0000,  0.0184, -0.0475,  0.2359,  0.0127,  2.0665]

(3)接着使用卷积核进行卷积操作,就能得到我们的输出矩阵,需要注意的是pytorch中的卷积默认是带有bias的,所以计算卷积后需要加上bias偏量。例如输出的第一个值的计算过程如下:

[0.0000,  0.0000],        [-0.4872,  0.0604],
                    卷积                        加上  [-0.1179]
[0.0000, -0.2146]         [-0.3968, -0.3317]

# 即
(0*(-0.4872)+ 0*(0.0604)+ 0*(-0.3968)+(-0.2146)*(-0.3317))+(-0.1179)= -0.0467

我们的计算结果与pytorch的输出相同,我们只计算了其中一个值,其他的值也一样:

# output
tensor([[[[-0.0467, -1.1766, -0.0450],
          [ 0.5063,  0.1971, -1.0401],
          [-0.0748,  0.4769, -0.8986]]]], grad_fn=<ThnnConv2DBackward>)

通过我们的实验可以发现,在pytorch的卷积过程中,当通过N = (W − F + 2P ) / S + 1计算式得到的输出尺寸非整数时,会通过删除多余的行和列来保证卷积的输出尺寸为整数。

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

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/140101.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • centos关闭自动休眠_7P怎么强制重启

    centos关闭自动休眠_7P怎么强制重启taskkill/F/imnginx.exetaskkill/F/imnginx.exed:cdD:\phpstudy_pro\Extensions\Nginx1.15.11startnginx.exe然后做个计划任务。一个小时重启一次

    2022年8月13日
  • 自动化测试平台(三):用户token验证及用户增删改查接口开发

    自动化测试平台(三):用户token验证及用户增删改查接口开发上一篇我们实现了用户登录的验证并返回token。那如何去校验请求的token是否有效呢?这篇内容为你讲解token的验证及用户管理(增删改查)的功能。

    2022年6月29日
  • vagrant系列四:vagrant搭建redis与redis的监控程序redis-stat「建议收藏」

    vagrant系列四:vagrant搭建redis与redis的监控程序redis-stat

    2022年2月8日
  • flyme开放平台_uniapp重定向

    flyme开放平台_uniapp重定向#功能概述[Fly.js](https://github.com/wendux/fly)一个基于Promise的、强大的、支持多种JavaScript运行时的http请求库.有了它,您可以使用一份http请求代码在浏览器、微信小程序、Weex、Node、ReactNative、快应用中都能正常运行。同时可以方便配合主流前端框架,最大可能的实现WriteOnceRunEverywh…

    2022年9月3日
  • i386 i586 i686 的意思「建议收藏」

    i386 i586 i686 的意思「建议收藏」代表intel系列的cpu386几乎适用于所有的x86平台,不论是旧的pentum或者是新的pentum-IV与K7系列的CPU等等,都可以正常的工作!那个i指的是Intel兼容的CPU的意思,至于386不用说,就是CPU的等级啦!i586就是586等级的计算机,那是哪些呢?包括pentum第一代MMXCPU,AMD的K5,K

    2022年6月7日
  • 关于软件质量的思考 – 什么是质量

    关于软件质量的思考 – 什么是质量

    当选择一个商品的时候,我们常挂在嘴边的一个词就是“质量”,这是影响我们选择的一个很重要的指标。这一篇我们就来探讨一下什么是软件的质量。当然,都是个人的一些观点,不同意可以拍砖或者来探讨。

    质量这个词用得太普遍以至于混乱,有时候它表示质量这个指标,有时候它隐含质量好的意思。而且不可避免的,好的质量常常和它的反面联系在一起,就好像以前的“质量万里行”,或者现在的3.15,列出的都是质量方面的问题,好像很少宣扬质量好的产品。所以很多时候,我们看质量

    2022年9月23日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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