深度解析卷积神经网络(CNN):从像素到模型的完整指南
编辑本文是一篇关于卷积神经网络(CNN)的综合性技术教程。文章从传统神经网络处理图像的局限性出发,系统性地阐述了CNN的设计哲学——归纳偏置。通过将卷积操作类比为滑动内积,深入剖析了其模式匹配的数学本质。文章逐层递进,详细介绍了从一维到多维、从单通道到多通道的卷积过程,以及填充、步长、池化、激活函数等核心组件的作用。最后,文章揭示了CNN的学习引擎——自动微分与反向传播,并解释了为何反向传播是训练深度模型的标准选择。本文旨在为读者提供一个从零开始、全面且深刻的CNN知识体系。
图像的数字表示
本节介绍图像在计算机中是如何存储的,并将其拓展到在深度学习中图像的一般表示方式。
像素:图像的基本构成
在计算机中,图像是由一组像素(Pixel)所组成的,像素是组成数字图像的最小单位。每张图像都有以下三种属性:
- 大小:图像的大小由其高度和宽度所描述,单位可以为厘米、英寸或者像素等。
- 色彩空间:可以采用不同的色彩空间来描述颜色。常用的有RGB色彩空间,通过其基色的线性组合可生成各种颜色。
- 通道:这是色彩空间的一项属性,可以理解为颜色线性空间中的基底,基底的个数即为通道数。例如RGB色彩空间具有三种基本颜色(即基底)RGB,即红色、绿色和蓝色。通过这三种颜色的线性组合,可生成各种各样的颜色,下图即为RGB色彩空间的示意图:
为了能够显示各种颜色,就需要像素能够存储彩色信息。对于RGB色彩空间,常见的是各通道均采用一个字节(即8bit)来存储像素的颜色值,共24bit来存储像素的所有RGB色彩值。由于每个通道(即颜色基)只用8bit来存储,共可存储2^8 = 256个状态。例如,对于红色(R通道),0表示在给定像素中无红色,255表示在给定像素中强度最高(或可理解为红色占比为100%),对于其他通道同理。
上述内容是对图像在计算机中的表示的基本介绍,更加详细的请查阅参考资料:What is a Pixel? - GeeksforGeeks。
张量:深度学习中的图像语言
在深度学习中,图像一般表示为一个NumPy
数组,维度一般是3维,包括图片大小和通道数量等属性。此外,如果是批量处理的话,会引入一个图像数量的维度。这时的NumPy
数组一般称为张量(Tensors)。例如:
# [sample_number, height, width, channel_number]
[3, 28, 28, 3]
表示的就是3张图片所构成的列表,每张图片的宽和高均为28像素,采用的是3通道的色彩空间。该通道数量排在最后的表示方式称为Channel-last约定。需要注意的是:不是所有的表示方式都会采用Channel-Last约定。因此,在调用别人的数据集时,务必要确定其数据编码格式后再进行下一步操作。
卷积神经网络(CNN)的核心思想
现给定图像中物体识别和分类的任务,即从图像识别出目标物体,例如从图像中识别出宠物狗。如何构建一个神经网络来完成上述任务?传统的前馈神经网络(Feed-forward Neural Networks,FNNs)虽然可以完成上述任务,但是会存在有以下问题:
- FNNs是全连接神经网络(Fully-connected Neural Networks, FCNNs),若采用FNN完成图像物体识别任务,其对图像中目标物体位置敏感。为正确识别目标物体,需要各个位置均有目标物体的图像作为数据集,进而对于数据量的需求较高。若数据量较小,很容易过拟合(Overfitting)
- 对于图像规模较大时的FNN参数量巨大,学习时所需要的算法时间复杂度和空间复杂度会变的不可承受。
基于此,需要设计一个新的网络架构,来高效的完成图像物体识别和分类任务,这一个新的神经网络被称为卷积神经网络(Convolutional Neural Networks, CNNs)。
归纳偏置:CNN的“设计哲学”
为高效识别目标物体和降低学习和存储成本,可利用先验知识来指导设计网络结构,这些假设被称为归纳偏置(Inductive Bias)。归纳偏置指的是存在一组假设,以指导神经网络结构的设计,使其学习倾向于符合假设的解决方案。归纳偏置可类比为优化问题中的约束条件,以保证优化问题的解决方案从可行域中选择。
对图像中的目标物体进行观察与统计,可归纳出以下两点:
- 目标物体可以出现在图像中的任意位置;
- 由若干局部像素点聚集在一起形成目标物体图像,即邻近的像素点是相关的(称为局部性)
从上述两个先验结论中,可归纳出:
- 设计的网络结构对于输入(即图像)数据应位置不敏感,即无论输入如何平移变化,均不影响目标物体的识别结果;
- 可在任意位置,对重复出现的局部像素点模式进行提取,且提取出的特征应该保持不变,即输入的数据平移,则对应的特征也进行同样的平移操作。
归纳出的这两个要点分别被称为平移不变性(Translation Invariance)和平移等变性(Translation Equivalence),其中平移不变性为希望最终设计的神经网络涌现出来的特性。
为了实现平移不变性,做出以下两点基本假设:
- 局部性
- 平移等变性
在有了上述两点归纳偏置后,需在设计网络架构时,尽可能保证学习到的模型满足归纳偏置。
卷积:CNN的基石
从一维卷积理解核心原理
为了简化问题却又不失一般性,现假设输入信号/图像为一维有限数组,该数组可采用向量的形式表示,记作\pmb x = [x_1, x_2, \cdots, x_N]^\top。现需要“特征提取器”,从输入向量中提取特定像素聚集的模式,记特征提取器为\pmb u,其长度在定义网络结构时预先指定,需满足不等式1 \le \dim(\pmb u) \le N。
由于目标物体可能出现在图像中的任意位置,则特定模式也可能出现在图像中的任意位置。因此,为保证不重不漏,特征提取器需“扫描”输入信号的所有位置。\pmb u扫描输入向量\pmb x的过程可被视为模式匹配的过程,其每一次匹配的计算结果的全体所构成的数组(或矩阵)称为特征图。
在当前的问题设定中(即输入信号和特征提取器均为1维的情况),模式匹配其实就是在做相似度检测。根据线性代数中的知识可知,可采用内积运算(Inner Product)检测两个向量的相似程度。根据Cauchy-Schwartz不等式:
可知,当输入信号\pmb x中的片段与\pmb u的相似程度越高,其匹配的计算结果(即响应程度)越大。由于模式匹配过程中需要扫过整个输入信号\pmb x,因此在一维的情况下,其做的是滑动内积操作。将特征图记作G,令M \doteq \dim(\pmb u),则滑动内积操作可被描述为下式:
该式又被称为互相关/互协方差(Cross-Correlation)。由于是对每一个位置均进行模式匹配,因此当输入信号中发生了平移,提取到的特征图相应的也会发生同样的平移,这保证了平移等变性。
二维卷积:在图像上滑动
现将问题拓展为输入信号是二维单通道情况,假设输入图片的宽和高均相等,则一张二维图片可被表示为矩阵F \in \mathbb{R}^{n\times n}。与此同时,特征提取器也由一维向量扩展为二维向量H \in \mathbb{R}^{m \times m},其维度需满足不等式1 \le m \le n。
在物体识别任务中,图像被表示为了矩阵的形式,因此该矩阵也被称为数据矩阵。 为检测输入信号中是否包含特定模式,需要将一维的向量内积拓展为矩阵内积的形式,使其能够具有向量内积的性质,而这个矩阵内积操作就是Frobenius矩阵内积。对于两个同形状的矩阵A, B,其Frobenius矩阵内积定义为下式:
Frobenius内积也满足Cauchy-Schwartz不等式,即:
因此,当输入信号与特征提取器的模式匹配程度越高时,该区域的响应值(即Frobenius内积)的值则越大。同理,特征提取器需“扫描”输入信号的所有位置,因此计算的是滑动Frobenius矩阵内积。假设位置[i, j]表示的是矩阵第i行第j列的索引,则滑动Frobenius矩阵内积可表示为下式:
即互相关在二维情况下的计算公式。此外,为增强模型的表达能力,会增加一个偏置项b,该偏置项的作用是给特征图提供一个整体的偏移。需注意的是对于一个输出特征图,所有的位置共享同一个偏置项 b。此时,互相关特征图的计算公式可拓展为下式:
需注意的是,互相关运算不满足交换律,即不对称。为了满足对称性,引入卷积运算_convolution1。对于离散变量,卷积运算的定义如下:
其中特征模式矩阵H被称为卷积核(Convolutional Kernel)。同理,可以增加偏置项b增加模型的表达能力,进而卷积运算可以拓展为下式:
卷积与互相关的计算过程唯一区别是,卷积运算先将卷积核H进行翻转翻180度后(即二维的卷积先将卷积核进行对角的翻转),再滑动顺序计算。此外,由于卷积运算的索引计算采用的是减法的形式,因此可能会存在负数索引的情况,其并不是代表访问索引为负值的物理内存,而是代表的相对位置。假设卷积核的中心元素所在位置被定义为原点(即[0, 0]),则[-1, 0]位于该元素的正上方,[-1, -1]位于该元素的左上角。
出现负数索引的情况的原因是当卷积核H的原点位于数据矩阵F的左上角位置。此时,就会出现负数索引。这种情况反应的是下述问题:当卷积核的中心对准输入数据的边缘或角落时,那些超出输入边界的卷积核部分应该和什么值进行计算?
为了解决该问题,引入了填充(Padding)的概念,例如使用0元素填充的方式,将输入数据矩阵F的边缘填充为0,这样可保证卷积核超出输入数据矩阵F的边界部分不影响计算结果。此外,填充技术还可以调整特征图的大小。假设每次滑动一个元素,为防止卷积核超出输入边界需在输入数据矩阵F的四周分别填充了p行和p列0元素,则获得的特征图的大小为:
如果计算结果不是整数,通常会进行向下取整。此外,在实践中,人们通常会用两个术语来概括填充策略:
VALID
填充: 指的是不进行任何填充 (p=0
)。在这种模式下,卷积核只能在输入图像的“有效”区域内移动,输出的特征图尺寸会小于输入尺寸。SAME
填充: 指的是通过计算,自动在输入周围填充适量的0,使得当步长s=1
时,输出特征图的尺寸与输入特征图的尺寸保持相同。这在设计深层网络时非常方便,可以避免特征图尺寸在传递过程中迅速缩小。
与此同时,当卷积核的大小m \ll n时,特征图的数量可能多大,因此引入滑动步长(Strides),以减少特征图的数量。令步长为s\ge 1(s \in \mathbb{Z}),则此时每一个特征图的大小计算公式为下式:
需要特别注意的是:在深度学习框架中,将多维度的互相关称为卷积运算。原因是深度学习中的卷积核中的参数的具体取值是通过学习得到的,由于梯度下降法和误差反向传播的作用,即使采用标准卷积运算,先180度反转卷积核再滑动计算的结果,与不反转直接采用互相关公式计算的最终结果是一致的。在这种情况下,在保证最终结果一致的前提下,省略了180度翻转卷积核的操作,计算更加简便。因此在深度学习框架中,采用互相关实现卷积运算。
多通道卷积:处理彩色图像
最后,对于输入信号为二维多通道(例如 C_{in} 个通道)的情况,其卷积过程更为复杂。此时,卷积核也必须具有相同的通道数 C_{in}。运算时,卷积核的每个通道与输入数据对应的通道分别进行二维互相关运算,然后将得到的 C_{in} 个结果逐元素相加,最终合并成一个单通道的输出特征图。
池化层:降维与增强不变性
为进一步降低存储空间,以及进一步削弱位置敏感性,采用池化(Pooling),即下采样(Down Sampling)操作将特征图的维度降低,常用的池化有最大值池化和平均值池化等。池化操作的目的是忽略相对不重要的信号/信息,保留最重要的信号/信息。
具体而言,将特征图均分成若干子块,若采用的是最大池化,则对每一个子块取最大值填充到对应位置的池化后的特征图中;若采用的是平均值池化,则对每一个子块取均值后填充到池化后的特征图中。当池化前,平移后的最大信号所在位置未超过其原先位置所在的池化子块时,其并不会影响池化后的结果,在一定程度上去除了位置敏感。
需要注意的是,下采样出的值不是学习出来的。
从零到一:构建完整的CNN架构
目前为止,通过卷积运算共享参数的特性,在解决了多通道模式匹配问题,降低了神经网络的要学习的参数数量。此外,通过池化操作,在降低了位置敏感性的同时进一步降低了参数的数量。但是最终的目标是识别物体任务,因此需要将其建模为多分类任务。为此,需将提取好的高维特征图展开(Flatten)成一个向量,并通过FNN获得最终的类别线性倾向性(即logits),通过softmax归一化后,得到最终的类别概率分布,具体的神经网络架构如下图所示_of_CNN2:
需要注意的是:在池化层之前,需将卷积后的特征图通过激活函数,得到激活特征图。为缓解梯度消失(Gradient Vanishing)的问题,将激活函数从sigmoid函数替换为了ReLU(Rectified Linear Unit,线性整流单元)。
由于卷积运算本质上是一种线性运算,如果仅仅是线性操作的堆叠,那么整个网络无论多深,最终也只能表达线性关系。虽然池化操作在一定程度上引入了非线性,由于线性操作占了绝大多数,有限的池化操作所引入的非线性影响较小。为了让网络能够学习和表示更加复杂的非线性特征(这也是现实世界中绝大多数模式的本质),必须在卷积层之后引入非线性的激活函数(如ReLU)。
有很多优秀的参考资料直观的展示了CNN的工作过程和原理,例如:3D Visualization of a Convolutional Neural Network以及 CNN Explainer,读者若想直观的观察CNN的整体工作流程,可以查阅上述两个参考资料。
引擎揭秘:自动微分与反向传播
计算CNN的误差传播递推公式较为复杂,若对手动推导感兴趣可参考资料CNN BackPropagation - CMU。由于很多情况下,人工神经网络手动推导递推公式是十分复杂的,为解决这个问题,引入了自动微分(autograd)框架来自动计算节点的梯度。
自动微分的基础是求导的链式法则,应用链式法则可以将复杂的求导拆开为若干个容易子问题的解,通过减而治之的方式解决复杂的原始问题。假设\pmb x, \pmb w \in \mathbb{R}^n, y \in \mathbb R,求函数z = (\left<\pmb x, \pmb w\right> - y)^2计算\frac{\partial z}{\partial \pmb w}的导数。首先,可通过换元法,令:
将上述求导问题分解为三个子部分,利用求导的链式法则,可得:
进而有:
上述过程可以将其表示为一个计算图,如下所示:
这一个计算图本质上其实就是一个有向无环图(Directed Acyclic Graph,DAG),该图由节点和边构成,每个节点代表了一次计算,每条有向边代表了一个输入。构建计算图的流程是首先将数学公式先展开,分解为若干个操作子,即图中的a, b, z等;然后再将这些操作子按照计算顺序将计算表示成一个DAG。
有了上述计算图之后,即可自动计算导数。利用链式法则计算导数有两种方式,分别是正向累计和反向传播。由于乘法的结合律不改变计算乘法的计算结果,因此两种方式得到的导数其实是一致的。该描述可以被描述为下式:
即:正向累计先计算最内层的导数,反向传播先计算最外层的导数。
自动微分的反向传播需要用到前向传播执行图的计算结果。因此,在计算反向传播之前,需先进行前向传播,存储中间计算结果;然后,从相反方向执行图,利用链式法则逐步计算对应计算节点的导数,此过程中可以忽略无需计算导数的分支(即剪枝操作)。自动微分的计算时间复杂度为O(N),空间复杂度也为O(N),其中N为操作子个数。
为什么深度学习几乎无一例外地使用反向传播,而不是正向累计?正向模式和反向模式的计算量本身是相似的,但它们在处理不同类型的计算任务时,效率天差地别。这取决于输入的数量和输出的数量,具体对比如下表所示:
正向累计(Forward Mode) | 反向传播(Reverse Mode) | |
---|---|---|
核心 | 计算的是“一个输入变化”对“所有输出”的影响 | 计算的是“所有输入变化”对“一个输出”的影响 |
效率 | 一次正向传播,可以计算出最终输出对某一个输入参数的偏导数。如果要计算损失函数 L 对 N 个参数(w_1, w_2, ..., w_N)的全部偏导数,就需要执行 N 次正向传播。 | 一次前向传播 + 一次反向传播,就可以计算出某一个输出(通常是最终的标量损失 L)对所有输入参数(w_1, w_2, ..., w_N)的偏导数 |
适用场景 | 当输入少、输出多时高效 | 当输入多、输出少时极其高效 |
一个典型的神经网络,其参数(输入)数量极其庞大(可达数百万甚至数十亿),而最终的损失函数(输出)通常只有一个标量值。在这种“多输入,单输出”的场景下,反向传播的优势是压倒性的。它只需要一次完整的往返(forward + backward pass)就能得到损失对所有参数的梯度,而正向模式则需要进行数百万次传播。这正是反向传播成为训练神经网络事实标准的核心原因。
- 0
-
分享