《hands-on ml》Chapter 14

图像识别任务,如果使用之前的全连接层的话,对于一个100*100像素的图片,那么100个神经元将有1000W个连接,计算代价太大了。而卷积神经网络是如果解决这个问题的呢?

  • 每一层都是仅于部分神经元连接,这也是大脑中视觉皮层的方式,每个神经元仅关注自己的感受野(receptive field)
  • 每一层的权重是共享的,大大减少了权重的数量

CNN还引入了两个新的组件:卷积层(convolutional layers)和池化层(pooling layers)。

卷积层(Convolutional Layers)

相关概念

局部感受野(receptive field)

而在卷积层中,每个神经元只与输入数据的一个小的、局部的区域相连。这个局部的连接区域,就称为该神经元的局部感受野。它是卷积神经网络能够高效处理图像类网格数据的关键设计。它迫使网络首先关注局部特征,并通过层的堆叠来构建全局理解,这非常符合我们理解视觉世界的方式。

比如某一层的神经元位置为(i, j),其连接的上一层的神经元,其位置行范围为[i, i+fh-1],列范围为[j, j+fw-1],fh和fw是局部感受野的高和宽。

卷积核(Kernels,Filters)

卷积核可以理解为一种特征探测器,它是一个小型的权重矩阵(通常是 3×3, 5×5 等),这个矩阵中的权重是在训练过程中学习得到的。

在卷积运算中,卷积核在输入数据(如图像)上滑动。在每一个位置,它都与输入的局部区域进行点积运算,并生成一个数值输出到输出特征图中。

每个卷积核都被设计用来检测输入数据中的特定局部特征,因此某一层的神经元使用相同的卷积核,其输出就组成了一个特征图(feature map)。每个卷积层一般都会有多个特征图。

卷积(Convolution)

严格来说,卷积层的运算,并不是卷积,而是互相关(cross-correlation),或者叫滑动内积。


以2D图像为例,其计算过程如下

y[i,j]=\sum_{m=0}^{f_h-1}\sum_{n=0}^{f_w-1}x[i+m,j+n]\cdot w[m,n]

步长(stride)

步长是卷积或池化操作中的一个超参数,它定义了卷积核在输入数据上每次移动的距离。

  • 当步长为1时,卷积核仅移动一个像素,也是默认的设置,会保留较多的信息
  • 当步长为2时,卷积核每次移动2个像素,会使得输出特征图宽度高度减半。虽然丢失了一些信息,但是提高了计算效率

零填充(zero padding)

有时需要在输入的边缘外围填充一圈(或多圈)值为0的像素,这是因为:

  • 没有零填充,输出的特征图肯定会被缩放,零填充可以保证输出的特征图拥有相同的宽度和高度
  • 如果没有零填充,输入特征图最边缘的像素在卷积过程中被计算的次数远少于中心的像素(例如,角落的像素只参与一次卷积计算),这可能导致边界信息丢失。零填充让边缘像素也能处于卷积核的中心位置,使它们得到更公平的处理。

常见的填充策略有:

  • No padding/Valid padding,不填充,输出特征图会缩放
  • Same padding,会确保输出特征图尺寸相同
  • Full padding,确保每个输入都被卷积相同的次数,做法就是从输入特征图第一个像素的“之外”开始滑动,并一直滑动到最后一个像素的“之外”,这会产生一个比输入尺寸更大的输出特征图。

输出尺寸

对于一个输入尺寸为 W×W 的特征图,使用一个尺寸为 F×F 的卷积核,并以步长 S 进行卷积。如果不进行填充,输出尺寸会缩小为 ((W−F)/S)+1。通过在边缘填充 P 圈零,可以将输出尺寸控制为 ((W−F+2P)/S)+1。


特征图堆叠

前文提到,每个卷积核都会生成一个特征图,特征图上的参数会被所有神经元共享,因此整个模型的参数数量就能得到大大减少。

一个卷积层通常有多个卷积核,每个卷积核都会生成一个独立的特征图。所有这些特征图在深度方向上堆叠起来,就构成了该卷积层的输出。因此,一个卷积层的输出可以被看作一个三维张量:[高度,宽度,通道数],其中通道数就等于该层使用的卷积核数量,也就是特征图的数量。

一个卷积层中某个神经元的输出,其计算公式如下

z_{i,j,k}=b_k+\sum_{u=0}^{f_h-1}\sum_{v=0}^{f_w-1}\sum_{k'=0}^{f_{n'}-1}
x_{i',j',k'} \times w_{u,v,k',k}
\qquad\text{with}
\begin{cases}
i'=i \times s_h + u \\
j'=j \times s_w + v
\end{cases}
  • zi,j,k为卷积层中,特征图k中行i列j的神经元的输出
  • sh和sw是两个方向上的步长
  • fh和fw是局部感受野的高度和宽度,fn’是上一层特征图的数量
  • xi’,j’,k’是上个卷积层对应位置的神经元的输出
  • bk是特征图k的偏置项
  • wu,v,k’,k是特征图k与其输入(k‘特征图上的(u,v)位置)的连接权重

池化层(Pooling Layers)

池化层通常被放置在连续的卷积层之间。它的核心功能是对输入的特征图进行下采样,从而压缩数据。

池化层使用一个滑动窗口(例如 2×2 的窗口),在输入特征图上以特定的步长移动。对于每个窗口覆盖的区域,它执行一种聚合操作。最常见的两种操作是:

  1. 最大池化:选取窗口内的最大值作为输出。
  2. 平均池化:计算窗口内所有值的平均值作为输出。

池化层的主要作用有:

  1. 降低维度,减少计算量:通过下采样,显著减少后续层需要处理的参数数量和计算量,提升模型效率,并控制过拟合。
  2. 扩大感受野:随着数据空间尺寸的缩小,后续卷积层中每个神经元的感受野会相对变大,从而能够融合更广区域的上下文信息。
  3. 保持特征的平移不变性:即使输入特征图发生几个像素的微小平移,池化操作(尤其是最大池化)后的输出也基本保持不变。这使得网络更关注某个特征是否存在,而非其精确位置。
  4. 提取主要特征,增强鲁棒性:最大池化通过保留最显著的特征,有助于网络忽略噪声和微小的位置变化。

卷积神经网络的架构

卷积神经网络,一般都会包含两部分。前半段为卷积层和池化层交错堆叠,后半段再增加传统的神经网络,会包含若干个全连接层,最后输出预测值。

LeNet-5

LeNet-5架构是第一个公开的卷积神经网络,被广泛用于手写体识别。

架构的具体构成如下表所示

类型特征图数大小卷积核步长激活函数
Out全连接层10RBF
F6全连接层84tanh
C5卷积层1201 × 15 × 51tanh
S4平均池化层165 × 52 × 22tanh
C3卷积层1610 × 105 × 51tanh
S2平均池化层614 × 142 × 22tanh
C1卷积层628 × 285 × 51tanh
In输入层132 × 32

AlexNet

之前的架构都是卷积层和池化层交错堆叠,而AlexNet是第一个连续堆叠卷积层的架构,其构成如下表

类型特征图数大小卷积核步长填充激活函数
Out全连接层1000Softmax
F10全连接层4096ReLU
F9全连接层4096ReLU
S8最大池化层2566 × 63 × 32valid
C7卷积层25613 × 133 × 31sameReLU
C6卷积层38413 × 133 × 31sameReLU
C5卷积层38413 × 133 × 31sameReLU
S4最大池化层25613 × 133 × 32valid
C3卷积层25627 × 275 × 51sameReLU
S2最大池化层9627 × 273 × 32valid
C1卷积层9655 × 5511 × 114validReLU
In输入层3(RGB)227 × 227

为了避免过拟合,使用了两个正则化手段

  • 在训练全连接层的时候,使用了50%的dropout
  • 使用了数据增强,让输入图像随机调整角度、亮度、翻转等

此外,在C1和C3的ReLU激活函数之后,还使用了局部响应归一化(Local Response Normalization),其灵感来源于生物神经中,被强烈激活的神经元会抑制其邻近神经元的活性。

LRN会抑制相邻特征图中相同位置的神经元,其公式如下

b_i=a_i(k+\alpha\sum_{j=j_{\text{low}}}^{j_{\text{high}}} {a_j}^2)^{-\beta}
\qquad\text{with }
\begin{cases}
j_{\text{high}}=\min(i+\frac{r}{2},f_n-1) \\
j_{\text{low}}=\max(0,i-\frac{r}{2}) \\
\end{cases}
  • ai为归一化之前的激活函数的输出
  • b为特征图i上某个神经元归一化之后的输出
  • k, α, β, r这些都是超参数,k为偏置参数,r为深度半径
  • fn为特征图的数量

GoogLeNet

GoogLeNet的核心就是一个inception模块,其核心思想就是:在同一个层级上,让网络能够并行地、自主地选择不同尺度的特征,这与传统依次堆叠卷积层的串行结构形成了鲜明对比。

inception模块的架构如下图所示:

在Inception模块中,并行地应用 1×1、3×3、5×5 卷积核以及一个 3×3 最大池化层,然后将所有输出在通道维度上拼接起来,这样做的好处就是:

  • 多尺度特征提取:网络在每一层都能同时捕捉到不同范围的上下文信息。1×1 卷积关注极局部特征,3×3 卷积关注中等区域模式,5×5 卷积则能捕捉更大范围的特征。池化操作则增强了特征的平移不变性
  • 密集表示:通过拼接操作,输出的特征图变得非常“稠密”,包含了多种不同抽象层次的信息,为下一层提供了更丰富的特征基础。

至于为什么会有 1×1 的卷积核,这是因为:

  • 1×1 卷积作为一个 “瓶颈层”,极大地降低了后续更大卷积核的计算量,使得构建更深的网络成为可能。因此这里起到了降维,以及节省计算成本的作用。
  • 虽然局部感受野很小,但是可以实现跨通道的的信息整合。对多个通道的信息进行线性组合,实现高效的特征变换。

ResNet(Residual Network

退化问题(Degradation Problem)

在 ResNet 出现之前,深度学习界有一个共识:网络越深,性能越好。因为更深的网络可以学习更复杂、更抽象的特征。

然而,实践发现,当网络深度超过某个点(例如 20 层)后,会遇到一个严峻的问题:更深的网络反而表现更差,如下图所示:

残差学习(residual learning)

当训练一个神经网络的时候,我们需要让网络来找到目标函数h(x)。而如果我们将输入x直接加到神经网络的输出(这种也称作跳跃连接,skip connections),那么网络的目标函数就变成了f(x)=h(x)-x,这个就是残差学习,如下图所示。残差学习使得构建和训练极深网络(如 ResNet-152,甚至1000层以上的网络)成为可能。

当我们初始化一个常规神经网络时,其权重初始值接近零,因此网络初始输出值也接近于零。但若引入跳跃连接,形成的网络初始阶段会直接复制其输入——换言之,它最初模拟的是恒等函数(identity function)。如果目标函数与恒等函数非常接近(这种情况十分常见,比如在图像去噪中,目标是去除噪声,但干净图像的大部分内容就是输入图像本身),这种机制将显著加速训练过程。

为什么残差学习如此有效呢?主要是因为:

a. 简化学习目标,实现“恒等映射”

对于深层网络,如果一个模块是多余的,那么最优解就是恒等映射,即 h(x)=x

  • 在传统网络中:让一堆非线性层去拟合恒等映射 h(x)=x 是非常困难的。
  • 在残差网络中:只需要让残差函数 f(x) 学习到 0 即可(权重置为0)。即 f(x)=0,则 h(x)=f(x)+x=x

b. 彻底缓解梯度消失问题

在反向传播过程中,由于链式法则,会出现梯度消失的问题,导致浅层权重无法更新。而由于残差学习中的跳跃连接,会避免梯度消失的问题。比如计算损失函数L对于输入x的梯度

\begin{align*}
\frac{\partial{L}}{\partial{x}} &= \frac{\partial{L}}{\partial{h(x)}}  \times
\frac{\partial{h(x)}}{\partial{x}}  \\
&=
 \frac{\partial{L}}{\partial{h(x)}}  \times
(\frac{\partial{f(x)}}{\partial{x}} + 1)
\end{align*}

即使主路径的梯度很小,由于这个1的存在,确保了训练信号能够有效地到达网络的每一个角落,即使是最浅的层也能迅速得到更新,从而极大地加速了整个网络的收敛过程。

残差单元(residual units)

整个ResNet就是很多个残差单元堆叠组成的,其基本的结构就是:卷积 -> 归一化 -> ReLU -> 卷积 -> 归一化,最后执行跳跃连接和ReLU激活。


SENet(Squeeze-and-Excitation Networks)

SENet是2017年ImageNet图像分类竞赛的冠军模型,通过显式建模特征通道之间的相互依赖关系来提升网络性能。它提出了“特征重标定”策略,通过学习自动获取每个特征通道的重要程度,从而增强有用特征并抑制不重要的特征。

通道的重要性

在SENet出现之前,主流的CNN架构(如ResNet、Inception)主要专注于如何在空间维度(高度和宽度)上提取更强大的特征,例如使用不同大小的卷积核来捕捉多尺度信息。

然而,卷积层在通道维度上通常只是进行简单的线性聚合,缺乏对通道关系进行非线性建模的能力。网络很难自适应地理解不同通道特征的重要性差异。SENet正是为了解决这个问题而诞生的。

SE模块

SENet的核心就是SE模块,其具有即插即用的特性,可以嵌入到几乎任何主流的CNN架构中,从而创造出SE-ResNet、SE-Inception等变体,如下图所示

SE模块的主要操作有以下几步:

  • Squeeze(压缩):通过全局平均池化,将每个通道的特征图压缩成1个值。
  • Excitation(激励):通过两个全连接层,学习通道之间的非线性关系,并生成每个通道的权重用来表达其重要性
  • Recalibration(重新校准):将通道的权重逐项乘回原有的特征图,增强有用特征并抑制不重要特征

SE模块的架构

一个SE模块主要有三部分组成,一个全局平均池化层,以及两个全连接层:一个使用ReLU激活函数的隐藏层,一个sigmoid激活函数的输出层。

比如输入为256个特征图,经过全局平均池化层后,变为了256个值,每个值代表了该特征图的平均激活值。接下来就会经过“瓶颈”神经网络的处理:

  • 第一个全连接层充当了降维的作用,将通道数缩小到256/r r 是缩减比率,如16)。这大大减少了参数量和计算成本,并增强了非线性。
  • 第二个全连接层充当升维的作用,将通道数恢复到256,使用sigmoid激活函数,将输出控制在[0,1]

由于使用了降维和较小的全连接层,SE模块增加的参数量和计算量非常少(通常在2%以下),但带来的性能提升却非常显著。

发表评论