卷积神经网络CNN学习笔记-卷积计算Conv2D函数的理解

目录

  • 1.全连接层存在的问题
  • 2.卷积运算
  • 3.填充(padding)
    • 3.1填充(padding)的意义
  • 4.步幅(stride)
  • 5.三维数据的卷积运算
  • 6.结合方块思考
  • 7.批处理
  • 8.Conv2D函数解析
  • 9.conv2d代码
    • 9.1 stride=1
    • 9.2 stride=2
  • 参考文章

1.全连接层存在的问题

在全连接层中,相邻层的神经元全部连接在一起,输出的数量可以任意决定。全连接层存在什么问题呢?那就是数据的形状被“忽视”了。比如,输入数据是图像时,图像通常是高、长、通道方向上的3维形状。但是,向全连接层输入时,需要将3维数据拉平为1维数据。实际上,前面提到的使用了MNIST数据集的例子中,输入图像就是1通道、高28像素、长28像素的(1, 28, 28)形状,但却被排成1列,以784个数据的形式输入到最开始的Affine层。图像是3维形状,这个形状中应该含有重要的空间信息。比如,空间上邻近的像素为相似的值、RBG的各个通道之间分别有密切的关联性、相距较远的像素之间没有什么关联等,3维形状中可能隐藏有值得提取的本质模式。但是,因为全连接层会忽视形状,将全部的输入数据作为相同的神经元(同一维度的神经元)处理,所以无法利用与形状相关的信息。而卷积层可以保持形状不变。当输入数据是图像时,卷积层会以3维数据的形式接收输入数据,并同样以3维数据的形式输出至下一层。因此,在CNN中,可以(有可能)正确理解图像等具有形状的数据。另外,CNN 中,有时将卷积层的输入输出数据称为特征图(feature map)。其中,卷积层的输入数据称为输入特征图(input feature map),输出数据称为输出特征图(output feature map)。本文中将“输入输出数据”和“特征图”作为含义相同的词使用.

2.卷积运算

卷积层进行的处理就是卷积运算。卷积运算相当于图像处理中的“滤波器运算”。在介绍卷积运算时,我们来看一个具体的例子(图7-3)。
在这里插入图片描述
如图7-3所示,卷积运算对输入数据应用滤波器。在这个例子中,输入数据是有高长方向的形状的数据,滤波器也一样,有高长方向上的维度。假设用(height, width)表示数据和滤波器的形状,则在本例中,输入大小是(4, 4),滤波器大小是(3, 3),输出大小是(2, 2)。另外,有的文献中也会用“核”这个词来表示这里所说的“滤波器”。现在来解释一下图7-3的卷积运算的例子中都进行了什么样的计算。图7-4中展示了卷积运算的计算顺序。对于输入数据,卷积运算以一定间隔滑动滤波器的窗口并应用。这里所说的窗口是指图7-4中灰色的3 × 3的部分。如图7-4所示,将各个位置上滤波器的元素和输入的对应元素相乘,然后再求和(有时将这个计算称为乘积累加运算)。然后,将这个结果保存到输出的对应位置。将这个过程在所有位置都进行一遍,就可以得到卷积运算的输出。在全连接的神经网络中,除了权重参数,还存在偏置。CNN中,滤波器的参数就对应之前的权重。并且,CNN中也存在偏置。图7-3的卷积运算的例子一直展示到了应用滤波器的阶段。包含偏置的卷积运算的处理流如图7-5所示。如图7-5所示,向应用了滤波器的数据加上了偏置。偏置通常只有1个(1 × 1)(本例中,相对于应用了滤波器的4个数据,偏置只有1个),这个值会被加到应用了滤波器的所有元素上。
在这里插入图片描述
在这里插入图片描述

3.填充(padding)

在进行卷积层的处理之前,有时要向输入数据的周围填入固定的数据(比如0等),这称为填充(padding),是卷积运算中经常会用到的处理。比如,在图7-6的例子中,对大小为(4, 4)的输入数据应用了幅度为1的填充。“幅度为1的填充”是指用幅度为1像素的0填充周围。
在这里插入图片描述
如图7-6所示,通过填充,大小为(4, 4)的输入数据变成了(6, 6)的形状。然后,应用大小为(3, 3)的滤波器,生成了大小为(4, 4)的输出数据。这个例子中将填充设成了1,不过填充的值也可以设置成2、3等任意的整数。在图7-5的例子中,如果将填充设为2,则输入数据的大小变为(8, 8);如果将填充设为3,则大小变为(10, 10)

3.1填充(padding)的意义

使用填充主要是为了调整输出的大小。比如,对大小为(4, 4)的输入数据应用(3, 3)的滤波器时,输出大小变为(2, 2),相当于输出大小比输入大小缩小了 2个元素。这在反复进行多次卷积运算的深度网络中会成为问题。为什么呢?因为如果每次进行卷积运算都会缩小
空间,那么在某个时刻输出大小就有可能变为 1,导致无法再应用卷积运算。为了避免出现这样的情况,就要使用填充。在刚才的例子中,将填充的幅度设为 1,那么相对于输入大小(4, 4),输出大小也保持为原来的(4, 4)。因此,卷积运算就可以在保持空间大小不变
的情况下将数据传给下一层。

4.步幅(stride)

在这里插入图片描述
在图7-7的例子中,对输入大小为(7, 7)的数据,以步幅2应用了滤波器。通过将步幅设为2,输出大小变为(3, 3)。像这样,步幅可以指定应用滤波器的间隔。综上,增大步幅后,输出大小会变小。而增大填充后,输出大小会变大。如果将这样的关系写成算式,会如何呢?接下来,我们看一下对于填充和步幅,如何计算输出大小。这里,假设输入大小为(H, W),滤波器大小为(FH, FW),输出大小为(OH, OW),填充为P,步幅为S。此时,输出大小可通过式(7.1)进行计算。
在这里插入图片描述
在这里插入图片描述

5.三维数据的卷积运算

之前的卷积运算的例子都是以有高、长方向的2维形状为对象的。但是,图像是3维数据,除了高、长方向之外,还需要处理通道方向。这里,我们按照与之前相同的顺序,看一下对加上了通道方向的3维数据进行卷积运算的例子。图7-8是卷积运算的例子,图7-9是计算顺序。这里以3通道的数据为例,展示了卷积运算的结果。和2维数据时(图7-3的例子)相比,可以发现纵深方向(通道方向)上特征图增加了。通道方向上有多个特征图时,会按通道进行输入数据和滤波器的卷积运算,并将结果相加,从而得到输出。
在这里插入图片描述
在这里插入图片描述
需要注意的是,在3维数据的卷积运算中,输入数据和滤波器的通道数要设为相同的值。在这个例子中,输入数据和滤波器的通道数一致,均为3。滤波器大小可以设定为任意值(不过,每个通道的滤波器大小要全部相同)。这个例子中滤波器大小为(3, 3),但也可以设定为(2, 2)、(1, 1)、(5, 5)等任意值。再强调一下,通道数只能设定为和输入数据的通道数相同的值(本例中为3)。

6.结合方块思考

将数据和滤波器结合长方体的方块来考虑,3维数据的卷积运算会很容易理解。方块是如图7-10所示的3维长方体。把3维数据表示为多维数组时,书写顺序为(channel, height, width)。比如,通道数为C、高度为H、长度为W的数据的形状可以写成(C, H, W)。滤波器也一样,要按(channel, height, width)的顺序书写。比如,通道数为C、滤波器高度为FH(Filter Height)、长度为FW(Filter Width)时,可以写成(C, FH, FW)。
在这里插入图片描述
在这个例子中,数据输出是1张特征图。所谓1张特征图,换句话说,就是通道数为1的特征图。那么,如果要在通道方向上也拥有多个卷积运算的输出,该怎么做呢?为此,就需要用到多个滤波器(权重)。用图表示的话,如图7-11所示。
在这里插入图片描述
图7-11中,通过应用FN个滤波器,输出特征图也生成了FN个。如果将这FN个特征图汇集在一起,就得到了形状为(FN, OH, OW)的方块。将这个方块传给下一层,就是CNN的处理流。如图 7-11 所示,关于卷积运算的滤波器,也必须考虑滤波器的数量。因此,作为4维数据,滤波器的权重数据要按(output_channel, input_channel, height, width)的顺序书写。比如,通道数为3、大小为5 × 5的滤波器有20个时,可以写成(20, 3, 5, 5)。卷积运算中(和全连接层一样)存在偏置。在图7-11的例子中,如果进一步追加偏置的加法运算处理,则结果如下面的图7-12所示。图7-12中,每个通道只有一个偏置。这里,偏置的形状是(FN, 1, 1),滤波器的输出结果的形状是(FN, OH, OW)。这两个方块相加时,要对滤波
器的输出结果(FN, OH, OW)按通道加上相同的偏置值。另外,不同形状的方块相加时,可以基于NumPy的广播功能轻松实现(1.5.5节)。
在这里插入图片描述

7.批处理

神经网络的处理中进行了将输入数据打包的批处理。之前的全连接神经网络的实现也对应了批处理,通过批处理,能够实现处理的高效化和学习时对mini-batch的对应。我们希望卷积运算也同样对应批处理。为此,需要将在各层间传递的数据保存为4维数据。具体地讲,就是按(batch_num, channel, height, width)的顺序保存数据。比如,将图7-12中的处理改成对N个数据进行批处理时,数据的形状如图7-13所示。图7-13的批处理版的数据流中,在各个数据的开头添加了批用的维度。像这样,数据作为4维的形状在各层间传递。这里需要注意的是,网络间传递的是4维数据,对这N个数据进行了卷积运算。也就是说,批处理将N次的处理汇总成了1次进行.
在这里插入图片描述

8.Conv2D函数解析

torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode=‘zeros’, device=None, dtype=None)

  • in_channels:输入通道数,也就是图7-13中的C,指示多少张H×W

  • out_channels:输出通道数,也就是图7-13中的FN

  • kernel_size:卷积核大小,也就是滤波器大小,可以自定义为num或者是num1×num2
    kernel_sizenum时,表示卷积核大小为num×num.

  • stride:当stride=1,卷积核如图9-1所示移动,第一行卷积完毕时,到第二行卷积,其中卷积核每次卷积在水平方向上移动时相差stride=1个格子,垂直方向移动时,相差stride=1个格子.当stride=2时,卷积核如图9-2所示移动,第一行卷积完毕时,从第一行蹦到第三行卷积.水平方向移动时相隔stride=2个格子移动,垂直方向上移动时,相差stride=2个格子移动.

  • padding:padding=0是表示不填充任何0,padding=1表示从(A,A)大小填充为(A+2,A+2),因为是上下左右同时填充1个,所以都要加2.

  • dilation,这个参数涉及到空洞卷积的东西,但是这个我不太理解,只知道dilation=1时就是我们正常卷积.
    在这里插入图片描述
    空洞卷积参考
    👉:🔗深入理解空洞卷积
    👉:🔗Convolution arithmetic

  • groups 分组卷积,一般取值groups = in_channels.这个不太理解,只知道取值一般就是这样,原因以后再补充.现在研一啥也不懂

  • bias即是否要添加偏置参数作为可学习参数的一个,默认为True。

  • padding_mode='zeros':即padding的模式,默认采用零填充

9.conv2d代码

9.1 stride=1

在这里插入图片描述

图9-1
import torch
import torch.nn as nn# 设定一个[1, 3, 5, 5]的输入
input = torch.Tensor([[[[1, 2, 3, 4, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5]],[[1, 2, 3, 4, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5]],[[1, 2, 3, 4, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5]]]])
# 设定一个卷积
conv = nn.Conv2d(in_channels=3,out_channels=3,kernel_size=3,#这里的kernel_size=3和kernel_size=(3,3)意思一样stride=1,padding=0,# 注意,这里padding=0意思是不填充任何数字# 若padding=1,则举个例子,原来的(3,3)是填充为(5,5),而非(4,4)dilation=1,groups=3)# 设定卷积的权重数值
conv.weight.data = torch.Tensor([[[[1, 1, 1],[1, 1, 1],[1, 1, 1]]],[[[2, 2, 2],[2, 2, 2],[2, 2, 2]]],[[[3, 3, 3],[3, 3, 3],[3, 3, 3]]]])
# 利用卷积得到输出
output = conv(input)
print(output)

9.2 stride=2

在这里插入图片描述

图9-2
import torch
import torch.nn as nn# 设定一个[1, 3, 5, 5]的输入
input = torch.Tensor([[[[1, 2, 3, 4, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5]],[[1, 2, 3, 4, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5]],[[1, 2, 3, 4, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5]]]])
# 设定一个卷积
conv = nn.Conv2d(in_channels=3,out_channels=3,kernel_size=3,stride=2,padding=0,dilation=1,groups=3)# 设定卷积的权重数值
conv.weight.data = torch.Tensor([[[[1, 1, 1],[1, 1, 1],[1, 1, 1]]],[[[2, 2, 2],[2, 2, 2],[2, 2, 2]]],[[[3, 3, 3],[3, 3, 3],[3, 3, 3]]]])
# 利用卷积得到输出
output = conv(input)
print(output)

参考文章

[1]🔗Pytorch的nn.Conv2d详解
[2]🔗深入理解空洞卷积
[3]🔗Convolution arithmetic

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/115432.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序阻止返回事件

需求场景 当在一个表单页面 填写了很多数据,或者编辑页面数据发生变动之后,这时候返回上一个页面需要提醒用户是否返回的弹框 实现方法一(ios会存在一定的问题) 在onLoad生命周期里 注册 wx.enableAlertBeforeUnload({message: "您内容已更新,还没保存,确定要退出吗?&…

Socks5代理:数字化时代的技术支柱

随着数字化时代的到来,技术不仅改变了我们的日常生活,还重新定义了商业、通信、娱乐和全球互联。在这一浪潮中,Socks5代理技术崭露头角,成为跨界电商、爬虫数据分析、企业出海和游戏体验的关键推动力。这项技术不仅在实现数字化愿…

vue3+ts父子组件以及单页面刷新的方法

父子组件刷新页面: 父组件定义函数reset,子组件props接收 示例一: 父组件 //ts删减部分: import { deleteCompanyById, findAllCompanys } from /api/company import { usePureFetch } from /nexus/useFetch import type Compa…

CUDA学习笔记(十三) Shared Memory

CUDA SHARED MEMORY shared memory在之前的博文有些介绍,这部分会专门讲解其内容。在global Memory部分,数据对齐和连续是很重要的话题,当使用L1的时候,对齐问题可以忽略,但是非连续的获取内存依然会降低性能。依赖于…

基于Pix4D使用无人机光学影像制作正射影像(DOM)和数字表面模型(DSM) 操作步骤

基于Pix4D使用无人机光学影像制作正射影像(DOM)和数字表面模型(DSM) 操作步骤 0. 前言1.获取无人机光学影像2.DOM和DSM3.操作步骤3.1 初始界面3.2 新建项目3.3查看处理过程报告3.4查看处理进度和成果 4.在ArcMap中打开DSM和DOM 0.…

【X3m】DDR压力测试

Index of /downloads/unittest/ 设置CPU模式和降频温度# 若设备重启需再次配置这两条指令 echo performance > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor echo 105000 > /sys/devices/virtual/thermal/thermal_zone0/trip_point_1_temp #1 cpu test ec…

django基于Python的房价预测系统+爬虫+大屏可视化分析

欢迎大家点赞、收藏、关注、评论 文章目录 前言一、项目介绍二、开发环境三、功能需求分析1 数据采集功能设计2数据管理功能设计3爬虫功能需求分析4 数据可视化功能需求分析数据库表的设计 四、核心代码五、效果图六、文章目录 前言 房价是一个国家经济水平的重要体现&#xff…

找不到mfc140u.dll无法继续执行此代码的5个修复方法分享

是使用计算机的过程中,我们经常会遇到各种各样问题,其中丢失“mfc140u dll”(动态链接库)是最常见的一种。DLL文件是一种可在多个程序之间共享的代码库,它可以被应用程序在运行时动态加载和卸载。而“mfc140u dll”则是…

三刷操作系统之一文带你搞懂FreeRTOS——信号量

信号量是操作系统中重要的一部分,信号量一般用来进行资源管理和任务同步,FreeRTOS中信号量又分为二值信号量、计数型信号量、互斥信号量和递归互斥信号量。不同的信号量其应用场景不同。 1.信号量简介 信号量常常用于控制对共享资源的访问和任务同步。举一个很常见的例子,…

熟练使用 Redis 的五大数据结构:Java 实战教程

入门 入门阶段主要记住 Redis 的命令,熟练使用 Redis 的 5 大数据结构就可以了。 如果没有 Redis 环境,可以直接通过这个网址https://try.redis.io/,很赞,它会给你模拟一个在线的环境可供你尽情使用! 熟练使用Redis的…

C#数据结构--数组和ArrayList

目录 本章目录: 2.1 数组基本概念 2.1.1 数组的声明和初始化 2.1.2 数组元素的设置和存取访问 2.1.4 多维数组 2.1.5 参数数组 2.2ArrayList 类 2.2.1ArrayList 类的成员 2.2.2 应用 ArrayList 类 数组和ArrayList之间的区别以及使用的场景 数组&#xf…

变分贝叶斯深度学习综述

**©PaperWeekly 原创 作者 |**薛博阳 **单位 |**香港中文大学 **研究方向 |**语言模型 引言 近年来,贝叶斯深度学习(Bayesian Deep Learn-ing)在诸多领域得到广泛关注应用,效果显著。本文将针对贝叶斯深度学习框架进行系…

Beyond Compare远程对比

文章目录 Beyond Compare 远程对比1. Beyond Compare基础知识1.1 特性1.2 工作原理 2. 设置远程连接3. 文件和文件夹远程对比4. 问题解决方案 Beyond Compare 远程对比 Beyond Compare是一款强大的文件和文件夹比较工具,提供了用于比较文件和文件夹的直观界面。可以…

测试老鸟总结,Allure测试报告-自动化测试详解,惊险避坑...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 1、Allure安装教程…

前端HTML CSS JS风格规范

本文代码规范来自HTML/CSS代码开发规范文档 文件命名规范 使用小写字母、数字和下划线组成文件名。 避免使用特殊字符和空格。 使用语义化的命名,能够清晰地表达出文件的功能或内容。 目录结构规范 使用约定俗成的目录结构,如:src/compon…

实战:打造一个开箱即用的超丝滑超漂亮hexo博客网站-v4-(通过百度网盘同步空间来同步source核心数据)

实战:打造一个开箱即用的超丝滑超漂亮hexo博客网站-v4-(通过百度网盘同步空间来同步source核心数据) 目录 文章目录 实战:打造一个开箱即用的超丝滑超漂亮hexo博客网站-v4-(通过百度网盘同步空间来同步source核心数据)目录写在前面本次更新方案背景方案官…

云台/稳定器/无人机姿态控制之欧拉角与四元数控制优缺点分析

基于欧拉角的姿态控制简述: 通过陀螺仪数据解算出姿态:pitch,roll,yaw(相对航向),根据目标 姿态:dst_pitch,dst_roll,dst_yaw计算出误差姿态pitch_err,roll_err,yaw_err。将误差姿态转换为目标速度e_pitch_rate,e_roll_rate,e_yaw_rate。然后…

Homeassistant docker配置

Homeassistant docker配置 【说明】本系列为自用教程,记录以便下次使用 【背景】一台J1900 4G64G的小主机,安装了OP系统,里面自带了Docker。为实现Homeassistant(简称HA)控制智能家居设备,进行如下配置。 【…

汽车屏类产品(三):抬头显示Head-Up Display(HUD)

前言 你的下一台车,一定要考虑加装一个HUD。 汽车抬头显示器或汽车抬头显示器(也称为汽车HUD)是任何透明的显示器,它可以在汽车中显示数据,而不需要用户将视线从平时的视角移开。这个名字的由来源于飞行员能够在头部“向上”并向前看的情况下查看信息,而不是向下倾斜查…

[swift刷题模板] 树状数组(BIT/FenwickTree)

[TOC]([swift刷题模板] 树状数组(BIT/FenwickTree) ) 一、 算法&数据结构 1. 描述 [python刷题模板] 树状数组 二、 模板代码 1. 单点赋值(增加),区间求和(PURQ) 例题: 307. 区域和检索 - 数组可修改 class BIT {var c: [Int]var n: Int init(_ n: Int){c…