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

卷积神经网络(一)

第七章 卷积神经网络

从今天开始学习卷积神经网络的内容。

本章的主题是卷积神经网络(Convolutional Neural Network,CNN)。 CNN被用于图像识别、语音识别等各种场合,在图像识别的比赛中,基于 深度学习的方法几乎都以CNN为基础。本章将详细介绍CNN的结构,并用 Python实现其处理内容。

7.1 整体结构

CNN和之前介绍的神经网络一致,都是通过组装各个层来进行构建的。只不过其中出现了新的层:卷积层和池化层。

我们知道,相邻层所有神经元之间都有连接称为全连接(full-connected)。另外我们用Affine层实现了全连接。另外,我们用Affine层实现了全连接层。如果使用 这个Affine层,一个5层的全连接的神经网络就可以通过图7-1所示的网络结 构来实现

全连接的神经网络中,Affine层后面跟着激活函数ReLU 层(或 者 Sigmoid层)。这里堆叠了4层“Affine-ReLU”组合,然后第5层是 Affine层,最后由Softmax层输出最终结果(概率)

如果新增卷积层和池化层,就是一个CNN了。

如图7-2所示,CNN中新增了Convolution层和Pooling层。CNN的 层的连接顺序是“Convolution - ReLU -(Pooling) ”( Pooling层有时会被省略)。这可以理解为之前的“Affine - ReLU”连接被替换成了“Convolution - ReLU -(Pooling)”连接。

还需要注意的是,在图7-2的CNN中,靠近输出的层中使用了之前 的“Affi ne - ReLU”组合。此外,最后的输出层中使用了之前的“Affi ne - Softmax”组合。这些都是一般的CNN中比较常见的结构。

7.2 卷积层

CNN中出现了一些特有的术语,比如填充、步幅等。此外,各层中传 递的数据是有形状的数据(比如,3维数据),这与之前的全连接网络不同, 因此刚开始学习CNN时可能会感到难以理解。本节我们将花点时间,认真 学习一下CNN中使用的卷积层的结构。

7.2.1 全连接层的问题

之前介绍的全连接的神经网络中使用了全连接层(Affine层)。在全连接 层中,相邻层的神经元全部连接在一起,输出的数量可以任意决定。

全连接层存在什么问题呢?那就是数据的形状被“忽视”了。比如,输 入数据是图像时,图像通常是高、长、通道方向上的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)。本书中将“输入输出数据”和“特 征图”作为含义相同的词使用

7.2.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个),这个值 会被加到应用了滤波器的所有元素上。

7.2.3 填充

在进行卷积层的处理之前,有时要向输入数据的周围填入固定的数据(比 如0等),这称为填充(padding),是卷积运算中经常会用到的处理。比如, 在图7-6的例子中,对大小为(4,4)的输入数据应用了幅度为1的填充。“幅 度为1的填充”是指用幅度为1像素的0填充周围。

填充的目的通常是为了保持输出数据与输入数据大小不变。

卷积运算的填充处理:向输入数据的周围填入0(图中用虚线表示填充,并省略了 填充的内容“0”)

如图7-6所示,通过填充,大小为(4,4)的输入数据变成了(6,6)的形状。 然后,应用大小为(3,3)的滤波器,生成了大小为(4,4)的输出数据。这个例 子中将填充设成了1,不过填充的值也可以设置成2、3等任意的整数。在图7-5 的例子中,如果将填充设为2,则输入数据的大小变为(8,8);如果将填充设 为3,则大小变为(10,10)。

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

7.2.4 步幅

应用滤波器的位置间隔称为步幅(stride)。之前的例子中步幅都是1,如 果将步幅设为2,则如图7-7所示,应用滤波器的窗口的间隔变为2个元素。

在图7-7的例子中,对输入大小为(7,7)的数据,以步幅2应用了滤波器。 通过将步幅设为2,输出大小变为(3,3)。像这样,步幅可以指定应用滤波器 的间隔。

综上,增大步幅后,输出大小会变小。而增大填充后,输出大小会变大。 如果将这样的关系写成算式,会如何呢?接下来,我们看一下对于填充和步 幅,如何计算输出大小。

这里,假设输入大小为(H,W),滤波器大小为(FH,FW),输出大小为 (OH,OW),填充为P,步幅为S。此时,输出大小可通过式(7.1)进行计算。

OH=\frac{H+2P-FH}{S}+1

OW=\frac{W+2P-FW}{S}+1

现在,我们使用这个算式,试着做几个计算。

例1:图7-6的例子 输入大小:(4,4);填充:1;步幅:1;滤波器大小:(3,3)

OH=\frac{4+2*1-3}{1}+1=4

OW=\frac{4+2*1-3}{1}+1=4

例2:图7-7的例子 输入大小:(7,7);填充:0;步幅:2;滤波器大小:(3,3)

OH=\frac{7+2*0-3}{2}+1=3

OW=\frac{7+2*0*3}{2}+1=3

例3 输入大小:(28,31);填充:2;步幅:3;滤波器大小:(5,5)

OH=\frac{28+2*2-5}{3}+1=10

OW=\frac{28+2*2-5}{3}+1=10

如这些例子所示,通过在式(7.1)中代入值,就可以计算输出大小。这 里需要注意的是,虽然只要代入值就可以计算输出大小,但是所设定的值必 须使式(7.1)中的和分别可以除尽。当输出大小无法 除尽时(结果是小数时),需要采取报错等对策。顺便说一下,根据深度学习 的框架的不同,当值无法除尽时,有时会向最接近的整数四舍五入,不进行报错而继续运行。

http://www.xdnf.cn/news/985537.html

相关文章:

  • 基于C++实现(控制台)小学算数自测系统
  • ateⅹⅰt()的用法
  • DD3118完整版参数规格书|DD3118 3.0读卡器控制方案|DD3118高速3.0读卡器芯片
  • 【数据采集+人形机器人】使用 Apple Vision Pro 对宇树(Unitree)G1 和 H1 人形机器人进行全身的遥操作控制
  • RAG 处理流程
  • Linux内核学习资料-deepseek
  • AIGC 基础篇 Python基础 05 元组,集合与字典
  • 45. Jump Game II
  • OPenCV CUDA模块图形变换----构建透视变换映射表函数buildWarpPerspectiveMaps()
  • AUTOSAR实战教程--DoIP_03_ 代码分析与调用栈观测(ISOLAR版)
  • 详解多模态
  • 项目制造型企业如何实现高效管理?从金属工具制造说起
  • 【LeetCode 热题 100】只出现一次的数字 / 多数元素 / 颜色分类 / 寻找重复数
  • 建造者模式(Builder Pattern)
  • 设计模式-组合模式
  • Ubuntu20.04更新Cmake版本
  • 找到字符串中所有字母异位词
  • 使用 PyTorch 和 TensorBoard 实时可视化模型训练
  • SpringBoot学习day1-SpringBoot的简介与搭建
  • Phthon3 学习记录-0611
  • Windows 删除文件出现错误代码0x80070570:文件或目录损坏且无法读取
  • 第五章网络管理
  • vibe coding 2025工具全景图
  • 构建高效开发节奏:我的IDEA休息提醒插件实践
  • fastadmin自动保存格式datetime
  • JavaEE-SpringBoot
  • 基于SpringBoot实现的课程答疑系统设计与实现【源码+文档】
  • 【MySQL数据库 | 第四篇】 数据类型+DDL表操作1
  • 从零开始了解数据采集技术篇(2)——如何提高数据采集的精度与速度
  • ALIGN_COMMA_ENABLE参数