深度学习--卷积神经网络CNN
考虑到篇幅问题和实际用途进行精简,只选取个人觉得值得一说的部分
本章节代码未放全,但实测可跑,详见官网
参考
CNN笔记:通俗理解卷积神经网络
Convolutional Neural Networks (CNNs / ConvNets)
卷积神经网络 (CNN) 基本原理和公式
零基础入门深度学习(4) - 卷积神经网络
深度学习:卷积神经网络中的卷积核
最容易理解的对卷积(convolution)的解释
【DL笔记6】从此明白了卷积神经网络(CNN)
在 CNN 中,为什么要逐渐增加特征图的通道数?
机器学习算法之——卷积神经网络(CNN)原理讲解
卷积神经网络(convolutional neural network,CNN)
将空间不变性(spatial invariance)的这一概念系统化,从而基于这个模型使用较少的参数来学习有用的表示。
- 平移不变性(translation invariance):不管检测对象出现在图像中的哪个位置,神经网络的前面几层应该对相同的图像区域具有相似的反应,即为“平移不变性”。
- 局部性(locality):神经网络的前面几层应该只探索输入图像中的局部区域,而不过度在意图像中相隔较远区域的关系,这就是“局部性”原则。最终,可以聚合这些局部特征,以在整个图像级别进行预测。
平移不变性(translation invariance)
现在引用上述的第一个原则:平移不变性。
这意味着检测对象在输入 $\mathbf{X}$ 中的平移,应该仅导致隐藏表示 $\mathbf{H}$ 中的平移。
也就是说,**$\mathbf{V}$** 和 $\mathbf{U}$ 实际上不依赖于 $X(i,j)$ 的位置,即
$$
V_{i,j,a,b} = V_{a,b}.
$$
并且 $\mathbf{U}$ 是一个常数,比如 $u$。
因此,我们可以简化 $\mathbf{H}$ 定义为:
$$
[H]{i,j} = u + \sum_a \sum_b [V]{a,b} [X]_{i+a, j+b}.
$$
这就是卷积(convolution)。
我们使用系数 $[V]{a,b}$ 对位置 $(i,j)$ 附近的像素 $[X]{i+a,j+b}$ 进行加权得到 $[H]_{i,j}$。
注意,$[V]{a,b}$ 的系数比 $[V]{i,j,a,b}$ 少很多,因为前者不再依赖于图像中的位置。这是显著的进步!
局部性(locality)
引用上述的第二个原则:局部性。
如上所述,为了收集用来训练参数 $[H]_{i,j}$ 的相关信息,我们不应偏离到距 $(i,j)$ 很远的地方。这意味着在
$$
|a| > \Delta \quad \text{或} \quad |b| > \Delta
$$
的范围之外,我们可以设置
$$
[V]_{a,b} = 0.
$$
因此,我们可以将 $[H]_{i,j}$ 重写为:
$$
[H]{i,j} = u + \sum{a=-\Delta}^{\Delta} \sum_{b=-\Delta}^{\Delta} [V]{a,b} [X]{i+a, j+b}.
$$
简而言之,是一个卷积层(convolutional layer),而卷积神经网络是包含卷积层的一类特殊神经网络。在深度学习研究社区中,**$V$** 被称为卷积核(convolution kernel)或者滤波器(filter),亦或简单称为该卷积层的权重,通常是可学习的参数。
当图像处理的局部区域很小时,卷积神经网络与多层感知机的训练差异可能巨大:以前多层感知机可能需要数十亿个参数来表示网络中的一层,而现在卷积神经网络通常只需几百个参数,而且不需要改变输入或隐藏表示的维数。
参数大幅减少的代价是,我们的特征现在是平移不变的,并且每个隐藏活性值确定时,每层只包含局部信息。以上所有权重学习都依赖归纳偏置。当偏置与现实相符时,我们能得到样本有效的模型,并能很好泛化;若偏置与现实不符(比如图像不满足平移不变性),模型可能难以拟合训练数据。
卷积
在进一步讨论前,先简要回顾为什么该操作称为卷积。
数学中,两个函数(比如 $f, g: \mathbb{R}^d \to \mathbb{R}$)的卷积定义为:
$$
(f * g)(\mathbf{x}) = \int f(\mathbf{z}) , g(\mathbf{x} - \mathbf{z}) , d\mathbf{z}.
$$
也就是说,卷积是在把一个函数“翻转”并平移 $\mathbf{x}$ 时,测量 $f$ 和 $g$ 之间的重叠。
离散情况下,积分变成求和。例如,对于索引为 $\mathbb{Z}$ 的平方可和无限维向量,我们有:
$$
(f * g)(i) = \sum_a f(a) , g(i - a).
$$
二维张量的卷积定义为:
$$
(f * g)(i,j) = \sum_a \sum_b f(a,b) , g(i - a, j - b).
$$
这看起来类似于
$$
Y_{i,j} = \sum_{a,b} W_{a,b} , X_{i+a, j+b},
$$
但有个主要区别:这里用的是索引差值 $(i - a, j - b)$,而不是 $(i + a, j + b)$。
这种区别是表面的。
我们在中的定义更准确地描述了互相关(cross-correlation)。
通道
这种方法有一个问题:我们忽略了图像一般包含三个通道(红、绿、蓝)。
实际上,图像是一个三维张量,比如尺寸为 $1024 \times 1024 \times 3$,其中前两个轴是空间位置,第三个轴是颜色通道。
因此,将张量 $X$ 索引为:
$$
X[i,j,k].
$$
对应地,卷积权重张量扩展为四维:
$$
V[a,b,c,d].
$$
此外,输入图像是三维的,隐藏表示 $H$ 也最好用三维张量表示:对每个空间位置采用一组隐藏表示(多个通道)。可以把隐藏表示想象为多个二维张量堆叠而成的通道(channel),也称为特征映射(feature maps)。
直观上,底层通道可能专注于边缘检测,其他通道检测纹理等。
多通道卷积层可表示为:
$$
H[i,j,d] = \sum_{a=-\Delta}^\Delta \sum_{b=-\Delta}^\Delta \sum_c V[a,b,c,d] \cdot X[i+a,j+b,c].
$$
其中隐藏表示 $H$ 中的索引 $d$ 是输出通道,输出继续作为三维张量输入下一卷积层。
定义了多通道卷积层,$V$ 是该层权重。
互相关运算
严格来说,卷积层是个错误的叫法,因为它所表达的运算其实是互相关运算(cross-correlation),而不是卷积运算。
感受野(Receptive Field)
神经网络中神经元“看到的”输入区域,在卷积神经网络中,feature map上某个元素的计算受输入图像上某个区域的影响,这个区域即该元素的感受野。感受野是个相对概念,某层feature map上的元素看到前面不同层上的区域范围是不同的,通常在不特殊指定的情况下,感受野指的是看到输入图像上的区域。
卷积核大小(Kernel size)
常用大小为 3×3、5×5,有时也用 1×1(用于通道变换和升维降维)。较小卷积核组合层数可以实现更大感受野,且参数更少。
汇聚层与卷积层的区别与作用总结
降维(减少空间尺寸),从而减少后续计算量和参数规模,提高模型对平移和微小变形的鲁棒性,助于防止过拟合,增强模型的泛化能力。
通过局部汇聚(最大池化或平均池化)提取局部显著信息,虽然会丢失部分细节,但保留最重要的特征。
卷积层(Convolutional Layer)与汇聚层的对比
方面 | 卷积层 | 汇聚层 |
---|---|---|
参数 | 可训练的卷积核参数 | 无参数,固定的聚合操作 |
主要功能 | 特征提取和变换 | 降维与特征汇聚 |
降维方式 | 通过步长(stride)和填充(padding)调整输出尺寸 | 通过池化窗口大小和步长缩小空间尺寸 |
信息保留 | 保留更多细节和复杂特征 | 牺牲部分细节,保留局部显著特征 |
计算复杂度 | 相对较高 | 较低 |
对模型鲁棒性的影响 | 依赖卷积核设计和训练 | 提高对平移、小变形的鲁棒性 |
总结
从信息保留角度看,卷积层保留更多特征细节,且具有学习能力。
汇聚层主要用于降低空间维度和计算成本,并增强模型对输入变换的鲁棒性。两者在卷积神经网络中常常配合使用,互为补充。
图像卷积
卷积神经网络(convolutional neural network)是含有卷积层(convolutional layer)的神经网络。
基于图像的空间局部相关性假设——邻近像素更相关,局部特征更有意义。
conv 是 convolution(卷积) 的缩写,卷积是一个滑动窗口求加权和的过程。
互相关运算
卷积层得名于卷积(convolution)运算,但我们通常在卷积层中使用更加直观的互相关(cross-correlation)运算。在二维卷积层中,一个二维输入数组和一个二维核(kernel)数组通过互相关运算输出一个二维数组。
在二维互相关运算中,卷积窗口从输入数组的最左上方开始,按从左往右、从上往下的顺序,依次在输入数组上滑动。当卷积窗口滑动到某一位置时,窗口中的输入子数组与核数组按元素相乘并求和,得到输出数组中相应位置的元素。
1 | import torch |
卷积层
卷积层将输入和卷积核做互相关运算,并加上一个标量偏差来得到输出。卷积层的模型参数包括了卷积核和标量偏差。在训练模型的时候,通常我们先对卷积核随机初始化,然后不断迭代卷积核和偏差。
1 | # 继承 nn.Module,Conv2D 是一个神经网络模块 |
学习卷积核
卷积核也称为滤波器(Filter)。
1 | # 构造二维卷积层,(输出通道,输入通道,卷积核形状,是否使用偏置) |
特征映射和感受野
卷积层有时被称为特征映射(feature map),因为它可以被视为一个输入映射到下一层的空间维度的转换器。 在卷积神经网络中,对于某一层的任意元素
,其感受野(receptive field)是指在前向传播期间可能影响
计算的所有元素(来自所有先前层)。
填充(padding)和步幅(stride)
填充
填充(padding):在输入图像的边界填充元素(通常填充元素是0)
填充0并不能还原边缘的信息,而是让边缘能被卷积核覆盖到,不是恢复边缘,而是通过训练去拟合边缘区域应该如何处理。
卷积不降维控制特征图的空间维度(H × W)变化策略能保持特征图大小不变(对于残差连接、对齐输出特征很重要),逐层控制感受野增长速度(稳定局部特征提取速度),预防过快地降维(避免剧烈的信息损失)
填充0虽然不直接增加感受野,但通过保持尺寸不变与多层卷积堆叠,能让更深层的卷积核感受到更大范围的输入区域。
CNN强调从细节到语义的渐进式建构,而不是突变式压缩。逐步丢弃是必须的,快速丢弃是有害的。
- 低层特征是高层语义的基础,图像语义的形成是逐层抽象的过程,如果低层细节在前几层就被池化或卷积快速抹去,那么深层根本没机会学习“从边缘->形状->物体”的演化路径。
- 很多任务需要细节,图像分割、图像修复、关键点检测等任务对局部精度要求极高。
- 梯度传播与训练稳定性,太快压缩特征图尺寸,会导致梯度传回路径过窄,信息瓶颈造成特征通道表达受限,导致训练困难。
卷积神经网络中卷积核的高度和宽度通常为奇数,例如1、3、5或7。 选择奇数的好处是,保持空间维度的同时,我们可以在顶部和底部填充相同数量的行,在左侧和右侧填充相同数量的列。
此外,使用奇数的核大小和填充大小也提供了书写上的便利。对于任何二维张量X,当满足: 1. 卷积核的大小是奇数; 2. 所有边的填充行数和列数相同; 3. 输出与输入具有相同高度和宽度 则可以得出:输出Y[i, j]是通过以输入X[i, j]为中心,与卷积核进行互相关计算得到的。
1 | import torch |
当卷积核的高度和宽度不同时,可以填充不同的高度和宽度,使输出和输入具有相同的高度和宽度。
1 | # kernel_size高5宽3,padding表示上下两边各填充2行零左右两边各填充1行零,padding可选,nn.Conv2d本质传入还是4D |
步幅(Stride)
在卷积操作中,stride 是卷积核在输入特征图上滑动时每一步移动的像素数
有时候为了高效计算或是缩减采样次数,卷积窗口可以跳过中间位置,每次滑动多个元素。将每次滑动元素的数量称为步幅(stride)。
1 | # 卷积层 |
多输入多输出通道
添加通道时,我们的输入和隐藏的表示都变成了三维张量。
多输入通道
当输入包含多个通道时,需要构造一个与输入数据具有相同输入通道数的卷积核,以便与输入数据进行互相关运算。
1 | import torch |
多输出通道
随着神经网络层数的加深,我们常会增加输出通道的维数,通过减少空间分辨率以获得更大的通道深度。直观地说,我们可以将每个通道看作对不同特征的响应。
1 | def corr2d_multi_in_out(X, K): |
1X1卷积层
看起来似乎没有多大意义。毕竟,卷积的本质是有效提取相邻像素间的相关特征,而1X1卷积显然没有此作用。尽管如此,仍然十分流行,经常包含在复杂深层网络的设计中。
总之就是展平为线性回归算了,不用考虑那么多
1 | def corr2d_multi_in_out_1x1(X, K): |
汇聚层
通常处理图像时,希望逐渐降低隐藏表示的空间分辨率、聚集信息,这样随着我们在神经网络中层叠的上升,每个神经元对其敏感的感受野(输入)就越大。
汇聚(pooling)层,它具有双重目的:降低卷积层对位置的敏感性,同时降低对空间降采样表示的敏感性。
最大汇聚层和平均汇聚层
池化是 CNN 中的一种空间汇聚操作。池化又叫下采样(Dwon sampling), 与之相对的是上采样(Up sampling). 卷积得到的特征图一般需要一个池化层以降低数据量
与卷积层类似,汇聚层运算符由一个固定形状的窗口组成,该窗口根据其步幅大小在输入的所有区域上滑动,为固定形状窗口(有时称为汇聚窗口)遍历的每个位置计算一个输出。 然而,不同于卷积层中的输入与卷积核之间的互相关计算,汇聚层不包含参数。 相反,池运算是确定性的,我们通常计算汇聚窗口中所有元素的最大值或平均值。这些操作分别称为最大汇聚层(maximum pooling)和平均汇聚层(average pooling)。
1 | import torch |
填充和步幅
汇聚层也可以改变输出形状。
1 | X = torch.arange(16, dtype=torch.float32).reshape((1, 1, 4, 4)) |
多个通道
在处理多通道输入数据时,汇聚层在每个输入通道上单独运算,而不是像卷积层一样在通道上对输入进行汇总。 这意味着汇聚层的输出通道数与输入通道数相同。
1 | X = torch.cat((X, X + 1), 1) # 拼接 |
卷积神经网络(LeNet)
LeNet
LeNet(LeNet-5)由两个部分组成:
卷积编码器:由两个卷积层组成;
全连接层密集块:由三个全连接层组成。
为了将卷积块的输出传递给稠密块,我们必须在小批量中展平每个样本。换言之,我们将这个四维输入转换成全连接层所期望的二维输入。这里的二维表示的第一个维度索引小批量中的样本,第二个维度给出每个样本的平面向量表示。
在卷积神经网络中,常在若干卷积层后接一个池化层(总体趋势是逐渐降低分辨率,但方式不限于池化),以降低特征图的空间分辨率,从而减少计算量,并增强网络对图像小幅平移、缩放等变换的鲁棒性(不变性)。
权值共享是卷积神经网络(CNN)的一大核心特点。具体来说,每个卷积核(滤波器)在输入特征图上滑动,使用相同的一组权重进行卷积操作。因此,卷积层的参数数量只等于卷积核中权重的总数加上一个偏置项。相比于传统的全连接神经网络(如 BP 网络),这种权值共享机制大幅减少了需要训练的参数数量,从而降低了模型复杂度并有助于防止过拟合。
权值共享让卷积核参数在空间上”全局固定”,即用同一组局部滤波器权重在整个图上滑动,保证网络能高效且一致地捕捉图像中的局部特征。