卷积神经网络(一)---原理和结构

news2024/11/19 8:25:56

        在介绍卷积神经网络之前,先提出三个观点,正是这三个观点使得卷积神经网络能够真正起作用。

1. 局部性

        对于一张图片而言,需要检测图片中的特征来决定图片的类别,通常情况下这些特征都不是由整张图片决定的,而是由一些局部的区域决定的。

        比如图4.1中的鸟喙,该特征只存在于图片的局部中。

2. 相同性 

        对于不同的图片,如果它们具有同样的特征,这些特征会出现在图片不同的位置也就是说可以用同样的检测模式去检测不同图片的相同特征,只不过这些特征处于图片中不同的位置,但是特征检测所做的操作几乎一样。

        图4.2中两张图片的鸟喙处于不同的位置,但是可以用相同的检测模式去检测。

3. 不变性

        对于一张大图片,如果我们进行下采样,那么图片的性质基本保持不变。

        图4.3经过下采样还是能够看出来是一张鸟的图片。

        上面的三个性质分别对应着卷积神经网络中的三种思想,接下来介绍网络的层结构。 

        卷积神经网络和一般的全连接神经网络是相似的,也是由一些神经元构成的,如图4.4所示。这些神经元中有着需要学习的参数,通过网络输入,最后输出结果,通过损失函数来优化网络中的参数。卷积神经网络与其不同之处在于网络的层结构是不同的。图4.4是全连接神经网络,由一系列隐藏层构成,每个隐藏层由若干个神经元构成,其中每个神经元都和前一层的所有神经元相关联,但是每一层中的神经元是相互独立的。

        这样的神经网络在处理图片上存在什么问题呢?比如在MNIST数据集上,图片大小是 28x28,那么第一个隐藏层的单个神经元的权重数目就是28x28=784,这似乎还不是特别大,但这只是一张小图片,且是灰度图。对于一张较大的图片而言,比如200x200x3,就会导致权重数目是200x200x3=120000,如果设置几个隐藏层中的神经元数目,就会导致参数增加特别快。其实这样的图片在现实中并不算大图片,所以全连接神经网络对于处理图像并不是一个好的选择。 

        图4.5所示的是卷积神经网络的处理过程,不同于一般的全连接神经网络,卷积神经网络是一个3D容量的神经元,也就是说神经元是以三个维度来排列的:宽度、高度和深度。比如输入的图片是32x32x3,那么这张图片的宽度就是32,高度也是32,深度是3。后面会详细地介绍卷积神经网络是如何计算的,以及为什么它被这样设计并取得如此好的效果。 

        卷积神经网络中的主要层结构有三个:卷积层、池化层和全连接层,通过堆叠这些层结构形成了一个完整的卷积神经网络结构。卷积神经网络将原始图片转化成最后的类别得分,其中一些层包含参数,一些层没有包含参数,比如卷积层和全连接层拥有参数,而激活层和池化层不含参数。这些参数通过梯度下降法来更新,最后使得模型尽可能正确地识别出图片类别。

        接下来具体介绍每一种层的连接方式和它们的超参数。

卷积层

        卷积层是卷积神经网络的核心,大多数计算都是在卷积层中进行的。

1. 概述

        首先介绍卷积神经网络的参数。这些参数是由一些可学习的滤波器集合构成的,每个滤波器在空间上(宽度和高度)都比较小,但是深度和输入数据的深度保持一致。举例来说,卷积神经网络的第一层卷积一个典型的滤波器的尺寸可以是5x5x3(宽和高都是5),或者是3x3x3(宽和高都是3),这里的宽度和高度可以任意定义,但是深度必须是3,因为深度要和输入一致,而输入的图片是3通道的。在前向传播的时候,让每个滤波器都在输入数据的宽度和高度上滑动(卷积),然后计算整个滤波器和输入数据任意一处的内积。 

        当滤波器沿着输入数据的宽度和高度滑动时,会生成一个二维的激活图,激活图上的每个空间位置表示了原图片对于该滤波器的反应。直观来看,网络会让滤波器学习到当它看到某些类型的视觉特征的时候就激活,具体的视觉特征可以是边界、颜色轮廓、甚至可以是网络更高层上的蜂巢状或者车轮状图案。

        在每个卷积层上,会有一整个集合的滤波器,比如20个,这样就会形成20张二维的、不同的激活图,将这些激活图在深度方向上层叠起来就形成了卷积层的输出。

        如果用大脑和生物神经元做比喻,那么输出的3D数据中的每个数据都可以看成是神经元的一个输出,而该神经元只是观察输入数据中的一种特征,并且和空间上左右两边的所有神经元共享参数(因为这些输出都是使用同一个滤波器得到的结果)。下面介绍卷积神经网络中的神经元连接,它们在空间中的排列,以及它们参数共享的模式。

2. 局部连接

        在处理图像这样高维度输入的时候,让每个神经元都与它那一层中的所有神经元进行全连接是不现实的。相反,让每个神经元只与输入数据的一个局部区域连接是可行的,为什么可以这样做呢?其实这是因为图片特征的局部性,所以只需要通过局部就能提取出相应的特征。

        与神经元连接的空间大小叫做神经元的感受野(receptivefeld),它的大小是一个人为设置的超参数,这其实就是滤波器的宽和高。在深度方向上,其大小总是和输入的深度相等。最后强调一下,对待空间维度(宽和高)和深度维度是不同的,连接在空间上是局部的,但是在深度上总是和输人的数据深度保持一致

        图4.6形象地展示了感受野在空间和深度上的大小,左边表示输入的数据,中间是感受野,右边每个小圆点表示一个神经元。下面举一个具体的例子来说明一下。比如输入的数据尺寸为32x32x3,如果感受野(滤波器尺寸)是5x5,卷积层中每个神经元会有输入数据中5x5x3区域的权重,一共5x5x3=75个权重。这里再次强调感受野深度的大小必须是3,和输入数据保持一致。比如输入数据体尺寸是16x16x20感受野是3x3,卷积层中每个神经元和输入数据体之间就有3x3x20=180个连接这里的深度必须是20,和输入数据一致。

3. 空间排列 

        前面介绍了每个神经元只需要与输入数据的局部区域相连接,但是没有介绍卷积层中神经元的数量和它们的排列方式、输出深度、滑动步长,以及边界填充控制着卷积层的空间排布。

        首先,卷积层的输出深度是一个超参数,它与使用的滤波器数量一致,每种滤波器所做的就是在输入数据中寻找一种特征。比如说输入一张原始图片,卷积层输出的深度是20,这说明有20个滤波器对数据进行处理,每种滤波器寻找一种特征进行激活。

        其次,在滑动滤波器的时候,必须指定步长。比如步长为1,说明滤波器每次移动1个像素点。当步长为2的时候,滤波器会滑动2个像素点。滑动的操作会使得输出的数据在空间上变得更小。

        最后介绍边界填充,可以将输入数据用0在边界进行填充,这里将0填充的尺寸作为一个超参数,有一个好处就是,可以控制输出数据在空间上的尺寸,最常用来保证输入和输出在空间上尺寸一致。

        输出的尺寸到底是多少呢?其实可以用一个公式来计算,就是\frac{W-F+2P}{S}+1,其中W表示输入的数据大小,F表示卷积层中神经元的感受野尺寸,S表示步长,P表示边界填充0的数量。比如输入是7x7、滤波器是3x3,步长是1,填充的数量是0。那么根据公式,就能得到\frac{7-3+2*0}{1}+1=5,即输出的空间大小是5x5,如果步长是2,那么 \frac{7-3+2*0}{2} + 1 = 3,输出的空间大小就是3x3。可以用图 4.7所示的这个一维的例子来具体说明。

        右上角表示神经网络的权重,其中输入数据的大小为5,感受野的大小为3;左边表示滑动步长为1,且填充也为1;右边表示滑动步长为2,填充为1。

4. 零填充的使用 

        从上面的例子中,我们看到输入的维度是5,输出的维度也是5。之所以如此,是因为感受野是3,并且使用了1的零填充。如果不使用零填充,那么输出数据的维度也就只有3,因为\frac{5-3+2*0}{1}+1=3。一般来说,当步长S=1时,零填充的值为P=\frac{F-1}{2},这样就能够保证输入的数据和输出的数据具有相同的空间尺寸。

5. 步长的限制

        通过上面的公式我们知道步长的选择是有所限制的,举例来说,当输入尺寸 W=10 的时候,如果不使用零填充,即 P=0,滤波器尺寸 F=3,这样步长 S=2 就行不通,因为\frac{10-3+0}{2}+1=4.5,结果不是一个整数,这就说明神经元不能整齐对称地滑过输入数据体,这样的超参数设置是无效的,使用 PyTorch 的时候就会报错,可以使用零填充让设置变得合理。在后面卷积神经网络的结构设计中,需要合理地设计网络的尺寸,使得所有维度都能够正常工作,这件事并没有看上去那么容易。

6. 参数共享

        在卷积层使用参数共享可以有效地减少参数的个数,这样之所以能够行得通,是因为之前介绍的特征的相同性,也就是说相同的滤波器能够检测出不同位置的相同特征。比如说一个卷积层的输出是20x20x32,那么其中神经元的个数就是 20x20x32=12800,如果窗口大小是3x3、而输入的数据体深度是10,那么每个神经元就有3x3x10=900个参数,这样合起来就有12800x900=11520000个参数,单单一层卷积就有这么多参数,这样运算速度显然是特别慢的。

        根据之前介绍的,一个滤波器检测出一个空间位置\left ( x_{1}, y_{1} \right )处的特征,那么也能够有效检测出\left ( x_{2},y_{2} \right )位置的特征,所以就可以用相同的滤波器来检测相同的特征,基于这个假设,我们就能够有效减少参数个数。比如上面这个例子,一共有32个滤波器这使得输出体的厚度是32、每个滤波器的参数为3x3x10=900,总共的参数就有32x900=28800个,极大减少了参数的个数。

        由参数共享我们知道输出体数据在深度切片上所有的权重都使用同一个权重向量,那么卷积层在向前传播的过程中,每个深度切片都可以看成是神经元的权重对输入数据体做卷积,这也就是为什么要把这些3D的权重集合称为滤波器,或者卷积核。

        需要注意的是,参数共享之所以能够有效,是因为一个特征在不同位置的表现是相同的,比如一个滤波器检测到了水平边界这个特征,那么这个特征具有平移不变性所以在其他位置也能够检测出来。但是有时候这样的假设可能是没有意义的,特别是当卷积神经网络的输入图像呈现的是一些明确的中心结构的时候,希望在图片的不同位置学习到不同的特征。一个具体的例子就是人脸识别,人脸一般位于图片的中心,我们希望不同的特征能够在不同的位置被学习到,比如眼睛特征或者头发特征,正是由于这些特征在不同的地方,才能够对人脸进行识别。

7. 总结

        最后总结一下卷积层的一些性质。

  1. 输入数据体的尺寸是W_{1}*H_{1}*D_{1}
  2. 4个超参数:滤波器数量K,滤波器空间尺寸F,滑动步长S,零填充的数量P
  3. 输出数据体的尺寸为W_{2}*H_{2}*D_{2},其中W_{2}=\frac{W_{1}-F+2P}{S}+1, H_{2}=\frac{H_{1}-F+2P}{S}+1, D_{2}=K
  4. 由于参数共享,每个滤波器包含的权重数目为F*F*D_{1},卷积层一共有F*F*D_{1}*K个权重和K个偏置
  5. 在输出体数据中,第d个深度切片(空间尺寸是W_{2}*H_{2}),用第d个滤波器和输入数据进行有效卷积运算的结果,再加上第d个偏置

        对于卷积神经网络的一些超参数,常见的设置是F=3,S=1,P=1,同时这些超参数也有一些约定俗成的惯例和经验,在之后的章节会介绍。

池化层

        上一部分介绍完卷积神经网络中最核心的内容——卷积层,下面来介绍一下第二种层结构——池化层。

        通常会在卷积层之间周期性插入一个池化层,其作用是逐渐降低数据体的空间尺寸,这样就能够减少网络中参数的数量,减少计算资源耗费,同时也能够有效地控制过拟合。

        下面先来介绍到底什么是池化层。池化层和卷积层一样也有一个空间窗口,通常采用的是取这些窗口中的最大值作为输出结果,然后不断滑动窗口,对输入数据体每个深度切片单独处理,减少它的空间尺寸,如图4.8所示。

        从图4.8能够看出池化层能够有效降低数据体空间的大小,图4.9形象地说明了窗口大小是2,滑动步长是2的最大值池化是如何计算的:每次都从2x2的窗口中选择最大的数值,同时每次滑动2个步长进入新的窗口。

        池化层之所以有效,是因为之前介绍的图片特征具有不变性,也就是通过下采样不会丢失图片拥有的特征,由于这种特性,我们可以将图片缩小再进行卷积处理,这样能够大大降低卷积运算的时间。

        最常用的池化层形式是尺寸为2x2的窗口,滑动步长为2,对图像进行下采样将其中75%的激活信息都丢掉,选择其中最大的保留下来,这其实是因为我们希望能够更加激活里面的数值大的特征,去除一些噪声信息。

        池化层有一些和卷积层类似的性质。

  1. 输入数据体的尺寸是W_{1}*H_{1}*D_{1}
  2. 有两个需要设置的超参数,空间大小F和滑动步长S
  3. 输出数据体的尺寸是W_{2}*H_{2}*D_{2},其中W_{2}=\frac{W_{1}-F}{S}+1H_{2}=\frac{H_{1}-F}{S}+1D_{2}=D_{1}
  4. 对输入进行固定函数的计算,没有参数引入
  5. 池化层中很少引入零填充

        在实际中,有两种方式:一种是F=3,S=2,这种池化有重叠;另外更常用的一种是F=2,S=2,一般来说应该谨慎使用比较大的池化窗口,以免对网络有破坏性。 

        除了最大值池化之外,还有一些其他的池化函数,比如平均池化,或者L2范数池化。在实际中证明,在卷积层之间引入最大池化的效果是最好的,而平均池化一般放在卷积神经网络的最后一层。

全连接层

        全连接层和之前介绍的一般的神经网络的结构是一样的,每个神经元与前一层所有的神经元全部连接,而卷积神经网络只和输入数据中的一个局部区域连接,并且输出的神经元每个深度切片共享参数。

        一般经过了一系列的卷积层和池化层之后,提取出图片的特征图,比如说特征图的大小是3x3x512,这个时候,将特征图中的所有神经元变成全连接层的样子,直观上也就是将一个3D的立方体重新排列,变成一个全连接层,里面有3x3x512=4608个神经元,再经过几个隐藏层,最后输出结果。

        在这个过程中为了防止过拟合会引入Dropout。最近的研究表明,在进入全连接层之前,使用全局平均池化能够有效地降低过拟合。

卷积神经网络的基本形式

        卷积神经网络中通常是由上面介绍的三种层结构所构成,上一章还介绍过引入激活函数增加模型的非线性,所以卷积神经网络最常见的形式就是将一些卷积层和ReLU层放在一起,有可能在ReLU层前面加上批标准化层,随后紧跟着池化层,再不断重复,直到图像在空间上被缩小到一个足够小的尺寸,然后将特征图展开,连接几层全连接层,最后输出结果,比如分类评分等。

        图4.10就是一种卷积神经网络的基本形式。

1. 小滤波器的有效性

        一般而言,几个小滤波器卷积层的组合比一个大滤波器卷积层要好,比如层层堆叠了3个3x3的卷积层,中间含有非线性激活层,在这种排列下面,第一个卷积层中每个神经元对输入数据的感受野是3x3,第二层卷积层对第一层卷积层的感受野也是3x3,这样对于输入数据的感受野就是5x5,同样,第三层卷积层上对第二层卷积层的感受野是3x3,这样第三层卷积层对于第一层输入数据的感受野就是7x7。

        假设这里不使用3个3x3的感受野,直接单独使用一个7x7大小的卷积层,那么所有神经元的感受野也是7x7,但是这样会有一些缺点。多个卷积层首先与非线性激活层交替的结构,比单一卷积层的结构更能提取出深层的特征;其次,假设输入数据体的深度是C,输出体的深度也是C,那么单独的7x7的卷积层会有7*7*C*C=49*C^2的参数个数,而使用3个3x3的卷积层的组合,仅仅含有3*\left ( 3*3*C*C \right ) = 27*C^2的参数。直观来说,选择小滤波器的卷积组合能够对输入数据表达出更有力的特征,同时使用参数也更少。唯一的不足是反向传播更新参数的时候,中间的卷积层可能会占用更多的内存。

2. 网络的尺寸

        对于卷积神经网络的尺寸设计,没有严格的数学证明,这是根据经验制定出来的规则。

  1. 输入层:一般而言,输入层的大小应该能够被2整除很多次,常用的数字包括32,64,96 和 224。
  2. 卷积层:卷积层应该尽可能使用小尺寸的滤波器,比如3x3或者5x5,滑动步长取1。还有一点就是需要对输入数据体进行零填充,这样可以有效地保证卷积层不会改变输入数据体的空间尺寸。如果必须要使用更大的滤波器尺寸,比如7x7,通常用在第一个面对原始图像的卷积层上。
  3. 池化层:池化层负责对输入的数据空间维度进行下采样,常用的设置使用2x2的感受野做最大值池化,滑动步长取2。另外一个不常用的设置是使用3x3的感受野步长设置为2。一般而言池化层的感受野大小很少超过3,因为这样会使得池化过程过于激烈,造成信息的丢失,这通常会造成算法的性能变差。
  4. 零填充:零填充的使用可以让卷积层的输入和输出在空间上的维度保持一致除此之外,如果不使用零填充,那么数据体的尺寸就会略微减少,在不断进行卷积的过程中,图像的边缘信息会过快地损失掉。

        上面介绍了卷积神经网络中最重要的三种层结构:卷积层、池化层和全连接层,下面会介绍每一种层结构在PyTorch中是如何实现的。

        

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

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

相关文章

暑期集训周报三

题解 SMU Summer 2024 Contest Round 8-CSDN博客 CSDN 积累题目 dp 1.花店橱窗 思路:用dp[i][j]表示第i个放在j位置上的最大价值,那么我们可以枚举i-1被放在了区间[i-1,j-1]的那个位置,找到最大价值部分,然后更新dp[i][j]&a…

gitee的远程连接与公钥SSH的连接

目录 1. 登录注册gitee1.1 登录注册1.2 创建仓库 2. 远程连接3. 公钥连接4. 参考链接 1. 登录注册gitee 1.1 登录注册 gitee官网 进入后进行登录注册 1.2 创建仓库 2. 远程连接 在你想要上传文件的文件夹中进行git初始化(我在其他文章已经写过,链接…

FastAPI(七十六)实战开发《在线课程学习系统》接口开发-- 课程详情

源码见:"fastapi_study_road-learning_system_online_courses: fastapi框架实战之--在线课程学习系统" 这个接口用户可以不登录,因为我们的课程随意浏览 那么我们梳理下这里的逻辑 1.根据课程id判断课程是否存在 2.课程需要返回课程的详情 3…

X-AnyLabeling标注软件使用方法

第一步 下载 官方X-AnyLabeling下载地址 github:X-AnyLabeling 第二步 配置环境 使用conda创建新的虚拟环境 conda create -n xanylabel python3.8进入环境 conda activate xanylabel进入X-AnyLabeling文件夹内,运行下面内容 依赖文件系统环境运行环…

【把玩数据结构】详解队列

目录 队列介绍队列概念队列的结构生活中的队列 队列的实现队列的初始化队列的销毁队尾入队列队头出队列获得队头元素获得队尾元素统计队列元素个数 队列介绍 队列概念 队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表。队列遵…

Python 代码中的 yield 到底是什么鬼?

在Python编程中,有一个强大而神秘的关键字,那就是yield。初学者常常被它搞得晕头转向,而高级开发者则借助它实现高效的代码。到底yield是什么?它又是如何在Python代码中发挥作用的呢?让我们一起来揭开它的面纱。 Pyth…

Chrome浏览器设置暗黑模式 - 护眼模式 - 亮度调节 - DarkReader - 地址栏和书签栏设置为黑色背景

效果图 全黑 浅灰 (DarkReader设置开启亮色亮度-25) 全白 前言 主要分两部分需要操作, 1)地址栏和书签栏 》 需要修改浏览器的外观模式 2)页面主体 》 需要安装darkreader插件进行设置 步骤 1)地址栏和…

Unity UGUI 实战学习笔记(3)

仅作学习,不做任何商业用途 不是源码,不是源码! 是我通过"照虎画猫"写的,可能有些小修改 不提供素材,所以应该不算是盗版资源,侵权删 拼UI 提示面板的逻辑 using System.Collections; using System.Col…

加密溢出问题

今天编写程序,使用一个非常简单的对256取模的运算,但是总是得不到正确的结果。 后来发现,是数据的值的范围问题。 例如,处理图像时,值的范围是【0,255】. 异或等等运算都是没有问题的。 但是,如果进行加法…

websocket通信问题排查思路

websocket通信问题排查思路 一、websocket连接成功,但数据完全推不过来。 通过抓包发现,是回包时间太长超过了1分钟导致的。这种通常是推送数据的线程有问题导致的。 正常抓包的情况如下: 二、大量数据可以正常推送成功,不定时…

C++从入门到起飞之——内存管理(万字详解) 全方位剖析!

🌈个人主页:秋风起,再归来~🔥系列专栏:C从入门到起飞 🔖克心守己,律己则安 目录 1. C/C内存分布 2. C语言中动态内存管理方式:malloc/calloc/realloc/free 3. C内存管理…

AI大模型大厂面试真题:「2024大厂大模型技术岗内部面试题+答案」

AI大模型岗的大厂门槛又降低了!实在太缺人了,大模型岗位真的强烈建议各位多投提前批,▶️众所周知,2025届秋招提前批已经打响,🙋在这里真心建议大家6月7月一定要多投提前批! 💻我们…

数字音频工作站(DAW)软件FL Studio 24.1.1.4234中文版

在数字化音乐制作的浪潮中,FL Studio 24.1.1.4234的发布无疑又掀起了一股新的热潮。这款由Image-Line公司开发的数字音频工作站(DAW)软件,以其强大的功能和易用的界面,赢得了全球无数音乐制作人的青睐。本文将深入探讨…

git cherry-pick用法

git cherry-pick 如何将我另一个分支上的某个提交合并到新的分支上 首先切换到新分支上git cherry-pick <commit_hash>例如&#xff1a;git cherry-pick f8a70c9

Linux--Socket编程TCP

前文&#xff1a;Socket套接字编程 TCP的特点 面向连接&#xff1a;TCP 在发送数据之前&#xff0c;必须先建立连接。可靠性&#xff1a;TCP 提供了数据传输的可靠性。面向字节流&#xff1a;TCP 是一个面向字节流的协议&#xff0c;这意味着 TCP 将应用程序交下来的数据看成是…

简单的数据结构:栈

1.栈的基本概念 1.1栈的定义 栈是一种线性表&#xff0c;只能在一端进行数据的插入或删除&#xff0c;可以用数组或链表来实现&#xff0c;这里以数组为例进行说明 栈顶 &#xff1a;数据出入的那一端&#xff0c;通常用Top表示 栈底 :相对于栈顶的另一端&#xff0c;也是固…

【无标题】shell脚本的基本命令+编写shell脚本

shell脚本 一.shell基础 1.shell概念 2.shell脚本 3.shell脚本编写注意事项 二.编写shell脚本 1.编写一个helloworld脚本&#xff0c;运行脚本 [rootshell ~]# vim helloworld.sh #!/bin/bash //声明 echo "hello world!" ls -lh /etc/ 运行脚本(四种方式)&…

react版本判断是否面包含

react-admin: react版本 import { useState,useEffect } from react import ./Secene.css import { Checkbox } from "antd"; import* as turf from turf/turf; import type { CheckboxProps } from antd; // const onChange: CheckboxProps[onChange] (e) >…