首先说下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宽度方向两侧填充的:

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 torchim = 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)]

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

(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计算式得到的输出尺寸非整数时,会通过删除多余的行和列来保证卷积的输出尺寸为整数。

参数名字和值输出代码:

for name, param in c.named_parameters():
  ...:     print(name,param)

out:  
weight Parameter containing:
tensor([[[[ 0.2163,  0.3264],
          [-0.3781,  0.2940]]]], requires_grad=True)
bias Parameter containing:
tensor([-0.4384], requires_grad=True)

pytorch中的卷积操作详解相关推荐

  1. NLP中的卷积操作详解(torch.nn.Conv1d)

    NLP领域中,由于自然文本是一维的,通常使用一维卷积即可达到要求. 在实际应用中,经embedding层处理后的数据格式一般为(batch_size, word_embeddings_dim, max ...

  2. PyTorch中计算KL散度详解

    PyTorch计算KL散度详解 最近在进行方法设计时,需要度量分布之间的差异,由于样本间分布具有相似性,首先想到了便于实现的KL-Divergence,使用PyTorch中的内置方法时,踩了不少坑,在 ...

  3. PyTorch中的matmul函数详解

    PyTorch中的两个张量的乘法可以分为两种: 两个张量对应的元素相乘(element-wise),在PyTorch中可以通过torch.mul函数(或者∗*∗运算符)实现 两个张量矩阵相乘(Matr ...

  4. PyTorch中squeeze()和unsqueeze()详解

    pytorch中squeeze()和unsqueeze()作用 squeeze() squeeze() 用于在张量的指定维度插入新的维度 (为1) 得到维度提升的张量. unsqueeze() uns ...

  5. PyTorch中torch.norm函数详解

    torch.norm() 是 PyTorch 中的一个函数,用于计算输入张量沿指定维度的范数.具体而言,当给定一个输入张量 x 和一个整数 p 时,torch.norm(x, p) 将返回输入张量 x ...

  6. Linux中的vi操作详解【转】

    vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指令.由于对Unix及Linux系统的任何版本,vi编辑器是完全相 ...

  7. PyTorch中的topk函数详解

    听名字就知道这个函数是用来求tensor中某个dim的前k大或者前k小的值以及对应的index. 用法 torch.topk(input, k, dim=None, largest=True, sor ...

  8. pytorch中scatter()、scatter_()详解

    scatter().scatter_() scatter() 和 scatter_() 的作用一样. 不同之处在于 scatter() 不会直接修改原来的 Tensor,而 scatter_() 会在 ...

  9. python中permute_PyTorch中permute的用法详解

    PyTorch中permute的用法详解 permute(dims) 将tensor的维度换位. 参数:参数是一系列的整数,代表原来张量的维度.比如三维就有0,1,2这些dimension. 例: i ...

最新文章

  1. cygwin编译verilator_Windows 安装 verilator
  2. 排序算法之直接插入排序
  3. Exchange禁用中继后仍然被中继的处理方法
  4. 记一次php项目上线遇到的坑
  5. 死磕Java并发:J.U.C之并发工具类:CountDownLatch
  6. 数据库索引的实现原理及查询优化
  7. 如何在 ASP.Net Core 中使用 Consul 来存储配置
  8. 2020 存储技术热点与趋势总结
  9. session cookie区别 客户端存储
  10. Android提供两个常用的消息弹出框【Toast和Alert】
  11. Centos7 Zabbix监控部署
  12. java实现9*9乘法表
  13. Boostnote:适合程序员的笔记软件
  14. “浅尝”JavaScript设计模式
  15. 2011年下半年 系统集成项目管理工程师 下午试卷
  16. 音频线是什么 音频线如何连接
  17. BLAST原理和用法总结(一)
  18. java中的LinkedList(链表)与ArrayList(动态数组):(1)简单辨析
  19. skylin怎么添加geoserver发布的wfs图层
  20. python count函数用法示例_python count函数用法详解

热门文章

  1. 有一个分数序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个数列的前20项之和
  2. 叠加多个装饰器——day13
  3. 网络I/O模型--04非阻塞模式(解除accept()、 read()方法阻塞)的基础上加入多线程技术...
  4. Android远程桌面助手之功能简介
  5. string与wstring互转
  6. java实现中缀表达式转后缀表达式
  7. Nginx前端设置反向代理,后端Apache如何获取访客的真实IP,结合PHP
  8. 九度OJ1005题 一直WA??
  9. 接口测试工具--apipost如何取消json参数中转义字符
  10. 性能测试之JMeter接口关联【JSON提取器】详解