当前位置: 首页 > news >正文

【动手学深度学习PyTorch版】13 卷积层的填充和步幅

上一篇移步【动手学深度学习PyTorch版】12 卷积层_水w的博客-CSDN博客

目录

一、卷积层的填充和步幅

1.1 填充

1.2 步幅

1.3 总结

二、代码实现填充和步幅(使用框架)


一、卷积层的填充和步幅

1.1 填充

假设我们给出一个输入图像的大小为(32x32),图片比较小的时候,那么如果应用一个大小为5x5的卷积核,输出就会减少4x4,也就是说(32x32)变成了[(32-5+1)x(32-5+1)]=(28x28)。

如果用7层,那么我们得到的输出就是(4x4),而且我们用更大的卷积核的话,可以更快的减少输出的大小,

所以卷积层的输出形状由输入形状和卷积核窗口形状决定。填充和步幅。它们可以对给定形状的输入和卷积核改变输出形状

那么就会有个问题:假设我不想要我的输出变得这么小,应该怎么办?如果我想要做更深的卷积层怎么办?

解决这个问题的第一个办法:填充

可以在输入的周围添加额外的行或者列,让我们的输出变得比以前更加大。

比如,下图中,我们在输入的周围添加额外的行0或者列0,然后滑动窗口,得到输出。

填充之后,我们就相当于多了参数Ph和Pw,

原输入数组形状是Nh×Nw,卷积核形状是Kh×Kw,那么原输出数组形状就是

(Nh-Kh+1)×(Nw-Kw+1)。如果我们对输入数组进行填充高加Ph,宽加Pw,那么新的输出数组形状就是(Nh-Kh+Ph+1)×(Nw-Kw+Pw+1)。

通常我们为了方便在构造网络时推测每个层的输出形状,会设置Ph=Kh-1,Pw=Kw-1。这样输入输出形状就是一致的,是为了将Ph和Pw的值代入进去式子的时候,就可以消去。

也就是说,我的输出和输入的大小不会发生变化,都是Nh和Nw。这是一个挺好的东西, 不管我们选取的核的大小,都不会改变输出和输入的大小。

具体说填充,我们可以在上或者下填充,

① 奇数卷积核更容易做padding。我们假设卷积核大小为k * k,为了让卷积后的图像大小与原图一样大,根据公式可得到padding=(k-1)/2,这里的k只有在取奇数的时候,padding才能是整数,否则padding不好进行图片填充。

② k为偶数时,p为浮点数,所做的操作为一个为向上取整,填充,一个为向下取整,填充。

1.2 步幅

假设我们的输入变成了(254x254),假设我想要输出的大小为4x4,那么在使用5x5卷积核的情况下,需要55层才能将输出降低到4x4,这就比较痛苦了。

因为层数越多计算就越复杂,需要大量的计算才能得到较小的输出。

可以使用步幅:行/列的滑动步长来解决这个问题。

因为之前输出的大小是跟层数呈现线性相关的,那使用步幅可以让输出的大小跟层数变成指数相关。

假设我们的核还是2x2,使用步幅的高度为3,宽度为2,

输出Y的第一个元素还是0,但是到输出Y的第2个元素“8”时,下一个不再是之前我们考虑的绿框了(默认步幅为1),而是往右移两点,直接变成了红框,

再往右跳2的话,由于没有足够的值了,所以输出的宽度就为2。

同理,在高度上,类似。

当我们不做步幅的调整,即默认步幅为1,那么输出的大小为4x4。

现在使用了步幅之后,我们就直接把我们的5x5大矩阵变成了一个2x2的小矩阵了。

这就是步幅的概念,在每次滑动窗口的时候,控制滑动的行数或者列数,成倍的减少输出的形状。

1.3 总结

参数

in_channels:输入的通道数目
out_channels: 输出的通道数目
kernel_size:卷积核的大小,类型为int 或者元组,当卷积是方形的时候,只需要一个整数边长即可,卷积不是方形,要输入一个元组表示 高和宽。
stride: 卷积每次滑动的步长为多少,默认是 1
padding: 设置在所有边界增加 值为 0 的边距的大小(也就是在feature map 外围增加几圈 0 ),例如当 padding =1 的时候,如果原来大小为 3 × 3 ,那么之后的大小为 5 × 5 。即在外围加了一圈 0 。
dilation:控制卷积核之间的间距
groups:控制输入和输出之间的连接
bias: 是否将一个 学习到的 bias 增加输出中,默认是 True 。
padding_mode : 字符串类型,接收的字符串只有 “zeros” 和 “circular”。

二、代码实现填充和步幅(使用框架)

(1)输入和输出通道为1,核大小为3x3,填充padding=1 为上下左右都填充一行。

随机生成8x8的矩阵,输入通道为1,输出通道为1,卷积核大小为1x2的,没有设置步长与边界,步长默认为1。

放入函数comp_conv2d(conv2d,X),此时的Ph为2,Pw为2,可以看到我们的输出也是8x8。

# 在所有侧边填充1个像素
import torch
from torch import nn

def comp_conv2d(conv2d, X): # conv2d 作为传参传进去,在内部使用
    X = X.reshape((1,1)+X.shape) # 输入通道为1,输出通道为1,在维度前面加入一个通道数和批量大小数
    Y = conv2d(X)  # 卷积处理是一个四维的矩阵
    return Y.reshape(Y.shape[2:]) # 将前面两个维度拿掉,得到一个矩阵输出

conv2d = nn.Conv2d(1,1,kernel_size=3,padding=1)  # 输入和输出通道为1,核大小为3x3,填充padding=1 为上下左右都填充一行
X = torch.rand(size=(8,8))
print(comp_conv2d(conv2d,X).shape)

是因为上下左右各填充一行,核大小为3x3的话,(8x8)---->(8-3+Ph+1)x(8-3+Pw+1)---->(8-3+2+1)x(8-3+2+1)---->(8)x(8),就不会对输入的大小做什么变化。

(2)当然,我们也可以不那么对称,可以填充不同的高度和宽度。

此时,卷积核的大小为5x3,还是想让输入和输出的大小是一样的话,那么(8x8)---->(8-3+Ph+1)x(8-5+Pw+1),可以计算得到Ph为2,Pw为4,那么上下填充padding应该是2,左右填充padding的列数应该是1,

conv2d = nn.Conv2d(1,1,kernel_size=(5,3),padding=(2,1))
print(comp_conv2d(conv2d,X).shape)

 如果这样设置的话,那么输入和输出还是一样的大小。

(4) 填充padding=2 为上下左右都填充2行,

随机生成8x8的矩阵,输入通道为1,输出通道为1,卷积核大小为3x3的,边界左右扩展1,上下扩展1,步长为2。

那么如果没有“stride=2”的话我们的输出还是8x8,有“stride=2”之后,因为输入的高宽可以被整除,那么输出是从8x8变成了4x4。

# 将高度和宽度的步幅设置为2
conv2d = nn.Conv2d(1,1,kernel_size=3,padding=1,stride=2)
print(comp_conv2d(conv2d,X).shape)

(5)看一个稍微复杂,做一个完全不对称的情况,可以控制在行和列上每一次的卷积的大小。

输入X为8×8,输入通道为1,输出通道为1,卷积核为3×5,边界扩展1,左步长为3,右步长为4。 

# 一个稍微复杂的例子
conv2d = nn.Conv2d(1,1,kernel_size=(3,5),padding=(0,1),stride=(3,4))
print(comp_conv2d(conv2d,X).shape)

那么得到是数组形状是⌊(8-3+0+3)/3⌋=2, (8-5+1+4)/ 4 = 2。

相关文章:

  • 第十三届蓝桥杯C++B组国赛H题——机房 (AC)
  • django框架技术沉淀
  • 血的教训---入侵redis并远程控制你的机器场景复现
  • 基于javaweb的养老院管理系统(java+springboot+thymeleaf+html+js+mysql)
  • 【CV】第 6 章:图像分类的实际方面
  • HazelEngine 学习记录 - Shader Asset Files
  • 网络安全—DDoS攻防
  • 【JavaWeb】之富文本编辑器
  • Synchronized底层核心原理
  • 基于JSP的房屋销售系统设计与实现
  • Arduino UNO 可视化GT-24工业级无线透传
  • 【QT 自研上位机 与 STM32F103下位机联调>>>通信测试-基础样例-联合文章】
  • c语言的三种基本结构——初学者一定要了解哦
  • 无人驾驶:高精地图与定位
  • 【论文笔记】提高超高分辨率图像的语义分割准确性的两种方法:MagNet(CVPR2021)与FCtL(ICCV2021)
  • 4个实用的微服务测试策略
  • Angular4 模板式表单用法以及验证
  • Laravel深入学习6 - 应用体系结构:解耦事件处理器
  • NLPIR语义挖掘平台推动行业大数据应用服务
  • node和express搭建代理服务器(源码)
  • SpiderData 2019年2月13日 DApp数据排行榜
  • Wamp集成环境 添加PHP的新版本
  • Webpack入门之遇到的那些坑,系列示例Demo
  • 不用申请服务号就可以开发微信支付/支付宝/QQ钱包支付!附:直接可用的代码+demo...
  • 强力优化Rancher k8s中国区的使用体验
  • 我从编程教室毕业
  • 小程序 setData 学问多
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • 东超科技获得千万级Pre-A轮融资,投资方为中科创星 ...
  • 函数计算新功能-----支持C#函数
  • ​MySQL主从复制一致性检测
  • ​第20课 在Android Native开发中加入新的C++类
  • !!java web学习笔记(一到五)
  • # 数论-逆元
  • (3)llvm ir转换过程
  • (LNMP) How To Install Linux, nginx, MySQL, PHP
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (心得)获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列。
  • (一)UDP基本编程步骤
  • (原)记一次CentOS7 磁盘空间大小异常的解决过程
  • (转)创业的注意事项
  • .gitignore文件设置了忽略但不生效
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .net core 3.0 linux,.NET Core 3.0 的新增功能
  • .NET Core MongoDB数据仓储和工作单元模式封装
  • .NET Windows:删除文件夹后立即判断,有可能依然存在
  • .NET/C# 在 64 位进程中读取 32 位进程重定向后的注册表
  • .netcore 如何获取系统中所有session_如何把百度推广中获取的线索(基木鱼,电话,百度商桥等)同步到企业微信或者企业CRM等企业营销系统中...
  • .net知识和学习方法系列(二十一)CLR-枚举
  • .Net中wcf服务生成及调用
  • @拔赤:Web前端开发十日谈
  • [ 第一章] JavaScript 简史
  • [ 渗透测试面试篇 ] 渗透测试面试题大集合(详解)(十)RCE (远程代码/命令执行漏洞)相关面试题
  • [ 云计算 | AWS ] AI 编程助手新势力 Amazon CodeWhisperer:优势功能及实用技巧