经典卷积神经网络
经典卷积神经网络
Acacia_Ma卷积神经网络
- 卷积神经网络
convolutional neural network:CNN
:是指那些至少在网络的某一层中使用了卷积运算来代替一般的矩阵乘法运算的神经网络。 - 卷积神经网络专门处理具有类似网格结构的数据的神经网络。如:时间序列是一维网格,图像数据是二维网格。
一、卷积运算
1.1 数学卷积
1.1.1 卷积定义
示例:一个激光传感器输出$ x(t)$, 表示宇宙飞船在时刻 t 的位置的观测结果。假设传感器包含噪声,则$ x(t) $与飞船在时刻 t 的真实位置有偏离。
可以利用观测结果的均值来估计飞船的位置。假设越近的观测结果越相关,于是对最近的观测结果赋予更高的权重。
令 $w(a)$ 为权重函数,其中 a 表示观测结果距离当前时刻的间隔,则得到时刻 t 飞船真实位置的估计:
$s(t)=\int x(a)w(t-a)da$
这种运算就称作卷积
convolution
,用符号星号$ s(t)=(x*w)(t) $表示。理论上 $w(\cdot) $可以为任意的实值函数,但是在这个示例中要求:
- $w(\cdot) $是个有效的概率密度函数,否则 s(t) 就不是一个加权平均。
- $w(\cdot)$ 在自变量为负数时,取值为零。否则涉及到未来函数,因为激光传感器只能输出 t 时刻之前的观测结果。
通常当计算机处理数据时,连续的数据会被离散化,因此时间 t 只能取离散值。
假设$ x(\cdot),w(\cdot)$ 都是定义在整数时刻 t 上,则得到离散形式的卷积:
$s(t)=(x*w)(t)=\sum_{a=-\infty}^{a=\infty}x(a)w(t-a)$
实际操作中,因为只能存储有限的数据,所以这些函数的值在有限的点之外均为零。因此无限级数的求和最终是有限级数的求和。
在卷积神经网络中,函数$ x(\cdot)$ 称作输入,函数 $w(\cdot)$ 称作核函数,输出有时被称作特征图
feature map
。可以对多个维度进行卷积运算。
如果二维图像$ \mathbf I$ 作为输入,则需要使用二维核函数$ \mathbf K$,卷积运算的输出为:
$\mathbf S(i,j)=(\mathbf I*\mathbf K)(i,j)=\sum_m\sum_n\mathbf I(m,n)\mathbf K(i-m,j-n)$
其中 (m,n) 表示二维图像$ \mathbf I $的像素点的坐标,$\mathbf I(m,n) $表示该坐标处的像素值。
通常$ \mathbf I $的尺寸较大,如 $\mathbf I\in \mathbb R^{100\times 200}$ ;而$ \mathbf K$ 的尺寸较小,如$ \mathbf K\in \mathbb R^{5\times 5}$
因为卷积是可交换的,所以可以等价写作:
$\mathbf S(i,j)=(\mathbf I*\mathbf K)(i,j)=\sum_m\sum_n\mathbf I(i-m,j-n)\mathbf K(m,n)$
这称作翻转
flip
了核。卷积的可交换性在数学证明中有用,但是在神经网络中很少使用。
1.1.2 数学卷积与矩阵乘法
离散卷积可以视作输入矩阵与一个特殊的核矩阵的乘法。
对于一维的离散卷积,核矩阵的每一行必须和上一行移动一个元素后相等。
这种类型的矩阵叫做
Toeplitz
矩阵。对于二维的离散卷积,核矩阵对应着一个双重块循环矩阵。
该矩阵大部分元素相等,且非常稀疏(几乎所有元素都为零)。
卷积运算可以转换成矩阵乘法,所以不需要对神经网络库的实现作出大的修改。
1.1.2.1 一维卷积和矩阵乘法
循环矩阵的定义:
$\mathbf C=\begin{bmatrix}c0&c{n-1}&\cdots&c_2&c_1\c_1&c_0&\cdots&c_3&c_2\ \vdots&\vdots&\ddots&\vdots&\vdots\ c{n-1}&c{n-2}&\cdots&c_1&c_0\end{bmatrix}$
可以利用循环矩阵求一维卷积。
假设有两个长度分别为 M 和 N 的序列 x(i) 和 w(i), 则一维卷积为:
$s(i)=x(i)*w(i)=\sum_{j}x(j)w(i-j)$
卷积的长度为 L=M+N-1。
- 首先用 0 扩充序列 x,w:
$x_p(i)=\begin{cases}x(i)&,0\le i\le M-1\ 0&, M-1\lt i\le L-1\end{cases}$
$w_p(i)=\begin{cases}w(i)&,0\le i\le N-1\ 0&, N-1\lt i\le L-1\end{cases}$
由于用 w 取卷积 x,因此构造 w 的循环矩阵:
$\mathbf W=\begin{bmatrix}w_p(0)&w_p(L-1)&w_p(L-2)&\cdots&w_p(1)\ w_p(1)&w_p(0)&w_p(L-1)&\cdots&w_p(2)\ \vdots&\vdots&\vdots&\ddots&\vdots\ w_p(L-1)&w_p(L-2)&w_p(L-3)&\cdots&w_p(0) \end{bmatrix}$
这里列优先,因此第一列是完全顺序的。
一维卷积为:
$\mathbf{\vec s}=\mathbf W\cdot x_p= \begin{bmatrix}w_p(0)&w_p(L-1)&w_p(L-2)&\cdots&w_p(1)\ w_p(1)&w_p(0)&w_p(L-1)&\cdots&w_p(2)\ \vdots&\vdots&\vdots&\ddots&\vdots\ w_p(L-1)&w_p(L-2)&w_p(L-3)&\cdots&w_p(0) \end{bmatrix}\cdot \begin{bmatrix}x_p(0)\ x_p(1)\ \vdots\ x_p(L-1)\end{bmatrix}$
其中 $\mathbf{\vec s}=(s(0),s(1),\cdots,s(L-1))^T$ 。
1.1.2.2 二维卷积和矩阵乘法
二维卷积:
$\mathbf S(i,j)=(\mathbf I*\mathbf K)(i,j)=\sum_m\sum_n\mathbf I(m,n)\mathbf K(i-m,j-n)$
假设$ \mathbf I\in \mathbb R^{M_I,N_I},\mathbf K\in \mathbb R^{M_K,N_K}$:
$\mathbf I=\begin{bmatrix}I{1,1}&I{1,2}&\cdots&I{1,NI}\ I{2,1}&I{2,2}&\cdots&I{2,NI}\ \vdots&\vdots&\ddots&\vdots\ I{MI,1}&I{MI,2}&\cdots&I{M_I,N_I} \end{bmatrix},\quad \mathbf K=\begin{bmatrix}K{1,1}&K{1,2}&\cdots&K{1,NK}\ K{2,1}&K{2,2}&\cdots&K{2,NK}\ \vdots&\vdots&\ddots&\vdots\ K{MK,1}&K{MK,2}&\cdots&K{M_K,N_K} \end{bmatrix}$
先将 $\mathbf I,\mathbf K$ 扩充到$ M\times N$ 维:$M=M_I+M_K-1,\quad N=N_I+N_K-1\$。扩充之后的新矩阵为 $\mathbf I_p,\mathbf K_p$ 。其中:
$\mathbf Ip=\begin{bmatrix}I{1,1}&I{1,2}&\cdots&I{1,NI}&0&\cdots&0\ I{2,1}&I{2,2}&\cdots&I{2,NI}&0&\cdots&0\ \vdots&\vdots&\ddots&\vdots&0&\cdots&0\ I{MI,1}&I{MI,2}&\cdots&I{MI,N_I}&0&\cdots&0\ 0&0&\cdots&0&0&\cdots&0\ \vdots&\vdots&\ddots&\vdots&\vdots&\ddots&\vdots\ 0&0&\cdots&0&0&\cdots&0\ \end{bmatrix}\ \mathbf K_p=\begin{bmatrix}K{1,1}&K{1,2}&\cdots&K{1,NK}&0&\cdots&0\ K{2,1}&K{2,2}&\cdots&K{2,NK}&0&\cdots&0\ \vdots&\vdots&\ddots&\vdots&0&\cdots&0\ K{MK,1}&K{MK,2}&\cdots&K{M_K,N_K}&0&\cdots&0\ 0&0&\cdots&0&0&\cdots&0\ \vdots&\vdots&\ddots&\vdots&\vdots&\ddots&\vdots\ 0&0&\cdots&0&0&\cdots&0\ \end{bmatrix}$
用 $\mathbf I_p $构造一个列向量$ f_p$ :将$ \mathbf I_p$ 的第一行转置之后将其成为 $f_p $的前 N 个元素;接下来是第二行的转置….第 M 行的转置。
$fp=(I{1,1},I{1,2},\cdots,I{1,NI},0,\cdots,I{MI,1},I{MI,2},\cdots,I{M_I,N_I},0,\cdots)^T$
将$ \mathbf K_p $中的每一行,都按照一维卷积中介绍的循环矩阵生成的方法构成一个 $N\times N $的循环矩阵。这些矩阵记做:$ \mathbf G_1,\mathbf G_2,\cdots \mathbf G_M$ 。
$\mathbf Gm= \begin{bmatrix} K{m,1}&0&\cdots&K{m,2}\ K{m,2}&K{m,1}&\cdots&K{m,3}\ \vdots&\vdots&\ddots&\vdots\ K{m,N_K}&K{m,NK-1}&\cdots&0\ 0&K{m,NK}&\cdots&0\ \vdots&\vdots&\ddots&\vdots\ 0&0&\cdots&K{m,1} \end{bmatrix},\quad m=1,2,\cdots,M$
用这些循环矩阵构造一个大的块循环矩阵:
$\mathbf Gb=\begin{bmatrix}[\mathbf G_1]&[\mathbf G_M]&\cdots& [\mathbf G_2] \ [\mathbf G_2]&[\mathbf G_1]&\cdots &[\mathbf G_3]\ \vdots&\vdots&\ddots&\vdots\ [\mathbf G_M]&[\mathbf G{M-1}]&\cdots&[\mathbf G_1]\end{bmatrix}$
计算: $h_b=\mathbf G_b \cdot f_p $。将$ h_b$ 的结果分配到 $\mathbf S$ 的各行(与构造 $f_p$ 相反的过程),即得到二维卷积。
1.2 神经网络卷积
1.2.1 卷积定义
许多神经网络库会实现一个与卷积有关的函数,称作互相关函数
cross-correlation
。它类似于卷积:$\mathbf S(i,j)=(\mathbf I*\mathbf K)(i,j)=\sum_m\sum_n\mathbf I(i+m,j+n)\mathbf K(m,n)$
有些机器学习库将它称作卷积。事实上在神经网络中,卷积指的就是这个函数(而不是数学意义上的卷积函数)。
神经网络的 2 维卷积的示例:
这里采用的是神经网络中卷积的定义:$\mathbf S(i,j)=(\mathbf I\mathbf K)(i,j)=\sum{m=0}^{1}\sum*{n=0}^{1}\mathbf I(i+m,j+n)\mathbf K(m,n) $。其中,m 和 n 由核函数决定。因为 $\mathbf K\in \mathbb R^{2\times 2}$,所以他们的取值范围是$ [0,2),\quad [0,2)$ 。
单个卷积核只能提取一种类型的特征。
如果希望卷积层能够提取多个特征,则可以并行使用多个卷积核,每个卷积核提取一种特征。我们称输出的
feature map
具有多个通道channel
。feature map
特征图是卷积层的输出的别名,它由多个通道组成,每个通道代表通过卷积提取的某种特征。事实上,当输入为图片或者
feature map
时,池化层、非线性激活层、Batch Normalization
等层的输出也可以称作feature map
。卷积神经网络中,非全连接层、输出层以外的几乎所有层的输出都可以称作feature map
。神经网络中,卷积运算的作用就类似于滤波,因此也称卷积核为
filter
滤波器。滤波器可以从原始的像素特征中抽取某些特征,如:边缘、角度、形状等。
如:
sobel
算子:$\mathbf K_x = \begin{bmatrix} -1&0&+1\ -2&0&+2\ -1&0&+1 \end{bmatrix}\quad \mathbf K_y = \begin{bmatrix} +1&+2&+1\ 0&0&0\ -1&-2&-1 \end{bmatrix}$
其中$ \mathbf K_x $表示检测垂直边缘的滤波器,它沿着水平方向做卷积;$\mathbf K_y $表示检测水平边缘的滤波器,它沿着垂直的方向做卷积。
下图所示为一张原始的灰度图:
经过$ \mathbf K_x $卷积之后:
经过 $\mathbf K_y $卷积之后:
实际上,在卷积神经网络中我们并不会手工设计卷积核,而是通过学习算法自动学得卷积核中每个位置的值。
1.2.2 输入填充
在卷积神经网络中,可以隐式地对输入填充零,使其得到加宽。
如果未填充零,则网络每一层的宽度会逐层递减。根据卷积的性质,网络每一层宽度减少的数量等于卷积核的宽度减 1。
- 如果卷积核尺寸较大,则网络的宽度迅速缩减,这限制了卷积神经网络的网络深度。
- 如果卷积核尺寸较小,则可用的卷积核的数量大幅度降低,这限制了卷积神经网络的表达能力。
对输入 $\mathbf V$ 有三种填充零的方式:
valid
填充、same
填充、full
填充。valid
填充:不使用零来填充输入,卷积核只允许访问那些图像中能完全包含整个核的位置。在
valid
填充模式中,输出的大小在每一层都缩减。假设核的宽度是 k ,则每经过一层,输出的宽度减少了 k-1 。如果输入图像的宽度是 m ,则网络经过了 d 层之后,输出的宽度变成$ m-(k-1)\times d $。如果核的宽度 k 非常大时,缩减非常明显。最终网络会缩减到 1 。
same
填充:使用足够的零来填充,使得输出和输入保持相同的大小。这是最常见的填充方式。在
same
填充模式中,网络可以包含任意多的卷积层,因为它不存在网络输出宽度缩减的问题。same
填充模式的一个问题是:输入的边缘单元可能存在一定程度上的欠表达。因为输入的中间区域的单元的影响域为全部的输出单元,这意味着这些输入单元的信息会被很多输出单元所编码。而输入的边缘区域的单元的影响域只是输出单元的一部分,这意味着这些输入单元的信息仅仅被少量输出单元所编码。
full
填充:在输入的两端各填充 k-1 个零,使得每个输入单元都恰好被卷积核访问 k 次。其中 k 为卷积核的宽度。它将从卷积核和输入开始相交的时候开始做卷积。
假设核的宽度是 k ,则每经过一层,输出的宽度增加了 k-1 。
如果输入图像的宽度是 m ,则网络经过了 d 层之后,输出的宽度变成$ m+(k-1)\times d $。
它使得输入的边缘单元也能够得到充分表达。
full
填充的一个问题是:输出的边界单元依赖于更少的输入单元。这使得学习到的结果在输出的中间部分表现较好,边缘部分的表现较差。
1.2.3 三维卷积
卷积神经网络的输入图片可以是二维(黑白图片),也可以是三维的(彩色图片)。
对于三维彩色图片,一个维度来表示不同的颜色通道(如红绿蓝),另外两个维度表示在每个通道上的空间坐标。
对于三维卷积:
假设输入为张量$ \mathbf V$ ,每个元素是 $V_{i,j,k}$ 。其中:$i $表示输入单元位于$ i $通道,$j,k$ 表示通道中的坐标。
假设输出为张量 $\mathbf Z$ ,每个元素为$ Z_{i,j,k}$ 。其中:$i $表示输出单元位于$ i $通道,$j,k $表示通道中的坐标。
注意:输出的通道数量通常与输入的通道数量不等。
输出有多个通道的原因是:使用了多个卷积核,每个卷积核会输出一个通道。
假设核张量为 4 维的张量 $\mathbf K$ ,每个元素是$ K_{i,l,j,k} $。其中:$i $表示输出单元位于$ i$ 通道,$l $表示输入单元位于$ l $通道,$j,k $表示通道中的坐标。
则三维卷积可以表示为:
$Z{i,j,k}=\suml\sum{m}\sum{n}V{l,j+m,k+n}K{i,l,m,n}$
其中:
- $\sum_m\sum_n$ 遍历了图像平面上的所有坐标。
- $\sum_l $遍历了输入的所有通道。
- $K_{i,:,:,:} $是单个三维卷积的核,多个并行的核的卷积结果组成了输出的多个通道。
上述表述中,张量$ \mathbf V 、 \mathbf Z $的通道索引位于坐标索引之前,这称作通道优先
channel-first
。还有另一种模式:通道索引位于坐标索引之后,这称作
channel-last
。如:
tensorflow
框架采用channel-last
的模式,theano
框架采用channel-first
的模式。这里默认采用channel-last
的方式来描述。
1.2.4 降采样
如果对卷积层的输出进行降采样,则表示跳过图片中的一些位置。
- 优点:可以降低计算开销。因为它降低了卷积层的输出单元数量,也就降低了高层网络的输入单元数量。
- 缺点:提取的特征可能没有那么好,因为跳过的位置可能包含一些关键信息。
假设希望对输出的每个方向上,每隔 s 个像素进行采样,则:
$Z{i,j,k}=\suml\sum{m}\sum{n}V{l,j\times s+m,k\times s+n}K{i,l,m,n}$
这里 s 称作降采样卷积的步幅。
可以对不同的方向定义不同的步幅。
假设 j 方向的步幅为 s_1, k 方向的步幅为 s_2, 则有:
$Z{i,j,k}=\suml\sum{m}\sum{n}V{l,j\times s_1+m,k\times s_2+n}K{i,l,m,n}$
降采样卷积有两种实现形式:
- 通过直接实现步幅为
s
的卷积。 - 先进行完整的卷积,再降采样。这种做法会造成计算上的大量浪费,不建议采用。
- 通过直接实现步幅为
1.2.5 梯度计算
实现卷积神经网络时,为了能够学习模型,必须能够计算核的梯度。
在某些简单情况下,核的梯度可以通过卷积来实现;大多数情况下(如:步幅大于 1 时),核的梯度无法通过卷积来实现。
卷积是一种线性运算,所以可以表示成矩阵乘法形式,涉及的矩阵是卷积核的函数。
该矩阵有两个特性:该矩阵是稀疏的;卷积核的每个元素都复制到该矩阵的很多个位置。
假设要训练一个卷积神经网络,它包含步幅为 s 的步幅卷积,卷积核为$ \mathbf K$ ,作用于多通道的图像 $\mathbf V $。则卷积输出为:
$Z{i,j,k}=\suml\sum{m}\sum{n}V{l,j\times s+m,k\times s+n}K{i,l,m,n}$
假设需要最小化某个损失函数 $J(\mathbf V,\mathbf K)$ ,则:
前向传播过程:计算$ \mathbf Z $,然后将$ \mathbf Z $传递到网络的其余部分来计算 $J $。
反向传播过程:假设得到一个张量$ \mathbf G : G{i,j,k}=\frac{\partial J}{\partial Z{i,j,k}} $。为了训练网络,需要对过滤器的权重求导。
令$ g(\mathbf G,\mathbf V,s){i,l,m,n}=\frac{\partial J}{\partial K{i,l,m,n}} $,则有:
$g(\mathbf G,\mathbf V,s){i,l,m,n}=\frac{\partial J}{\partial K{i,l,m,n}} =\sum{i^\prime}\sum{j}\sum{k}\frac{\partial J}{\partial Z{i^\prime,j,k}}\frac{\partial Z{i^\prime,j,k}}{\partial K{i,l,m,n}}$
根据 $Z_{i^\prime,j,k}$ 的定义,有:
$\frac{\partial Z{i^\prime,j,k}}{\partial K{i,l,m,n}}=\begin{cases} V_{l,j\times s+m,k\times s+n} ,& i^\prime=i\ 0,& i^\prime\ne i \end{cases}$
则有:
$g(\mathbf G,\mathbf V,s){i,l,m,n}=\frac{\partial J}{\partial K{i,l,m,n}}=\sum_j\sum_kG{i,j,k}V{l,j\times s+m,k\times s+n}$
如果该层不是网络的输入层,则需要对 \mathbf V 求梯度来使得误差进一步反向传播。
令$ h(\mathbf K,\mathbf G,s){l,j,k}=\frac{\partial J}{\partial V{l,j,k}}$, 则有:
$h(\mathbf K,\mathbf G,s){l,j,k}=\frac{\partial J}{\partial V{l,j,k}}=\sumi\sum{j^\prime}\sum{k^\prime}\frac{\partial J}{\partial Z{i,j^\prime,k^\prime}} \frac{\partial Z{i,j^\prime,k^\prime}}{\partial V{l,j,k}}$
根据$ Z_{i,j^\prime,k^\prime}$ 的定义,有:
$\frac{\partial Z{i,j^\prime,k^\prime}}{\partial V{l,j,k}}= \sum{\substack{m^\prime\s.t. \; j^\prime\times s+m^\prime=j}}\sum{\substack{n^\prime\s.t.\; k^\prime\times s+n^\prime =k}} K_{i,l,m^\prime,n^\prime}$
则有:
$h(\mathbf K,\mathbf G,s){l,j,k}=\frac{\partial J}{\partial V{l,j,k}} =\sumi\sum{j^\prime}\sum{k^\prime}G{i,j^\prime,k^\prime}\sum{\substack{m^\prime\s.t. \; j^\prime\times s+m^\prime=j}}\sum{\substack{n^\prime\s.t.\; k^\prime\times s+n^\prime =k}} K_{i,l,m^\prime,n^\prime}$
.
二、卷积层、池化层
卷积运算在神经网络中通过卷基层来实现。
对于卷积层的分层有两种观点:
卷积层是由复杂的、三个阶段的子层组成的(如左图所示)。
第一阶段子层:执行卷积运算。
这个阶段是线性变换,其作用是从输入中提取特征。
第二阶段子层:执行非线性的激活函数(如
reLU
单元)。这个阶段是非线性变换,其作用是引入非线性。
实际应用中,这一阶段可以被丢弃,因为第三阶段也可以引入非线性。
第三阶段子层:通过池化函数来调整输出。
这个阶段也是非线性变换,其作用是降低输出的维度,但保留了大部分重要的信息。
卷积层是简单的,仅仅包含卷积运算(如右图所示)。这是目前最流行的观点。
在这个观点中,卷积层、非线性激活层、池化层都是简单的网络层,它们相互配合使用。它们的作用参考前面的三个阶段子层。
2.1 卷积层
- 传统的网络层要求输入的每个样本各维度是固定长度的,卷积层可以处理各维度非固定长度的样本数据,如:输入的图片可以为不同的分辨率。
- 卷积层的卷积运算主要包含了三个重要的思想:稀疏交互
sparse interactions
、参数共享parameter sharing
、等变表示equivariant representation
。
2.1.1 稀疏交互
传统的网络层是全连接的,使用矩阵乘法来建立输入与输出的连接关系。矩阵的每个参数都是独立的,它描述了每个输入单元与输出单元的交互。这意味着每个输出单元与所有的输入单元都产生关联。
卷积层通过使用核矩阵来实现稀疏交互(也称作稀疏连接,或者稀疏权重),每个输出单元仅仅与少量的输入单元产生关联。
这降低了网络的参数和计算量,不仅减少了模型的存储需求,也降低了计算复杂度。
每个输入单元影响的输出单元:
- 对于传统全连接层,每个输入单元影响了所有的输出单元。
- 对于卷积层,每个输入单元只影响了 3 个输出单元(核尺寸为 3 时)。
每个输出单元依赖的输入单元:
- 对于传统全连接层,每个输出单元依赖所有的输入单元。
- 对于卷积层,每个输出单元只依赖 3 个输入单元(核尺寸为 3 时)。
在卷积神经网络中,虽然卷积层每个输出单元只依赖于少量的直接输入单元,但是它可能间接依赖于大部分的间接输入单元。
处在卷积网络更深层的单元,其接受域(即影响它的神经元)要比处在浅层的单元的接受域更大。
2.1.2 参数共享
参数共享:在模型的多个位置使用相同的参数。
- 传统的全连接层中,权重矩阵不同位置处的参数相互独立。
- 卷积层中,同一个核会在输入的不同区域做卷积运算。
- 核函数会在输入的不同区域之间共享,这些区域的大小就是核函数的大小。
- 物理意义:将小的、局部区域上的相同的线性变换(由核函数描述),应用到输入的很多区域上。
卷积运算在存储需求和计算效率方面要大大优于传统网络层的稠密矩阵的乘法运算。
网络参数比较:
- 对于传统全连接层:$ x3\rightarrow s_3$ 的权重$ w{3,3} $只使用了一次 。
- 对于卷积层:$ x3\rightarrow s_3 $的权重 $w{3,3}$被共享到 $x_i\rightarrow s_i,i=1,2,4,5 $。
2.1.3 等变表示
如果一个函数满足:输入发生改变,输出也以同样的方式改变,则称它是等变的
equivariant
。如果函数 $f(x),g(x)$ 满足$ f(g(x))=g(f(x)) $,则称 f(x) 对于变换 g 具有等变性。
对于卷积层,它具有平移等变的性质:如果 g 是输入的任何一个平移函数(如:将图片向右移动一个像素),则下面的两个操作的结果是相同的:
- 先对图片进行卷积之后,再对结果应用平移函数 g
- 先对图片应用平移函数 g ,再对图片进行卷积
因为根据定义有:
$\mathbf S(i,j)=(\mathbf I*\mathbf K)(i,j)=\sum_m\sum_n\mathbf I(i+m,j+n)\mathbf K(m,n)\ \rightarrow \sum_m\sum_n\mathbf I(i+m+\Delta_i,j+n+\Delta_j)\mathbf K(m,n)=\mathbf S(i+\Delta_i,j+\Delta_j)$
例如:
- 当处理时间序列时,如果把输入中的一个事件向后延时,则卷积的输出中也发生相应的延时。
- 当处理图像时,如果平移了输入的图片,则卷积的输出结果也平移了相同的量。
卷积对于某些变换并不是等变的:如缩放变换(改变图像的尺寸)、角度变换(旋转)。
这些非等变的变换需要其它机制来处理(而不是卷积)。
2.2 池化层
池化运算也叫亚采样或者下采样。池化运算用一个矩阵区域内部的某个总体统计量来作为神经网络在该矩阵区域的输出,它综合了该矩阵区域的信息。
- 最大池化:定义一个窗口,并从窗口内取出最大值作为总体统计量。
- 均值池化:定义一个窗口,并从窗口内取出平均值作为总体统计量。
- 其他常见的还有:$ L^{2} $范数以及基于中心像素距离的加权平均函数作为总体统计量。
池化层就是对输入专门执行池化运算的网络层。
池化层可以减少该层的输出数量。这意味着减少了网络下一层的输入数量,可以减少网络整体参数数量,降低计算量,减少参数存储需求,提高网络计算效率。
池化层输出的数量由池化的宽度 W 和步幅 S 决定。设输入单元的数量为 N ,设池化的位置为 $0,1,\cdots,n $,则有:
$n\times S+(W-1) \le (N-1) \rightarrow n \le \frac{N-W}{S}$
每个位置对应一个输出单元,因此输出单元的数量为$ \lfloor \frac{N-W}{S}\rfloor+1 $,其中$ \lfloor \rfloor $为向下取整数。
如下所示,池化层的输入单元数量为 6 ,池的宽度为 3、步幅为 2,池化层的输出单元数量为 2 。
池化层的宽度 W 可以随着输入图片尺寸的不同而动态调整,这可以解决图像任务中输入图像尺寸不同的问题。
2.2.1 平移近似不变性
当输入做出了少量的平移时,最大池化能够获得输出的近似不变性。即:当输入平移一个微小的量时,经过最大池化的输出近似不变。
下图给出了输入右移了一个单位时,最大池化的输出。可以看到:当输入的每个位置的值都发生改变时,最大池化的输出只有一半的值发生了改变。
最大池化平移近似不变性的原因:最大池化单元只对周围存在的最大值比较敏感,而不关心最大值的精确位置。
如下图所示,平均池化并没有平移近似不变性。事实上,最大池化、平均池化、以及其它池化对于平移变换均具有等变性。
局部平移不变性是个很重要的性质。该性质表明:网络只关心某个特征是否出现,而不关心它出现的具体位置。如:判断是否人脸时,并不关心眼睛的具体位置,只需要知道一只眼睛在脸的左边、一只眼睛在脸的右边。
但是有些领域,特征的具体位置很重要。如:判断两条线段是否相交。
2.2.2 模拟其它不变性
最大池化只能对空间的平移具有不变性,而无法对空间的旋转具有不变性。
可以将空间的旋转角度进行离散化,每个角度对应一个卷积,然后采用最大池化。这种做法也可以实现空间的旋转不变性。
下图中,使用多个滤波器和一个最大池化单元可以学得旋转不变性。
- 当输入旋转某个角度时,对应的滤波器被激活。
- 只要任意一个过滤器被激活,最大池化单元也相应被激活。
最大池化的空间平移不变性是原生的,其他变换的不变性则必须采用这种多通道的方法来实现。
2.3 卷积层、池化层的先验
先验有强弱之分:
- 弱的先验具有较高的熵,即较大的不确定性。如:方差很大的高斯分布(方差无穷大就成了均匀分布)。
- 强的先验具有较低的熵,即很小的不确定性。如:方差很小的高斯分布(方差很小意味着随机变量取值几乎确定)。
一个无限强的先验对于参数在参数空间的某些取值的概率是 0。即:永远不支持参数取这些值。
卷积层也可以看做是一个全连接层,但是它的权值有两个无限强的先验:
- 层内的权重都是重复的,同一个权重将复用多次。
- 层输出单元的接受区域内的权重非零,其它权重都是零。
这些先验表明:卷积层学得的函数只包含了局部连接关系,并且具有稀疏性、平移等变性。
最大池化层也是一个无限强的先验:每个最大池化单元都具有对少量平移的不变性。
卷积与池化只有当先验的假设合理,且正确时才有用。
如果任务依赖于保存精确的空间信息,那么使用最大池化将增大训练误差。
如果任务需要对输入中相隔较远的信息进行合并,那么卷积所需要的先验可能就不准确。
因为卷积拥有平移等变性,相隔的远近没有意义。
2.4 计算复杂度
对于卷积层,假设输入的
feature map
为:宽度$ W_I$、高度 $H_I$、输入通道数 $C_I $。假设一共 C_O 个卷积核,每个卷积核的宽度为$ W_K$、高度为$ H_K $。假设沿着宽度方向卷积的步幅为 $S_W$,沿着高度方向卷积的步幅为 $S_H$ 。则输出的
feature map
的几个参数为(其中$ \lfloor\rfloor$ 为向下取整数):宽度: $W_O = \lfloor\frac{W_I-W_K}{S_W}\rfloor+1$
其推导过程参考池化层的推导。
高度: $H_O = \lfloor\frac{H_I-H_K}{S_H}\rfloor+1$
输出通道数 $C_O$
卷积过程中的几个指标:
参数数量:$ C_I\times W_K\times H_K\times C_O$ ,它也就是核张量的尺寸。
计算量(以一次
乘-加
计算为单位):$C_I\times W_K\times H_K\times C_O\times W_O\times H_O$考虑输出
feature map
中的每一个值,每个值都是通过一次卷积计算得到。每个卷积计算的乘-加
运算量为$ C_I\times W_K\times H_K$。 一共有 $C_O\times W_O\times H_O$ 这样的值,则最终计算复杂度为上式。
对于池化层,假设输入的
feature map
为:宽度$ W_I$、高度 $H_I$、输入通道数$ C_I $。假设池化窗口的宽度为 $W_P$、高度为 $H_P $。假设沿着宽度方向池化的步幅为 $S_W$,沿着高度方向池化的步幅为$ S_H $。则输出
feature map
的几个参数为:- 宽度: $W_O = \lfloor\frac{W_I-W_P}{S_W}\rfloor+1$
- 高度: $H_O = \lfloor\frac{H_I-H_P}{S_H}\rfloor+1$
- 输出通道数$ C_O = C_I$
池化过程中的几个指标:
参数数量:0 。因为池化过程是无参数的。
计算量(以一次求最大值或者均值的计算为单位):$C_I\times W_O\times H_O$
考虑输出
feature map
中的每一个值,每个值都是通过一次池化计算得到。每个池化计算的运算量为 1 个单位。 一共有$ C_O\times W_O\times H_O$ 这样的值,则最终计算复杂度为上式,其中 $C_O = C_I $。
事实上,单次求最大值或者均值的计算量要小于单次
乘-加
的计算量,因此池化层的计算量要远远小于卷积层的计算量。对于普通的全连接层,假设输入单元数量为$ C_I\times W_I\times H_I $个,输出单元数量为$ C_O\times W_O\times H_O $个,其中: $W_O = \lfloor\frac{W_I-W_K}{S_W}\rfloor+1 $,$ H_O = \lfloor\frac{H_I-H_K}{S_H}\rfloor+1$ 。
则:
参数数量:$C_I\times W_I\times H_I\times C_O\times W_O\times H_O $。
因此,全连接层的参数数量是卷积层参数数量的 $\frac{W_I\times H_I\times W_O\times H_O}{W_K\times H_K}$ 倍。
当输入
feature map
宽高为32x32
,卷积核宽高为2x2
,步长为 1 时,全连接层的参数数量是卷积层参数数量的 24.6 万倍。计算量:(以一次
乘-加
计算为单位):$C_I\times W_I\times H_I\times C_O\times W_O\times H_O $。因此,全连接层的计算量是卷积层计算量的 $\frac{W_I\times H_I}{W_K\times H_K} $倍。
当输入
feature map
宽高为32x32
,卷积核宽高为2x2
,步长为 1 时,全连接层的计算量是卷积层计算量的 256 倍。
2.5 全连接层转卷积层
通常情况下,卷积神经网络的最后几层都是全连接层加一个输出层(如:一个
softmax
层)。事实上,全连接层可以和卷积层相互转换。
假设在全连接之前,网络的
feature map
的形状为$ C_I\times W\times H $,即:通道数为$ C_I$、宽度为 $W$、高度为 H 。假设输出一个长度为 $C_O $的一维向量。- 如果后接全连接层,则需要将其展平为长度为$ CI\times W \times H $的一维向量。权重$\mathbf W=(W{i,j})\quad,i=1,2,\cdots C_I\times W \times H;\quad j=1,2,\cdots C_O $,一共有$ C_I\times W\times H\times C_O $个参数。
- 如果后接卷积层,则需要$ C_O $个卷积核,每个卷积核的尺寸都是$ W\times H$ 。一共有$ C_I\times W\times H\times C_O $个参数。
- 如果将$ W_{:,j}$ 重新
reshape
成一个尺寸为$ W\times H$、输入通道为 $C_I $的卷积核,则它恰好与后接卷积层的第$ j$ 个卷积核相同。而且二者都是输入的线性组合,因此二者可以相互转换。
全连接层转卷积层的优点:可以适应尺寸多变的输入图像。
如果是全连接层,则全连接层的输入大小是固定的。
如果网络的输入尺寸发生变化,则该变化会传递到全连接层,而全连接层无法处理可变的输入。
如果是卷积层,则它对输入大小没有限制。
全卷积网络
FCN
就是将CNN
网络后面的几个全连接层替换为卷积层,它可以高效的对测试图像做滑动窗口式的预测。在测试阶段,如果图像尺寸大于网络的输入尺寸,则通常需要对图像进行多次裁剪。通常裁剪左上、左下、右上、右下、中间,以及翻转之后的这 5 个位置,一共 10 个位置进行预测。
即:每张大图片需要裁剪 10 张标准输入大小的图片,然后取这 10 次预测的综合结果作为该张图片的预测结果。
如果采用全卷积网络,则不需要做任何裁剪就可以直接预测,这大大提高了预测效率。
下图中,绿色表示卷积核,蓝色表示
feature map
。上半图:测试图像的尺寸与网络的输入尺寸相同,输出一个概率。
下半图:测试图像的尺寸较大时,输出一组概率。
它等效于:先将测试图像先执行所有可能的裁剪(这里是
2x2=4
种);然后预测所有裁剪图片的概率;然后将这一组概率取平均,即可得到测试图像的概率。它的计算效率远远高于全连接的原始方法,因为它节省了大量的共享计算。
例:在
VGG-net
中,训练图像尺寸是224x224
的,展平之前的feature map
尺寸为512x7x7
。如果测试图像尺寸是
384x384
的,展平之前的feature map
尺寸为512x12x12
。如果使用全连接层,则无法处理这种尺寸的输入(展平后全连接层的输入尺寸不匹配)。
如果后接卷积层,则卷积核的尺寸为
7x7
、通道数1000
,最终的输出的结果尺寸为1000x6x6
。它表示分别对测试图像的 36 个位置使用了原始的
CNN
,平均这 36 个位置的各类别概率,则得到了最终的 1000 个类别的概率 。它比等效的执行 36 次原始的
CNN
+ 全连接的形式节省了大量的共享计算。
三、基本卷积的变体
3.1 局部连接
局部连接与卷积很类似:局部连接也是连接受限的,但是每个连接都有自己的权重。
即:局部连接实现了稀疏交互,但是没有实现参数共享。
假设局部连接的权重矩阵为一个 6 维的张量 $\mathbf W$ ,其元素为 $W_{i,j,k,l,m,n}$, 其中$:i$ 为输出的通道;$j,k $为输出通道中的位置;$l$ 为输入的通道;$m,n$ 为输入通道中的位置。
则局部连接可以表示为:
$Z{i,j,k}=\sum{l}\sum_m\sum_nV{l,j+m,k+n}W{i,j,k,l,m,n}$
当权重共享时, $W{i,j,k,l,m,n} = K{i,l,m,n} $,此时局部连接操作退化到卷积操作。
局部连接也称作非共享卷积,因为它并不横跨位置来共享参数。
与基本卷积相比,权重参数由 $K{i,l,m,n} \rightarrow W{i,j,k,l,m,n} $。
这说明$ \mathbf W $中,不同位置的输出的计算过程中,采用了不同的权重。这意味着局部连接不满足输入的等变表示。
与全连接相比,局部连接实现了稀疏交互。
如果知道特征是一小部分区域的函数,而不是整个区域的函数时,局部连接层很有用。此时只需要处理部分输入即可。如:如果需要辨别一张图片是否人脸图像,则只需要在图像的下部中央部分寻找即可。
卷积也可以处理局部特征,但是对于不满足平移不变性的特征,卷积层无能为力。此时需要使用局部连接层。
在图片中识别是否存在人脸,这满足平移不变性,因此也可以使用卷积来处理。
有时候,可以进一步限制卷积层或者局部连接层。如:限制输出的通道 i 仅仅利用了一部分输入通道(而不是全部输入通道) 的数据。
这种方案减少了通道之间的连接,使得模型的参数更少,降低了存储消耗,减少了计算量。
3.2 拼接卷积
拼接卷积
tiled convolution
对卷积和局部连接进行了折中:学习一组核,使得当核在空间移动时,它们可以循环利用。- 拼接卷积在相邻的位置上拥有不同的过滤器,就像局部连接层一样。
- 拼接卷积每隔一定的位置,使用相同的过滤器,就像卷积层一样。
- 拼接卷积的参数仅仅会增长常数倍,常数就是过滤器集合的大小。
假设拼接卷积的权重矩阵为一个 6 维的张量$ \mathbf W$ ,其元素为$ W_{i,j,k,l,m,n}$, 其中:i 为输出的通道;$j,k $为输出通道中的位置;$l$ 为输入的通道;$m,n $为输入通道中的位置。
则拼接卷积可以表示为:
这里百分号是取摸运算,t 为不同的核的数量(它也就是核的轮换周期)。
- 如果 t 等于输入的尺寸,则拼接卷积退化成局部连接。
- 如果 t 等于 1 ,则拼接卷积退化成卷积。
通常在卷积层会引入非线性运算,而在非线性运算中,需要加入偏置项。
对于局部连接,每个输入单元都有各自的偏置。
对于拼接卷积,偏置项通过与核一样的拼接模式来共享。
对于常规卷积,通常在输入通道级别上共享偏置。即:同一个通道使用一个偏置项。
如果输入是固定大小的,也可以在每个输入位置上学习一个单独的偏置。其好处是:允许模型校正输入图像中不同位置的差异。
3.3 分组卷积
分组卷积
Group convolution
:将多个卷积核拆分为分组,每个分组单独执行一系列运算之后,最终在全连接层再拼接在一起。通常每个分组会在单独的
GPU
中训练,从而利用多GPU
来训练。分组卷积的重点不在于
卷积
,而在于分组
:在执行卷积之后,将输出的feature map
执行分组。然后在每个组的数据会在各个GPU
上单独训练。对卷积的输出
feature map
分组,等价于在卷积过程中对卷积核进行分组。
分组卷积在网络的全连接层才进行融合,这使得每个
GPU
中只能看到部分通道的数据,这降低了模型的泛化能力。如果每次分组卷积之后,立即融合卷积的结果则可以解决这个问题。
分组卷积降低了模型的参数数量以及计算量。
假设输入
feature map
具有$ C_I$ 的输入通道、宽/高分别为$ W_I,H_I,$假设卷积核的宽/高分别为 $W_K,H_K ,$有 $C_O$ 个卷积核。则:- 参数数量:$W_K\times H_K\times C_I\times C_O$
- 计算量(以一次
乘-加
计算为单位):$W_K\times H_K\times C_I\times W_O\times H_O\times C_O。$ 其中$ W_O,H_O $分别为输出feature map
的宽/高
假设采用分组卷积,将输入通道分成了 $G$ 组,则分组之后:
- 参数数量:$G\times W_K\times H_K\times \frac{C_I}{G}\times \frac{C_O}{G}$
- 计算量(以一次
乘-加
计算为单位):$G\times W_K\times H_K\times \frac{C_I}{G}\times W_O\times H_O\times \frac{C_O}{G}$
因此分组卷积的参数数量、计算量均为标准卷积计算的 $\frac 1G 。$
考虑到全连接层的参数数量在网络中占据主导地位,因此即使采取分组卷积,网络最终的参数数量的减小幅度不会很大。
因此分组卷积主要降低的是计算量。
分组卷积最早在
AlexNet
中出现。由于当时的硬件资源的限制,训练AlexNet
时卷积操作无法全部放在同一个GPU
中处理。因此,通过分组来在多个GPU
上分别处理,然后将多个GPU
的处理结果融合。
3.4 小卷积核替代
在
AlexNet
中用到了一些非常大的卷积核,如11x11、5x5
等尺寸的卷积核。卷积核的尺寸越大,则看到的图片信息越多,因此获得的特征会越好。
但是卷积核的尺寸越大,模型的参数数量会爆涨,不利于模型的深度的增加,计算量和存储量也大幅上升。
卷积核的尺寸越小,模型的参数数量越少,模型可以越深。
但是卷积核的尺寸太小,则只能看到图片的一个非常小的局部区域,获得的特征越差。
一种解决方案是:用多个小卷积层的堆叠来代替较大的卷积核。
假设大卷积核的宽度是 k ,则每经过一层,输出的宽度减少了$ k-1 $。假设希望通过 n 个宽度为$ k^\prime $的小卷积核来代替,则为了保持输出的大小一致,需要满足:
$k-1=n(k^\prime -1)$
当 $k^\prime=3 $时,即用尺寸为 3 的卷积核代替尺寸为 k 的卷积核时,有:$ n=\frac {k-1}{2}$
如:用 2 个
3x3
的卷积核来代替 1 个5x5
的卷积核。假设输入通道数为$ C_I,$输出通道数为 $C_O ,$则
5x5
卷积核的参数数量为 $C_O\times C_I\times 5\times 5 ;$而 2 个
3x3
卷积核的参数数量为 $2\times C_O\times C_I\times 3\times 3 ,$是前者的 72% 。如果用 5 个
3x3
的卷积核来代替 1 个11x11
的卷积核,则替代后的卷积核的参数数量是替代前的 37% 。
用多个小卷积层的堆叠代替一个大卷积层的优点:
可以实现与大卷积层相同的感受野。
具有更大的非线性,网络表达能力更强。
虽然卷积是线性的,但是卷积层之后往往跟随一个
ReLU
激活函数。这使得多个小卷积层的堆叠注入了更大的非线性。具有更少的参数数量。
小卷积层堆叠的缺点是:加深了网络的深度,容易引发梯度消失等问题,从而使得网络的训练难度加大。
用多个小卷积层的堆叠代替一个大卷积层可以看作是一种正则化:要求大卷积核通过多个小卷积核进行分解(同时在小卷积层之间注入非线性)。
感受野:一个特定的
CNN
输出单元在输入空间所受影响的区域。上图中,染色的区域为某个输出单元的感受野。- 一个感受野可以用中心位置和大小来表示。
- 用多个小卷积核来代替大卷积核时,输出单元的感受野不会受到影响。
通常选择使用
3x3
卷积核的堆叠:1x1
的卷积核:它无法提升感受野,因此多个1x1
卷基层的堆叠无法实现大卷积层的感受野。2x2
的卷积核:如果希望输入的feature map
尺寸和输出的feature map
尺寸不变,则需要对输入执行非对称的padding
。此时有四种padding
方式,填充方式的选择又成了一个问题。3x3
的卷积核:可以提升感受野,对称性填充(不需要考虑填充方式),且尺寸足够小。
3.5 非对称卷积核
在卷积核分解过程中,还有一种分解方式:非对称卷积核分解,将
nxn
卷积替换为1xn
卷积和nx1
卷积。非对称卷积核的分解有以下优点:
感受野保持不变。
节省计算成本,尤其是当
n
较大时。假设输入通道数和输出通道数都为 C ,原始卷积
nxn
的参数数量为:$n\times n\times C\times C=n^2C^2 。$假设非对称卷积的
1xn
的输出通道数也是 C ,则非对称分解时参数数量为:$ 1\times n\times C \times C+n\times 1\times C\times C=2nC^2 。$它是原始卷积的参数数量的$ \frac 2n 。$
在
Inception v2
论文中作者指出:对于较大的特征图 ,这种分解不能很好的工作;但是对于中等大小的特征图(尺寸在12~20
之间),这种分解效果非常好。因此非对称卷积分解通常用在较高的网络层。
3.6 多尺寸卷积核
图像中目标对象的大小可能差别很大。如下图所示,每张图像中狗占据区域都是不同的。
由于信息区域的巨大差异,为卷积操作选择合适的卷积核尺寸就非常困难。
- 信息分布更具有全局性的图像中,更倾向于使用较大的卷积核。如最最侧的图片所示。
- 信息分布更具有局部性的图像中,更倾向于使用较小的卷积核。如最右侧的图片所示。
一个解决方案是:分别使用多个不同尺寸的卷积核从而获得不同尺度的特征。然后将这些特征拼接起来。
在
Inception
系列的网络中,大量使用这种思想。在最初版本的
Inception
结构中,一个输入图片会分别同时经过1x1,3x3,5x5
的卷积核的处理;得到的特征再组合起来。通过多种尺度的卷积核,无论感兴趣的信息区域尺寸多大,总有一种尺度的卷积核与之匹配。这样总可以提取到合适的特征。
多尺寸卷积核存在一个严重的问题:参数数量比单尺寸卷积核要多很多,这就使得计算量和存储量都大幅增长。
3.7 1x1 卷积核
1x1
卷积并不是复制输入,它会进行跨通道的卷积。它有三个作用:实现跨通道的信息整合。
进行通道数的升维和降维。
在不损失分辨率的前提下(即:
feature map
尺寸不变),大幅增加非线性。事实上
1x1
卷积本身是通道的线性组合,但是通常会在1x1
卷积之后跟随一个ReLU
激活函数。
假设输入张量为$ \mathbf I\in \mathbb R^{(C_I\times W_I\times H_I)},$即:$C_I $个通道、宽度为$ W_I 、$高度为 $H_I 。$
如果图片直接通过一个宽度为 $W_K,$高度为$ H_K $、输出通道为 $C_O $的卷积层,则参数数量为:
$C_I\times C_O\times W_K\times H_K$
如果图片先通过一个
1x1
、输出通道为 $\sqrt {C_O}$ 的卷积层,再经过一个$ W_K\times H_K、$输出通道为 $\sqrt {C_O} $的卷积层;最后经过一个1x1
、输出通道为 $C_O $的卷积层。这里中间卷积层的输出通道不一定为$ \sqrt {C_O} ,$但是一定是一个比$ C_O$ 小的数。其作用是起到了信息压缩的作用(类似于
PCA
降维)。则参数数量为:
$C_I\times1\times 1 \times \sqrt{C_O}+\sqrt{C_O}\times W_K\times H_K\times \sqrt{C_O}+\sqrt{C_O}\times1\times 1\times C_O\ =C_I\sqrt{C_O}+W_KH_KC_O+C_O^{3/2}$
当$ C_I\simeq C_O $时(输入通道数与输出通道数接近),$C_I\times C_O\times W_K\times W_K\simeq W_KH_KC_O^2 ,以及 C_I\sqrt{C_O}+W_KH_KC_O+C_O^{3/2}\simeq 2C_O^{3/2}+W_KH_KC_O 。$
则二者参数的数量比例为:$\frac{2C_O^{3/2}+W_KH_KC_O}{W_KH_KC_O^2} \simeq \frac{1}{C_O} 。$因此后者的参数数量远远小于前者。
1x1
卷积层通常会形成瓶颈层bottleneck layer
。瓶颈层指的是网络中信息被压缩的层。输入
feature map
中每个元素值代表某个特征,将所有图片在该feature map
上的取值扩成为矩阵:$\mathbf P = \begin{bmatrix} P{1,1}&P{1,2}&\cdots&P{1,n}\ P{2,1}&P{2,2}&\cdots&P{2,n}\ \vdots&\vdots&\ddots&\vdots\ P{N,1}&P{N,2}&\cdots&P_{N,n}\ \end{bmatrix}$
其中 N 为样本的数量,$ n=W\times H\times C $。即:行索引代表样本,列索引代表特征。所有特征由
feature map
展平成一维得到。通常$ N \gg n $,则输入矩阵 $\mathbf P$ 的秩$ \text{rank}(\mathbf P) \lt n $。假设输入矩阵$ \mathbf P $的秩为 $r 。$
不考虑
1x1
卷积的非线性层,则1x1
卷积是输入特征的线性组合。输出featuremap
以矩阵描述为:$\mathbf P^ = \begin{bmatrix} P^{1,1}&P^{1,2}&\cdots&P^**{1,n^\}\ P^{2,1}&P^{2,2}&\cdots&P^{2,n^*}\ \vdots&\vdots&\ddots&\vdots\ P^{N,1}&P^*{N,2}&\cdots&P^_{N,n^*}\ \end{bmatrix}$
其中 $n^=W\times H\times C^ 。$
信息膨胀过程:当 $C^\gt C $时$,\mathbf P^$ 的容量要大于 $\mathbf P$ 的信息,因此所有的有效信息都可以得到保留。
信息压缩过程:当 $C^ \lt C $时,$ \mathbf P^ $的容量要小于 $\mathbf P$ 的信息,这时需要参考$ \mathbf P$ 的有效信息。
$\mathbf P $的有效信息由矩阵$ \mathbf P $的秩 $r $决定。
- 当矩阵$ \mathbf P$ 是满秩时,即:$ r=n ,$此时对 $\mathbf P$ 的任何压缩都会丢失有效信息。
- 当矩阵$ \mathbf P $不是满秩时:
- 当$ C^$ 非常小时, $\mathbf P^$ 的容量要小于$ \mathbf P $的有效信息,此时会导致有效信息丢失。
- 当$ C^$较大时,$ \mathbf P^$的容量要大于等于 $\mathbf P $的有效信息,此时不会丢失有效信息。这是
1x1
卷积相当于线性降维。
在前文提到的例子(示意图如下所示)中,输入
feature map
先经过1x1
卷积的压缩,这会导致该段信息容量的下降;然后经过常规卷积,此段信息容量不变;最后经过1x1
卷积的膨胀,恢复了信息容量。整体而言模型的信息容量很像一个
bottleneck
,因此1x1
卷积层也被称作瓶颈层。
事实上,不仅
1x1
卷积层会形成bottleneck
,任何会降低模型信息容量的层都会形成瓶颈。因此在卷积神经网络中,通常每经过一个卷积层,输出尺寸减半、输出通道数翻倍。
瓶颈层中的信息膨胀阶段不是必须存在,通常信息膨胀过程是为了保持整个瓶颈层的输入尺寸、输出尺寸满足某些约束。如:输出尺寸等于输入尺寸。
3.8 DepthWise 卷积
标准的卷积会考虑所有的输入通道,而
DepthWise
卷积会针对每一个输入通道进行卷积操作,然后接一个1x1
的跨通道卷积操作。DepthWise
卷积与分组卷积的区别在于:分组卷积是一种通道分组的方式,它改变的是对输入的
feature map
处理的方式。Depthwise
卷积是一种卷积的方式,它改变的是卷积的形式。Depthwise
分组卷积结合了两者:首先沿着通道进行分组,然后每个分组执行DepthWise
卷积。
假设输入张量为$ \mathbf I\in \mathbb R^{(C_I\times W_I\times H_I)},$即:$C_I $个通道、宽度为$ W_I 、$高度为$ H_I 。$
假设使用标准卷积,输入通道的数量为 $C_I,$输出通道的数量为$ C_O,$卷积核的尺寸为 $W_K\times H_K 。$则需要的参数数量为$ C_I\times W_K\times H_K\times C_O 。$
使用
Depthwise
卷积时,图像的每个通道先通过一个$ W_K\times H_K$ 的deptpwise
卷积层,再经过一个1x1
、输出通道为 $C_O $的卷积层。参数数量为:
$C_I\times W_K\times H_K+C_I\times 1\times 1\times C_O=W_KH_KC_I+C_IC_O$
其参数数量是标准卷积的 $\frac{1}{C_O} +\frac{1}{W_KH_K} 。$因此
depthwise
卷积的参数数量远远小于标准卷积。
4) DepthWise
卷积有几种变形的形式:
- 只有对每个输入通道执行单通道卷积,没有后续的
1x1
的跨通道卷积。 - 对输入通道执行单通道卷积的结果执行
BN
和ReLU
,再后接1x1
的跨通道卷积。这会引入更多的非线性。
3.9 通道混洗分组卷积
在分组卷积中,特征的通道被平均分配到不同的分组中。如果融合的时刻非常靠后,则对模型的泛化性相当不利,因为如果能在早期知道其它通道的一些信息,则很可能得到更有效的特征。
通道混洗分组卷积在每一次分组卷积之后执行一次通道混洗,被混洗过的通道被分配到不同的分组中。
经过通道混洗之后,每个分组输出的特征能够考虑到更多的通道,因此输出特征的表达能力更强。
在
ShuffleNet
中,大量运用了这种通道混洗分组卷积。在
AlexNet
的分组卷积中,执行的是标准卷积操作。在
ShuffleNet
中,分组卷积执行的是deptiwise
卷积,从而使得参数更少。
3.10 通道加权卷积
在常规卷积中,各通道产生的特征都是不分权重直接结合的。通道加权卷积中,不同的通道具有不同的权重,各通道产生的特征经过加权之后再结合。
所用到的权重是输入的函数。
注意:因为卷积是线性过程,因此卷积计算的通道加权等价于对输入的
feature map
的通道加权。SEnet
(Squeeze-and-Excitation Networks
)网络大量使用通道加权卷积。在SEnet
中存在三个关键的操作:Squeeze
操作:沿着空间维度压缩特征,将每个二维的feature map
通道压缩成一个实数。该实数具有全局的感受野,表征了在该
feature map
通道上响应的全局分布。Excitation
操作:通过一个类似循环神经网络中的门机制,用一个sigmoid
激活函数的全连接层获取每个feature map
通道的权重。实际上,
Excitation
操作使用了两个全连接层来获取通道权重。Reweight
操作:将特征通道的权重通过乘法逐通道的加权到先前的feature map
上。
3.11 空洞卷积
在图像分割任务,图像输入到传统卷积层,然后再输入到池化层。由于图像分割是逐像素的输出,因此需要将池化层的输出(一个较小的尺寸)升采样(一般使用反卷积操作)到原始的图像尺寸来进行预测。
但是这里有几个问题:
- 升采样(如:线性插值) 是确定性的映射,无法学习(也没有参数要学习)。
- 在这个图像的先减少尺寸、再增大尺寸过程中,有一些信息损失。
- 小物体信息无法重建。假设有 4 个池化层,每个池化层的尺寸为 2、步长为 2,理论上任何小于$ 2^4=16$ 个像素的物体信息将无法被重建。
解决方案是空洞卷积。
空洞卷积:对于空洞数为$ d$ 的空洞卷积,卷积结果为:
$\mathbf S(i,j)=\sum_m\sum_n\mathbf I(i+m(d+1)+1,j+n(d+1)+1)\mathbf K(m,n)$
它实际上等价于一个卷积核为 $(d+1)K+1 $的新的卷积核,其中 K 为当前卷积核的大小。新的卷积核的特点是:每隔 d 个位置,权重非零;否则权重为零。另外首行、首列、尾行、尾列权重均为零。
d+1 称作膨胀比
dilation rate
。空洞卷积的优点:在不做池化损失信息的情况下,加大感受野,让每个卷积的输出都包含较大范围的信息。
在图像需要全局信息,或者语音、文本需要较长序列信息的问题中,空洞卷积都能很好的应用。
空洞卷积的缺点:
网格效应(
Gridding Effect
)。如果仅仅多次叠加多个dilation rate=2
的3x3
的卷积核时,会发现:并不是所有的输入像素都得到计算,也就是卷积核不连续。这对于逐像素的预测任务来说,是致命的问题。
长距离信息可能与任务无关。采用空洞卷积可能对大物体的分割有效果,但是对于小物体的分割可能没有好处。
如何同时处理不同大小的物体,则是设计好空洞卷积网络的关键。
为了解决空洞卷积的缺点,人们提出了一种混合空洞卷积的结构(
Hybrid Dilated Convolution:HDC
) 。该结构有三个特性:
叠加的空洞卷积的
dilation rate
不能有大于 1 的公约数。这是为了对抗网格效应。如:
[2,4,6]
不是一个好的三层空洞卷积,因为会出现网格效应。将
dilation rate
设计成锯齿状结构。这是为了同时满足小物体、大物体的分割要求。如
[1,2,5,1,2,5]
的循环结构。最后一层的空洞卷积的
dilation rate
最大,且dilation rate
小于等于卷积核的大小。这也是为了对抗网格效应。
下面是一组
dilation rate
分别为[1,2,5]
的卷积核,卷积核的尺寸为3x3
四、应用
4.1 逐像素输出
卷积神经网络不仅可以输出分类任务的标签或者回归任务的实数值,还可以输出高维的结构化对象。如:图片上每个像素属于各个类别的概率。这允许模型标记图像中的每个像素,并绘制单个物体的精确轮廓。
这种结构化对象用张量表示。如:张量 $\mathbf S ,$其中$ S_{i,j,k}$ 是网络的输入像素$ (j,k) $属于类$ i $的概率。
对图像进行逐个像素标记的一种策略是:先产生图像标记的一个原始猜测;然后使用相邻像素之间的校验来修正该原始猜测;重复上述修正步骤直到收敛。
如下图所示:输入图像张量 $\mathbf X,$ 输出每个像素的类别张量 $\hat{\mathbf Y} 。$
该网络并不是一次性输出结果$ \hat {\mathbf Y}$ ,而是使用前一轮的输出$ \hat {\mathbf Y}^{(t-1)}$ 来改善结果$ \hat {\mathbf Y}^{(t)}$ 。
每一步对$ \mathbf X $执行卷积的卷积核都是张量$ \mathbf U 。$
每一步产生的$ \mathbf H^{(t)} $都需要两个输入:
一个输入是通过对图像 $\mathbf X$ 采用核$ \mathbf U$ 来卷积。
一个输入是通过对前一个输出$ \hat{\mathbf Y}^{(t-1)} $采用核 $\mathbf W $进行卷积。
第一次产生$ \mathbf H^{(1)} $时,这一项为零,因为还没有前一次输入。
张量$ \mathbf V $用于产生从$ \mathbf H^{(t)}$ 到 $\mathbf Y^{(t)} $的输出。
每一次重复修正相当于再一次执行同样的卷积(卷积核为$ \mathbf U $)。
很多个这样的卷积组成了一个深层网络,该网络的最后几层之间存在跨层的权值连接(连接权重为 $\mathbf W)。$
这种跨层的权值连接构成了反馈,因此这种深层网络形成了一个特殊的循环神经网络。
一旦对每个像素都进行了一次预测,就可以用各种方法来进一步处理这些预测的结果。
常规思路是:假设大片相连的像素对应于相同的标签。
4.2 可变输入类型
卷积神经网络使用的数据通常包含多个通道:每个通道都是时间/空间上一个点的某个角度的观测量。
同一个点,观测的角度不同,就产生了不同的通道。如:
- 三维的单通道:立体成像的数据。每个点代表了三维空间的一个点。
- 三维:空间的三个维度。
- 单通道:数据通道。
- 三维的多通道:彩色视频数据。时间维度+二维空间(图像)+色彩通道(红绿蓝三通道)
- 三维:时间维度(一维)+ 图像维度(二维)。
- 多通道:色彩通道(红绿蓝三通道)。
- 三维的单通道:立体成像的数据。每个点代表了三维空间的一个点。
卷积神经网络还可以处理具有变化的空间尺度的输入。如:输入图片的尺寸可能各不相同。
这种不同尺寸大小的输入,无法使用传统的基于矩阵乘法的神经网络来表示。
因为不同样本的输入的维度可能不同,所以权重矩阵的形状无法确定。
卷积神经网络可以处理这种情况:根据输入图片尺寸的大小,核会被自动的的使用不同次数。
- 如果要求网络的输出尺寸和输入尺寸是一样的(如:为每个输入像素分配类别标签),则无需做额外的工作。
- 如果要求网络的输出尺寸是固定的(如:为整个图像分配一个类别标签),此时需要插入一个池化层:池化区域的大小要和输入的大小成比例,从而保持固定数量的池化输出。
卷积能处理可变大小的输入,但这种“可变”必须是因为同一个事物在同一个角度下的、不同数量的观察不同导致的。
如:时间角度下的、数量上的不同观察导致时间维度可变,空间角度下的、数量上的不同观察导致空间维度可变。
这种可变并不包括特征数量(即:多少个观察角度)的可变。
如:某个样本具有 “年龄、学历、性别”特征,另一个样本只具有“年龄、学历”特征。则卷积对于这种类型的数据集无能为力。
4.3 高效的卷积算法
设计更快的卷积、或者近似卷积而不降低模型准确率的方法是一个活跃的研究领域。
甚至仅提高前向传播效率的技术也是有用的。因为在商业环境中,通常对模型的推断有性能要求或者限制。
4.3.1 傅里叶变换
卷积等效于:使用傅里叶变换将输入和核都转换到频域,然后在频域将输入和核进行逐点相乘,最后把相乘的结果使用傅里叶逆变换转换回时域。
对于某些规模的问题,这种算法可能比直接计算离散卷积效率更高。
4.3.2 可分离卷积
对于一个 d 维的核矩阵,如果可以表示成 d 个一维向量的外积时,称该核是可分离的。
这里的外积不同于代数意义上的叉乘,而是:
当核$ \mathbf K$ 是可分离时,假设有:$\mathbf K =\mathbf{\vec k}_1\otimes\mathbf{\vec k}_2\cdots\otimes\mathbf{\vec k}_d,\quad \mathbf{\vec k}_i \in \mathbb R^w 。$
直接使用$ \mathbf K$ 进行卷积运算是非常低效的。它等价于连续的对 d 个一维向量$ \mathbf{\vec k}_i $执行卷积。
由于$ \mathbf K \in \mathbb R^{w\times w\times\cdots\times w} ,$因此直接计算卷积需要$ O(w^d) $个参数,需要$ O(w^d)$ 的运行时间和存储空间。
如果使用可分离卷积,则只需要连续的对 d 个一维向量$ \mathbf{\vec k}_i $执行卷积。
此时需要$ O(w\times d) $个参数,只需要$ O(w\times d) $的运行时间和存储空间。
但遗憾的是:并不是每个核都是可分离的。
4.4 非监督的特征
- 通常卷积神经网络训练中代价最高的是学习卷积核,而输出层的学习代价相对较低。
- 因为卷积核的输入单元相对较多,而且卷积神经网络中可能需要学习多个卷积核。
- 经过了若干个池化层之后,输出层的输入单元的数量要小的多。
- 每个卷积核都可以提取某个特征,因此学习卷积核就是要学习特征。
- 降低卷积神经网络训练成本的方法是:使用那些非监督方式训练得到特征。
- 有三种基本策略来避免监督训练而得到特征:
- 简单地随机初始化特征。
- 人工设计特征。如:人工设计一个检测图像边缘的卷积核。
- 用无监督训练来学习特征。
4.5.1 随机初始化特征
随机初始化特征经常在卷积网络中表现的出乎意料的好。
随机初始化特征训练卷积神经网络的步骤是:
给出多个随机权重,生成一组候选的卷积核(这些卷积核可以是不同尺寸的)。
仅仅训练输出层来评估这一组候选卷积核的性能,挑选表现最好的那个卷积核。
训练过程中,卷积核的权重固定,不会被调整。
使用表现最好的那个卷积核的结构和权重,并重新训练整个网络。
训练过程中,卷积核的权重会被调整。
4.5.2 无监督学习特征
使用无监督学习特征来训练卷积神经网络时,允许其结构与输出层相分离。
其步骤是:
- 使用无监督学习特征。
- 提取训练集的全部特征,构建一个新的训练集。
- 将这个新的训练集作为输出层的输入,训练一个简单的神经网络(可能只有一个输出层,也可能添加一层隐层)。
无监督学习特征可以使用一些特殊的方法来学习,它不需要在每个梯度步骤中都完整的前向和反向传播。
如:逐层贪心预训练。逐层贪心预训练的经典模型是卷积深度信念网络。
使用无监督学习特征来训练卷积神经网络时,训练过程中可以完全不使用卷积。
通过该方法可以训练非常大的模型,并且只在前向传播期间产生高计算成本(反向传播阶段计算成本较低,因为大量的参数并不参与训练)。
当前大多数卷积神经网络以纯粹有监督的方式训练,因为计算能力比以前大幅度提升。
有监督的方式训练的预测能力更强。
无监督学习特征的优点难以说清:
- 使用无监督学习特征可以提供一些相对于监督训练的正则化。
- 使用无监督学习特征可以训练更大的网络结构,因为它的学习方式减少了计算成本。
五、 历史和现状
5.1 历史
卷积神经网络是第一个解决重要商业应用的神经网络。
卷积神经网络是用反向传播训练的第一个有效的深度神经网络之一。
卷积神经网络提供了一种方法来特化神经网络,从而处理具有网格结构拓扑的数据。
这种方法在二维图像上是最成功的。
为了处理一维序列数据,往往采用另一种强大的特化网络:循环神经网络。
5.2 神经科学基础
图像传输到大脑的流程可以简化为:
- 图像从光到达眼睛并刺激视网膜。
- 视网膜中的神经元对图像进行一些简单的预处理,但是基本不改变图像的表达方式。
- 图像通过视神经,以及称作外侧膝状体的脑部区域。
- 然后大脑的 V1 部分(也称作主要视觉皮层)开始处理图像。
神经生理学家
David Hubel
和Torsten Wiesel
观察了猫的脑内神经元的视觉响应发现:处于视觉系统较为前面的神经元对于特定的光模式反应最强烈,但是对于其它光模式几乎完全没有反应。卷积层被设计为描述 V1 的三个性质:
V1 分布在空间中。
它实际上具有二维结构来映射视网膜中的图像,视网膜下半部的光仅仅影响 V1 相应的一半。
卷积网络通过用二维映射定义特征的方式来描述该特性。
V1 包含许多简单细胞。
这些简单细胞的行为简单概括为:是在一个空间上小的、局部的接受域内的图像的线性函数。
卷积网络的卷积单元被设计为模拟简单细胞。
V1 还包括许多复杂细胞。
复杂细胞对于特征的位置的微小偏移具有不变性。
这通过卷积网络的最大池化单元来刻画。
复杂细胞对于照明中的一些变化也是不变的。
它不能简单地通过在空间位置上池化来刻画。它也激发了卷积网络中的一些跨通道池化策略,如
maxout
单元。
一般认为:类似于 V1 的原理也适用于视觉系统的其他区域。
在大脑中人们找到了响应一些特定概念的细胞,并且这种细胞对于输入的许多种变换都具有不变性。
这些细胞被称作祖母细胞,存在于内侧颞叶的区域。
一个人可能有这样的一个神经元,当他看到祖母的照片时,该神经元被激活。无论祖母出现在照片的哪个位置、无论是祖母的脸部还是全身、无论是光亮还是黑暗。
与卷积网络最后一层最接近的类比是:颞下皮质的脑区。
当查看一个对象时,信息从视网膜经过
LGN
流到 V1 ,然后到 V2 ,V4 ,然后是颞下皮质。这发生在瞥见对象的前
100ms
内。如果允许一个人继续观察对象更多的时间,那么信息将开始向后流动(即前面过程的反馈路径)。
因为大脑使用自上而下的反馈来更新较低级脑区中的激活。
如果打断人的注视,并且只观察前
100ms
内的大多数前向传播路径,则颞下皮质与卷积网络的最后一层非常相似。
动物的视觉系统与卷积网络的主要区别:
人眼大部分是非常低的分辨率,除了一个被称作中央凹的小块(手臂远的拇指大小的区域)。而大多数卷积网络实际上接收到的是一张高分辨率的照片。
虽然人们觉得可以看到高分辨率的整个场景,但是这是大脑的潜意识创建的错觉。因为大脑缝合了人们瞥见的若干个小区域。
人类大脑控制几次眼动(称作扫视),从而瞥见场景中最显眼的或者任务相关的部分。这称作注意力机制。
目前注意力机制在自然语言处理中大获成功。
人类视觉系统集成了许多其他感觉(如听觉,以及心情想法之类的因素),而卷积网络目前为止纯粹是视觉的。
人类视觉系统不仅用于识别对象,它还能够理解整个场景:包括多个对象、对象之间的关系、人们的身体与世界交互所需要的丰富的三维几何信息。而卷积神经网络在这些问题上还是起步阶段。
即使像 V1 这样简单的大脑区域也受到来自较高级别的反馈的严重影响。虽然神经网络模型也探索反馈机制,但是目前没有提供引人瞩目的改进。
大脑可能使用非常不同的激活函数、卷积函数、池化函数。单个神经元的激活可能并不能通过单个线性过滤器的响应来很好的表征。
CNN:图像分类
ImageNet
数据集:一个开源的图片数据集,包含超过 1400 万张图片和图片对应的标签,包含 2 万多个类别。自从
2010
年以来,ImageNet
每年举办一次比赛,即:ImageNet
大规模视觉识别挑战赛ILSVRC
,比赛使用 1000 个类别图片。2017 年 7 月,
ImageNet
宣布ILSVRC
于2017
年正式结束,因为图像分类、物体检测、物体识别任务中计算机的正确率都远超人类,计算机视觉在感知方面的问题基本得到解决,后续将专注于目前尚未解决的问题。ImageNet
中使用两种错误率作为评估指标:top-5
错误率:对一个图片,如果正确标记在模型输出的前 5 个最佳预测(即:概率最高的前 5 个)中,则认为是正确的,否则认为是错误的。最终错误预测的样本数占总样本数的比例就是
top-5
错误率。top-1
错误率:对一个图片,如果正确标记等于模型输出的最佳预测(即:概率最高的那个),则认为是正确的,否则认为是错误的。最终错误预测的样本数占总样本数的比例就是
top-1
错误率。
注:
feature map
的描述有两种:channel first
,如256x3x3
;channel last
,如3x3x256
。这里如果未说明,则默认采用channel last
描述。另外也可以显式指定,如:3x3@256
。
一、LeNet
1998 年
LeCun
推出了LeNet
网络,它是第一个广为流传的卷积神经网络。LeNet
网络包含了卷积层、池化层、全连接层,这些都是现代CNN
网络的基本组件。输入层:二维图像,尺寸为
32x32
。C1、C3、C5
层:二维卷积层。其中
C5
将输入的feature map
(尺寸16@5x5
)转化为尺寸为120x1x1
的feature map
,然后转换为长度为120
的一维向量。这是一种常见的、将卷积层的输出转换为全连接层的输入的一种方法。
S2、S4
层:池化层。使用sigmoid
函数作为激活函数。后续的
CNN
都使用ReLU
作为激活函数。F6
层:全连接层。输出层:由欧式径向基函数单元组成。
后续的
CNN
使用softmax
输出单元。下表中,
@
分隔了通道数量和feature map
的宽、高。
| 网络层 | 核/池大小 | 核数量 | 步长 | 输入尺寸 | 输出尺寸 |
| ------ | --------- | ------ | ---- | -------- | -------- |
| INPUT | - | - | - | - | 1@32x32 |
| C1 | 5x5 | 6 | 1 | 1@32x32 | 6@28x28 |
| S2 | 2x2 | - | 2 | 6@28x28 | 6@14x14 |
| C3 | 5x5 | 16 | 1 | 6@14x14 | 16@10x10 |
| S4 | 2x2 | - | 2 | 16@10x10 | 16@5x5 |
| C5 | 5x5 | 120 | 1 | 16@5x5 | 120@1x1 |
| F6 | - | - | - | 120 | 84 |
| OUTPUT | - | - | - | 84 | 10 |
二、AlexNet
- 2012 年
Hinton
和他的学生推出了AlexNet
。在当年的ImageNet
图像分类竞赛中,AlexeNet
以远超第二名的成绩夺冠,使得深度学习重回历史舞台,具有重大历史意义。
2.1 网络结构
AlexNet
有 5 个广义卷积层和 3 个广义全连接层。- 广义的卷积层:包含了卷积层、池化层、
ReLU
、LRN
层等。 广义全连接层:包含了全连接层、
ReLU
、Dropout
层等。
- 广义的卷积层:包含了卷积层、池化层、
网络结构如下表所示:
输入层会将
3@224x224
的三维图片预处理变成3@227x227
的三维图片。第二层广义卷积层、第四层广义卷积层、第五层广义卷积层都是分组卷积,仅采用本
GPU
内的通道数据进行计算。第一层广义卷积层、第三层广义卷积层、第六层连接层、第七层连接层、第八层连接层执行的是全部通道数据的计算。
第二层广义卷积层的卷积、第三层广义卷积层的卷积、第四层广义卷积层的卷积、第五层广义卷积层的卷积均采用
same
填充。当卷积的步长为 1,核大小为
3x3
时,如果不填充 0,则feature map
的宽/高都会缩减 2 。因此这里填充 0,使得输出feature map
的宽/高保持不变。其它层的卷积,以及所有的池化都是
valid
填充(即:不填充 0 )。第六层广义连接层的卷积之后,会将
feature map
展平为长度为 4096 的一维向量。
| 编号 | 网络层 | 子层 | 核/池大小 | 核数量 | 步长 | 激活函数 | 输入尺寸 | 输出尺寸 |
| ----- | ---------- | ------- | --------- | ------ | ---- | -------- | --------- | --------- |
| 第0层 | 输入层 | - | - | - | - | - | - | 3@224x224 |
| 第1层 | 广义卷积层 | 卷积 | 11x11 | 96 | 4 | ReLU | 3@227x227 | 96@55x55 |
| 第1层 | 广义卷积层 | 池化 | 3x3 | - | 2 | - | 96@55x55 | 96@27x27 |
| 第1层 | 广义卷积层 | LRN | - | - | - | - | 96@27x27 | 96@27x27 |
| 第2层 | 广义卷积层 | 卷积 | 5x5 | 256 | 1 | ReLU | 96@27x27 | 256@27x27 |
| 第2层 | 广义卷积层 | 池化 | 3x3 | - | 2 | - | 256@27x27 | 256@13x13 |
| 第2层 | 广义卷积层 | LRN | - | - | - | - | 256@13x13 | 256@13x13 |
| 第3层 | 广义卷积层 | 卷积 | 3x3 | 384 | 1 | ReLU | 256@13x13 | 384@13x13 |
| 第4层 | 广义卷积层 | 卷积 | 3x3 | 384 | 1 | ReLU | 384@13x13 | 384@13x13 |
| 第5层 | 广义卷积层 | 卷积 | 3x3 | 256 | 1 | ReLU | 384@13x13 | 256@13x13 |
| 第5层 | 广义卷积层 | 池化 | 3x3 | - | 2 | - | 256@13x13 | 256@6x6 |
| 第6层 | 广义连接层 | 卷积 | 6x6 | 4096 | 1 | ReLU | 256@6x6 | 4096@1x1 |
| 第6层 | 广义连接层 | dropout | - | - | - | - | 4096@1x1 | 4096@1x1 |
| 第7层 | 广义连接层 | 全连接 | - | - | - | ReLU | 4096 | 4096 |
| 第7层 | 广义连接层 | dropout | - | - | - | - | 4096 | 4096 |
| 第8层 | 广义连接层 | 全连接 | - | - | - | - | 4096 | 1000 |
网络参数数量:总计约 6237 万。
输出
Tensor size
采用channel last
风格描述。即227x227x3
等价于前文的3@227x227
。第 6 层广义连接层的卷积的参数数量最多,约 3770 万,占整体六千万参数的 60%。
原因是该子层的卷积核较大、输入通道数量较大、输出通道数量太多。该卷积需要的参数数量为:$256\times 6\times 6\times 4096 = 37,748,736 。$
| 编号 | 网络层 | 子层 | 输出 Tensor size | 权重个数 | 偏置个数 | 参数数量 |
| ----- | ---------- | ------- | ---------------- | -------- | -------- | ---------- |
| 第0层 | 输入层 | - | 227x227x3 | 0 | 0 | 0 |
| 第1层 | 广义卷积层 | 卷积 | 55x55x96 | 34848 | 96 | 34944 |
| 第1层 | 广义卷积层 | 池化 | 27x27x96 | 0 | 0 | 0 |
| 第1层 | 广义卷积层 | LRN | 27x27x96 | 0 | 0 | 0 |
| 第2层 | 广义卷积层 | 卷积 | 27x27x256 | 614400 | 256 | 614656 |
| 第2层 | 广义卷积层 | 池化 | 13x13x256 | 0 | 0 | 0 |
| 第2层 | 广义卷积层 | LRN | 13x13x256 | 0 | 0 | 0 |
| 第3层 | 广义卷积层 | 卷积 | 13x13x384 | 884736 | 384 | 885120 |
| 第4层 | 广义卷积层 | 卷积 | 13x13x384 | 1327104 | 384 | 1327488 |
| 第5层 | 广义卷积层 | 卷积 | 13x13x256 | 884736 | 256 | 884992 |
| 第5层 | 广义卷积层 | 池化 | 6x6x256 | 0 | 0 | 0 |
| 第6层 | 广义连接层 | 卷积 | 4096×1 | 37748736 | 4096 | 37752832 |
| 第6层 | 广义连接层 | dropout | 4096×1 | 0 | 0 | 0 |
| 第7层 | 广义连接层 | 全连接 | 4096×1 | 16777216 | 4096 | 16781312 |
| 第7层 | 广义连接层 | dropout | 4096×1 | 0 | 0 | 0 |
| 第8层 | 广义连接层 | 全连接 | 1000×1 | 4096000 | 1000 | 4097000 |
| 总计 | - | - | - | - | - | 62,378,344 |
2.2 设计技巧
AlexNet
成功的主要原因在于:- 使用
ReLU
激活函数。 - 使用
dropout
、数据集增强 、重叠池化等防止过拟合的方法。 - 使用百万级的大数据集来训练。
- 使用
GPU
训练,以及的LRN
使用。 - 使用带动量的
mini batch
随机梯度下降来训练。
- 使用
2.2.1 数据集增强
AlexNet
中使用的数据集增强手段:随机裁剪、随机水平翻转:原始图片的尺寸为
256xx256
,裁剪大小为224x224
。每一个
epoch
中,对同一张图片进行随机性的裁剪,然后随机性的水平翻转。理论上相当于扩充了数据集$ (256-224)^2\times 2 = 2048$ 倍。在预测阶段不是随机裁剪,而是固定裁剪图片四个角、一个中心位置,再加上水平翻转,一共获得 10 张图片。
用这 10 张图片的预测结果的均值作为原始图片的预测结果。
PCA
降噪:对RGB
空间做PCA
变换来完成去噪功能。同时在特征值上放大一个随机性的因子倍数(单位1
加上一个$ \mathcal N(0,0.1)$ 的高斯绕动),从而保证图像的多样性。- 每一个
epoch
重新生成一个随机因子。 - 该操作使得错误率下降
1%
。
- 每一个
AlexNet
的预测方法存在两个问题:- 这种
固定裁剪四个角、一个中心
的方式,把图片的很多区域都给忽略掉了。很有可能一些重要的信息就被裁剪掉。 裁剪窗口重叠,这会引起很多冗余的计算。
改进的思路是:
执行所有可能的裁剪方式,对所有裁剪后的图片进行预测。将所有预测结果取平均,即可得到原始测试图片的预测结果。
减少裁剪窗口重叠部分的冗余计算。
具体做法为:将全连接层用等效的卷积层替代,然后直接使用原始大小的测试图片进行预测。将输出的各位置处的概率值按每一类取平均(或者取最大),则得到原始测试图像的输出类别概率。
下图中:上半图为
AlexNet
的预测方法;下半图为改进的预测方法。
- 这种
2.2.2 局部响应规范化
局部响应规范层
LRN
:目地是为了进行一个横向抑制,使得不同的卷积核所获得的响应产生竞争。LRN
层现在很少使用,因为效果不是很明显,而且增加了内存消耗和计算时间。- 在
AlexNet
中,该策略贡献了1.2%
的贡献率。
LRN
的思想:输出通道 i 在位置 (x,y) 处的输出会受到相邻通道在相同位置输出的影响。为了刻画这种影响,将输出通道 i 的原始值除以一个归一化因子。
其中:$a_i^{(x,y)} $为输出通道 i 在位置 $(x,y)$ 处的原始值$,\hat a_i^{(x,y)} $为归一化之后的值。$n $为影响第 $i $通道的通道数量(分别从左侧、右侧 $n/2 $个通道考虑)。$\alpha,\beta,k$ 为超参数。
一般考虑$ k=2,n=5,\alpha=10^{-4},\beta=0.75 。$
2.2.3 多 GPU 训练
AlexNet
使用两个GPU
训练。网络结构图由上、下两部分组成:一个GPU
运行图上方的通道数据,一个GPU
运行图下方的通道数据,两个GPU
只在特定的网络层通信。即:执行分组卷积。- 第二、四、五层卷积层的核只和同一个
GPU
上的前一层的feature map
相连。 - 第三层卷积层的核和前一层所有
GPU
的feature map
相连。 - 全连接层中的神经元和前一层中的所有神经元相连。
- 第二、四、五层卷积层的核只和同一个
2.2.4 重叠池化
一般的池化是不重叠的,池化区域的大小与步长相同。
Alexnet
中,池化是可重叠的,即:步长小于池化区域的大小。重叠池化可以缓解过拟合,该策略贡献了
0.4%
的错误率。为什么重叠池化会减少过拟合,很难用数学甚至直观上的观点来解答。一个稍微合理的解释是:重叠池化会带来更多的特征,这些特征很可能会有利于提高模型的泛化能力。
2.2.5 优化算法
AlexNet
使用了带动量的mini-batch
随机梯度下降法。标准的带动量的
mini-batch
随机梯度下降法为:而论文中,作者使用了修正:
- 其中$ \alpha=0.9 , \beta=0.0005 ,\epsilon $为学习率。
- $-\beta\epsilon\vec\theta$ 为权重衰减。论文指出:权重衰减对于模型训练非常重要,不仅可以起到正则化效果,还可以减少训练误差。
三、VGG-Net
VGG-Net
是牛津大学计算机视觉组和DeepMind
公司共同研发一种深度卷积网络,并且在 2014 年在ILSVRC
比赛上获得了分类项目的第二名和定位项目的第一名。VGG-Net
的主要贡献是:- 证明了小尺寸卷积核(
3x3
)的深层网络要优于大尺寸卷积核的浅层网络。 - 证明了深度对网络的泛化性能的重要性。
- 验证了尺寸抖动
scale jittering
这一数据增强技术的有效性。
- 证明了小尺寸卷积核(
VGG-Net
最大的问题在于参数数量,VGG-19
基本上是参数数量最多的卷积网络架构。
3.1 网络结构
VGG-Net
一共有五组结构(分别表示为:A~E
), 每组结构都类似,区别在于网络深度上的不同。结构中不同的部分用黑色粗体给出。
卷积层的参数为
convx-y
,其中x
为卷积核大小,y
为卷积核数量。如:
conv3-64
表示64
个3x3
的卷积核。卷积层的通道数刚开始很小(64 通道),然后在每个池化层之后的卷积层通道数翻倍,直到 512。
每个卷积层之后都跟随一个
ReLU
激活函数,表中没有标出。
通用结构:
输入层:固定大小的
224x224
的RGB
图像。卷积层:卷积步长均为 1。
填充方式:填充卷积层的输入,使得卷积前后保持同样的空间分辨率。
3x3
卷积:same
填充,即:输入的上下左右各填充 1 个像素。1x1
卷积:不需要填充。
卷积核尺寸:有
3x3
和1x1
两种。3x3
卷积核:这是捕获左右、上下、中心等概念的最小尺寸。1x1
卷积核:用于输入通道的线性变换。在它之后接一个
ReLU
激活函数,使得输入通道执行了非线性变换。
池化层:采用最大池化。
- 池化层连接在卷积层之后,但并不是所有的卷积层之后都有池化。
- 池化窗口为
2x2
,步长为 2 。
网络最后四层为::三个全连接层 + 一个
softmax
层。- 前两个全连接层都是 4096 个神经元,第三个全连接层是 1000 个神经元(因为执行的是 1000 类的分类)。
- 最后一层是
softmax
层用于输出类别的概率。
所有隐层都使用
ReLU
激活函数。
VGG-Net
网络参数数量:其中第一个全连接层的参数数量为:
7x7x512x4096=1.02亿
,因此网络绝大部分参数来自于该层。与
AlexNet
相比,VGG-Net
在第一个全连接层的输入feature map
较大:7x7 vs 6x6
,512 vs 256
。
| 网络 | A , A-LRN | B | C | D | E |
| -------- | --------- | ------ | ------ | ------ | ---- |
| 参数数量 | 1.13亿 | 1.33亿 | 1.34亿 | 1.38亿 | 1.44 |
3.2 设计技巧
输入预处理:通道像素零均值化。
先统计训练集中全部样本的通道均值:所有红色通道的像素均值 $\overline {Red} 、$所有绿色通道的像素均值$ \overline {Green} 、$所有蓝色通道的像素均值$ \overline {Blue} 。$
$\overline {Red} = \sum{n}\sum{i}\sum{j} I{n,0,i,j}\ \overline {Green} = \sum{n}\sum{i}\sum{j} I{n,1,i,j}\ \overline {Blue} = \sum{n}\sum{i}\sum{j} I{n,2,i,j}$
其中:假设红色通道为通道
0
,绿色通道为通道1
,蓝色通道为通道2
;n 遍历所有的训练样本$,i,j $遍历图片空间上的所有坐标。对每个样本:红色通道的每个像素值减去$ \overline {Red} ,$绿色通道的每个像素值减去$ \overline {Green} ,$蓝色通道的每个像素值减去 $\overline {Blue} 。$
多尺度训练:将原始的图像缩放到最小的边 $S>=224 ,$然后在整副图像上截取
224x224
的区域来训练。有两种方案:
在所有图像上固定$ S $:用 $S=256 $来训练一个模型,用 $S=384 $来训练另一个模型。最后使用两个模型来评估。
对每个图像,在 $[S{\min},S{\max}]$ 之间随机选取一个$ S$ ,然后进行裁剪来训练一个模型。最后使用单个模型来评估。
- 该方法只需要一个单一的模型。
- 该方法相当于使用了尺寸抖动(
scale jittering
) 的数据增强。
多尺度测试:将测试的原始图像等轴的缩放到预定义的最小图像边,表示为 $Q (Q$ 不一定等于$ S ),$称作测试尺度。
在一张测试图像的几个归一化版本上运行模型,然后对得到的结果进行平均。
- 不同版本对应于不同的$ Q $值。
所有版本都执行通道像素归一化。注意:采用训练集的统计量。
该方法相当于在测试时使用了尺寸抖动。实验结果表明:测试时的尺寸抖动导致了更好的性能。
评估有三种方案:
single-crop
:对测试图片沿着最短边缩放,然后选择其中的center crop
来裁剪图像,选择这个图像的预测结果作为原始图像的预测结果。该方法的缺点是:仅仅保留图片的中央部分可能会丢掉图片类别的关键信息。因此该方法很少在实际任务中使用,通常用于不同模型之间的性能比较。
multi-crop
:类似AlexNet
的做法,对每个测试图像获取多个裁剪图像,平均每个裁剪图像的预测结果为原始图像的预测结果。该方法的缺点是:需要网络重新计算每个裁剪图像,效率较低。
dense
:将最后三个全连接层用等效的卷积层替代,成为一个全卷积网络。其中:第一个全连接层用7x7
的卷积层替代,后面两个全连接层用1x1
的卷积层替代。该全卷积网络应用到整张图片上(无需裁剪),得到一个多位置的、各类别的概率字典。通过原始图片、水平翻转图片的各类别预测的均值,得到原始图片的各类别概率。
该方法的优点是:不需要裁剪图片,支持多尺度的图片测试,计算效率较高。
实验结果表明:
multi-crop
评估方式要比dense
评估方式表现更好。另外,二者是互补的,其组合要优于任何单独的一种。下表中,S=[256;512]
,Q={256,384,512} 。还有一种评估策略:
ensemble error
。即:同时训练同一种网络的多个不同的模型,然后用这几个模型的预测结果的平均误差作为最终的ensemble error
。有一种术语叫
single-model error
。它是训练一个模型,然后采用上述的多种crop/dense
评估的组合,这些组合的平均输出作为预测结果。
权重初始化:由于网络深度较深,因此网络权重的初始化很重要,设计不好的初始化可能会阻碍学习。
- 论文的权重初始化方案为:先训练结构
A
。当训练更深的配置时,使用结构A
的前四个卷积层和最后三个全连接层来初始化网络,网络的其它层被随机初始化。 - 作者后来指出:可以通过
Xavier
均匀初始化来直接初始化权重而不需要进行预训练。
- 论文的权重初始化方案为:先训练结构
实验结果表明:
- 分类误差随着网络深度的增加而减小。
- 从
A-LRN
和A
的比较发现:局部响应归一化层LRN
对于模型没有任何改善。
四、Inception
Inception
网络是卷积神经网络的一个重要里程碑。在Inception
之前,大部分流行的卷积神经网络仅仅是把卷积层堆叠得越来越多,使得网络越来越深。这使得网络越来越复杂,参数越来越多,从而导致网络容易出现过拟合,增加计算量。而
Inception
网络考虑的是多种卷积核的并行计算,扩展了网络的宽度。Inception Net
核心思想是:稀疏连接。因为生物神经连接是稀疏的。Inception
网络的最大特点是大量使用了Inception
模块。
4.1 Inception v1
4.1.1 网络结构
InceptionNet V1
是一个 22 层的深度网络。 如果考虑池化层,则有 29 层。如下图中的depth
列所示。网络具有三组
Inception
模块,分别为:inception(3a)/inception(3b)
、inception(4a)/inception(4b)/inception(4c)/inception(4d)/inception(4e)
、inception(5a)、inception(5b)
。三组Inception
模块被池化层分隔。下图给出了网络的层次结构和参数,其中:
type
列:给出了每个模块/层的类型。patch size/stride
列:给出了卷积层/池化层的尺寸和步长。output size
列:给出了每个模块/层的输出尺寸和输出通道数。depth
列:给出了每个模块/层包含的、含有训练参数层的数量。#1x1
列:给出了每个模块/层包含的1x1
卷积核的数量,它就是1x1
卷积核的输出通道数。#3x3 reduce
列:给出了每个模块/层包含的、放置在3x3
卷积层之前的1x1
卷积核的数量,它就是1x1
卷积核的输出通道数。#3x3
列:给出了每个模块/层包含的3x3
卷积核的数量,它就是3x3
卷积核的输出通道数。#5x5 reduce
列:给出了每个模块/层包含的、放置在5x5
卷积层之前的1x1
卷积核的数量,它就是1x1
卷积核的输出通道数。#5x5
列:给出了每个模块/层包含的5x5
卷积核的数量,它就是5x5
卷积核的输出通道数。pool proj
列:给出了每个模块/层包含的、放置在池化层之后的1x1
卷积核的数量,它就是1x1
卷积核的输出通道数。params
列:给出了每个模块/层的参数数量。ops
列:给出了每个模块/层的计算量。
Inception V1
的参数数量为 697.7 万,其参数数量远远小于AlexNet
(6 千万)、VGG-Net
(超过 1 亿)。Inception V1
参数数量能缩减的一个主要技巧是:在inception(5b)
输出到linear
之间插入一个平均池化层avg pool
。- 如果没有平均池化层,则
inception(5b)
到linear
之间的参数数量为:7x7x1024x1024
,约为 5 千万。 - 插入了平均池化层之后,
inception(5b)
到linear
之间的参数数量为:1x1x1024x1024
,约为 1 百万。
- 如果没有平均池化层,则
4.1.2 Inception 模块
原始的
Inception
模块对输入同时执行:3 个不同大小的卷积操作(1x1、3x3、5x5
)、1 个最大池化操作(3x3
)。所有操作的输出都在深度方向拼接起来,向后一级传递。三种不同大小卷积:通过不同尺寸的卷积核抓取不同大小的对象的特征。
使用
1x1、3x3、5x5
这些具体尺寸仅仅是为了便利性,事实上也可以使用更多的、其它尺寸的滤波器。1 个最大池化:提取图像的原始特征(不经过过滤器)。
原始
Inception
模块中,模块的输出通道数量为四个子层的输出通道数的叠加。这种叠加不可避免的使得Inception
模块的输出通道数增加,这就增加了Inception
模块中每个卷积的计算量。因此在经过若干个模块之后,计算量会爆炸性增长。解决方案是:在
3x3
和5x5
卷积层之前额外添加1x1
卷积层,来限制输入给卷积层的输入通道的数量。注意:
1x1
卷积是在最大池化层之后,而不是之前。这是因为:池化层是为了提取图像的原始特征,一旦它接在1x1
卷积之后就失去了最初的本意。1x1
卷积在3x3
、5x5
卷积之前。这是因为:如果1x1
卷积在它们之后,则3x3
卷积、5x5
卷积的输入通道数太大,导致计算量仍然巨大。
4.1.3 辅助分类器
为了缓解梯度消失的问题,
InceptionNet V1
给出了两个辅助分类器。这两个辅助分类器被添加到网络的中间层,它们和主分类器共享同一套训练数据及其标记。其中:第一个辅助分类器位于
Inception(4a)
之后,Inception(4a)
模块的输出作为它的输入。第二个辅助分类器位于
Inception(4d)
之后,Inception(4d)
模块的输出作为它的输入。两个辅助分类器的结构相同,包括以下组件:
- 一个尺寸为
5x5
、步长为3
的平均池化层。 - 一个尺寸为
1x1
、输出通道数为128
的卷积层。 - 一个具有
1024
个单元的全连接层。 - 一个
drop rate = 70%
的dropout
层。 - 一个使用
softmax
损失的线性层作为输出层。
- 一个尺寸为
在训练期间,两个辅助分类器的损失函数的权重是 0.3,它们的损失被叠加到网络的整体损失上。在推断期间,这两个辅助网络被丢弃。
在
Inception v3
的实验中表明:辅助网络的影响相对较小,只需要其中一个就能够取得同样的效果。事实上辅助分类器在训练早期并没有多少贡献。只有在训练接近结束,辅助分支网络开始发挥作用,获得超出无辅助分类器网络的结果。
两个辅助分类器的作用:提供正则化的同时,克服了梯度消失问题。
4.2 Inception v2
Inception v2
的主要贡献是提出了Batch Normalization
。论文指出,使用了Batch Normalization
之后:可以加速网络的学习。
相比
Inception v1
,训练速度提升了 14 倍。因为应用了BN
之后,网络可以使用更高的学习率,同时删除了某些层。网络具有更好的泛化能力。
在
ImageNet
分类问题的top5
上达到4.8%
,超过了人类标注top5
的准确率。
Inception V2
网络训练的技巧有:- 使用更高的学习率。
- 删除
dropout
层、LRN
层。 - 减小
L2
正则化的系数。 - 更快的衰减学习率。学习率以指数形式衰减。
- 更彻底的混洗训练样本,使得一组样本在不同的
epoch
中处于不同的mini batch
中。 - 减少图片的形变。
Inception v2
的网络结构比Inception v1
有少量改动:5x5
卷积被两个3x3
卷积替代。这使得网络的最大深度增加了 9 层,同时网络参数数量增加 25%,计算量增加 30%。
28x28
的inception
模块从 2 个增加到 3 个。在
inception
模块中,有的采用最大池化,有的采用平均池化。在
inception
模块之间取消了用作连接的池化层。inception(3c),inception(4e)
的子层采用步长为 2 的卷积/池化。Pool+proj
列给出了inception
中的池化操作。avg+32
意义为:平均池化层后接一个尺寸1x1
、输出通道32
的卷积层。max+pass through
意义为:最大池化层后接一个尺寸1x1
、输出通道数等于输入通道数的卷积层。
Inception V2
的网络参数约为1126
万。
| 层 | 参数数量 |
| ------------ | -------- |
| conv1 | 9408 |
| conv2 | 114688 |
| inception-3a | 218094 |
| inception-3b | 259072 |
| inception-3c | 384000 |
| inception-4a | 608193 |
| inception-4b | 663552 |
| inception-4c | 912384 |
| inception-4d | 1140736 |
| inception-4e | 1447936 |
| inception-5a | 2205696 |
| inception-5b | 2276352 |
| fc | 1024000 |
| 共 | 11264111 |
Inception V2
在ImageNet
测试集上的误差率:
4.3 Inception v3
虽然
Inception v1
的参数较少,但是它的结构比较复杂,难以进行修改。原因有以下两点:- 如果单纯的放大网络(如增加
Inception
模块的数量、扩展Inception
模块的大小),则参数的数量会显著增长,计算代价太大。 Inception v1
结构中的各种设计,其对最终结果的贡献尚未明确。因此
Inception v3
的论文重点探讨了网络结构设计的原则。
- 如果单纯的放大网络(如增加
4.3.1 网络结构
Inception v3
的网络深度为 42 层,它相对于Inception v1
网络主要做了以下改动:7x7
卷积替换为 3 个3x3
卷积。3 个
Inception
模块:模块中的5x5
卷积替换为 2 个3x3
卷积,同时使用后面描述的网格尺寸缩减技术。5 个
Inception
模块:模块中的5x5
卷积替换为 2 个3x3
卷积之后,所有的nxn
卷积进行非对称分解,同时使用后面描述的网格尺寸缩减技术。2 个
Inception
模块:结构如下。它也使用了卷积分解技术,以及网格尺寸缩减技术。
Inception v3
的网络结构如下所示:3xInception
表示三个Inception
模块,4xInception
表示四个Inception
模块,5xInception
表示五个Inception
模块。conv padded
表示使用 0 填充的卷积,它可以保持feature map
的尺寸。在
Inception
模块内的卷积也使用 0 填充,所有其它的卷积/池化不再使用填充。
在
3xInception
模块的输出之后设有一个辅助分类器。其结构如下:Inception v3
整体参数数量约 23,626,728 万(论文Xception: Deep Learning with Depthwise Separable Convolutions
)。
4.3.2 设计技巧
Inception v3
总结出网络设计的一套通用设计原则:避免
representation
瓶颈:representation
的大小应该从输入到输出缓缓减小,避免极端压缩。在缩小feature map
尺寸的同时,应该增加feature map
的通道数。representation
大小通常指的是feature map
的容量,即feature map
的width x height x channel
。空间聚合:可以通过空间聚合来完成低维嵌入,而不会在表达能力上有较大的损失。因此通常在
nxn
卷积之前,先利用1x1
卷积来降低输入维度。猜测的原因是:空间维度之间的强相关性导致了空间聚合过程中的信息丢失较少。
平衡网络的宽度和深度:增加网络的宽度或者深度都可以提高网络的泛化能力,因此计算资源需要在网络的深度和宽度之间取得平衡。
4.3.2.1 卷积尺寸分解
大卷积核的分解:将大卷积核分解为多个小的卷积核。
如:使用 2 个
3x3
卷积替换5x5
卷积,则其参数数量大约是 1 个5x5
卷积的 72% 。nxn
卷积核的非对称分解:将nxn
卷积替换为1xn
卷积和nx1
卷积。- 这种非对称分解的参数数量是原始卷积数量的 $\frac 2n $。随着
n
的增加,计算成本的节省非常显著。 论文指出:对于较大的
feature map
,这种分解不能很好的工作;但是对于中等大小的feature map
(尺寸在12~20
之间),这种分解效果非常好。
- 这种非对称分解的参数数量是原始卷积数量的 $\frac 2n $。随着
4.3.2.2 网格尺寸缩减
假设输入的
feature map
尺寸为dxd
,通道数为k
。如果希望输出的feature map
尺寸为d/2 x d/2
,通道数为2k
。则有以下的两种方式:首先使用
2k
个1x1
的卷积核,执行步长为 1 的卷积。然后执行一个2x2
的、步长为 2 的池化操作。该方式需要执行 $2d^2k^2 $次
乘-加
操作,计算代价较大。直接使用
2k
个1x1
的卷积核,执行步长为 2 的卷积。该方式需要执行$ 2(\frac{d}{2})^2k^2 $次
乘-加
操作,计算代价相对较小。但是表征能力下降,产生了表征瓶颈。事实上每个
Inception
模块都会使得feature map
尺寸缩半、通道翻倍,因此在这个过程中需要仔细设计网络,使得既能够保证网络的表征能力,又不至于计算代价太大。
解决方案是:采用两个模块
P
和C
。- 模块
P
:使用k
个1x1
的卷积核,执行步长为 2 的卷积。其输出feature map
尺寸为d/2 x d/2
,通道数为k
。 模块
C
:使用步长为 2 的池化。其输出feature map
尺寸为d/2 x d/2
,通道数为k
。将模块
P
和模块C
的输出按照通道数拼接,产生最终的输出feature map
。
- 模块
4.3.2.3 标签平滑正则化
标签平滑正则化的原理:假设样本的真实标记存在一定程度上的噪声。即:样本的真实标记不一定是可信的。
对给定的样本 $\mathbf{\vec x} ,$其真实标记为 $y 。$在普通的训练中,该样本的类别分布为一个 $\delta $函数:$P(Y=k\mid X=\mathbf{\vec x})=\delta(y-k),\quad k=1,2,\cdots,K。$记做$ \delta_{k,y} 。$
采用标签平滑正则化(
LSR:Label Smoothing Regularization
)之后,该样本的类别分布为:$P(Y=k\mid X=\mathbf{\vec x})=(1-\epsilon)\delta_{k,y}+\frac \epsilon K,\quad k=1,2,\cdots,K$
其中$ \epsilon $是一个很小的正数(如 0.1),其物理意义为:样本标签不可信的比例。
该类别分布的物理意义为:
- 样本 $\mathbf{\vec x} $的类别为 $y $的概率为 $1-\frac {(K-1)\epsilon}K $。
- 样本 $\mathbf{\vec x}$ 的类别为$ 1,2,\cdots,y-1,y+1,\dots,K $的概率均$ \frac \epsilon K $。
论文指出:标签平滑正则化对
top-1
错误率和top-5
错误率提升了大约 0.2% 。
4.4 Inception v4 & Inception - ResNet
Inception v4
和Inception-ResNet
在同一篇论文中给出。论文通过实验证明了:结合残差连接可以显著加速Inception
的训练。性能比较:(综合采用了
144 crops/dense
评估的结果,数据集:ILSVRC 2012
的验证集 )
| 网络 | crops | Top-1 Error | Top-5 Error |
| ------------------- | ----- | ----------- | ----------- |
| ResNet-151 | dense | 19.4% | 4.5% |
| Inception-v3 | 144 | 18.9% | 4.3% |
| Inception-ResNet-v1 | 144 | 18.8% | 4.3% |
| Inception-v4 | 144 | 17.7% | 3.8% |
| Inception-ResNet-v2 | 144 | 17.8% | 3.7% |
Inception-ResNet-v2
参数数量约为 5500 万,Inception-ResNet-v1/Inception-v4
的参数数量也在该量级。
4.4.1 Inception v4
在
Inception v4
结构的主要改动:修改了
stem
部分。引入了
Inception-A
、Inception-B
、Inception-C
三个模块。这些模块看起来和Inception v3
变体非常相似。Inception-A/B/C
模块中,输入feature map
和输出feature map
形状相同。而Reduction-A/B
模块中,输出feature map
的宽/高减半、通道数增加。引入了专用的“缩减块”(
reduction block
),它被用于缩减feature map
的宽、高。早期的版本并没有明确使用缩减块,但是也实现了其功能。
Inception v4
结构如下:(没有标记V
的卷积使用same
填充;标记V
的卷积使用valid
填充)stem
部分的结构:Inception-A
模块(这样的模块有 4 个):Inception-B
模块(这样的模块有 7 个):Inception-C
模块(这样的模块有 3 个):Reduction-A
模块:(其中 k,l,m,n 分别表示滤波器的数量)
| 网络 | k | l | m | n |
| ------------------- | ---- | ---- | ---- | ---- |
| Inception-v4 | 192 | 224 | 256 | 384 |
| Inception-ResNet-v1 | 192 | 192 | 256 | 384 |
| Inception-ResNet-v2 | 256 | 256 | 256 | 384 |
- `Reduction-B`模块:
![img](http://www.huaxiaozhuan.com/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/imgs/dl_cnn_classification/inception_v4_reduce_B.png)
4.4.2 Inception-ResNet
在
Inception-ResNet
中,使用了更廉价的Inception
块:inception
模块的池化运算由残差连接替代。在
Reduction
模块中能够找到池化运算。
2) Inception ResNet
有两个版本:v1
和 v2
。
v1
的计算成本和Inception v3
的接近,v2
的计算成本和Inception v4
的接近。v1
和v2
具有不同的stem
。- 两个版本都有相同的模块
A、B、C
和缩减块结构,唯一不同在于超参数设置。
3) Inception-ResNet-v1
结构如下:
stem
部分的结构:Inception-ResNet-A
模块(这样的模块有 5 个):Inception-B
模块(这样的模块有 10 个):Inception-C
模块(这样的模块有 5 个):Reduction-A
模块:同inception_v4
的Reduction-A
模块Reduction-B
模块:
4) Inception-ResNet-v2
结构与Inception-ResNet-v1
基本相同 :
stem
部分的结构:同inception_v4
的stem
部分。Inception-ResNet-v2
使用了inception v4
的stem
部分,因此后续的通道数量与Inception-ResNet-v1
不同。Inception-ResNet-A
模块(这样的模块有 5 个):它的结构与Inception-ResNet-v1
的Inception-ResNet-A
相同,只是通道数发生了改变。Inception-B
模块(这样的模块有 10 个):它的结构与Inception-ResNet-v1
的Inception-ResNet-B
相同,只是通道数发生了改变。Inception-C
模块(这样的模块有 5 个):它的结构与Inception-ResNet-v1
的Inception-ResNet-C
相同,只是通道数发生了改变。
Reduction-A
模块:同inception_v4
的Reduction-A
模块。Reduction-B
模块:它的结构与Inception-ResNet-v1
的Reduction-B
相同,只是通道数发生了改变。
5) 如果滤波器数量超过 1000,则残差网络开始出现不稳定,同时网络会在训练过程早期出现“死亡”:经过成千上万次迭代之后,在平均池化之前的层开始只生成 0 。
解决方案:在残差模块添加到activation
激活层之前,对其进行缩放能够稳定训练。降低学习率或者增加额外的BN
都无法避免这种状况。
这就是Inception ResNet
中的 Inception-A,Inception-B,Inception-C
为何如此设计的原因。
- 将
Inception-A,Inception-B,Inception-C
放置在两个Relu activation
之间。 - 通过线性的
1x1 Conv
(不带激活函数)来执行对残差的线性缩放。
4.5 Xception
一个常规的卷积核尝试在三维空间中使用滤波器抽取特征,包括:两个空间维度(宽度和高度)、一个通道维度。因此单个卷积核的任务是:同时映射跨通道的相关性和空间相关性。
Inception
将这个过程明确的分解为一系列独立的相关性的映射:要么考虑跨通道相关性,要么考虑空间相关性。Inception
的做法是:- 首先通过一组
1x1
卷积来查看跨通道的相关性,将输入数据映射到比原始输入空间小的三个或者四个独立空间。 然后通过常规的
3x3
或者5x5
卷积,将所有的相关性(包含了跨通道相关性和空间相关性)映射到这些较小的三维空间中。一个典型的
Inception
模块(Inception V3
)如下:可以简化为:
- 首先通过一组
Xception
将这一思想发挥到极致:首先使用1x1
卷积来映射跨通道相关性,然后分别映射每个输出通道的空间相关性,从而将跨通道相关性和空间相关性解耦。因此该网络被称作Xception:Extreme Inception
,其中的Inception
块被称作Xception
块。Xception
块类似于深度可分离卷积,但是它与深度可分离卷积之间有两个细微的差异:操作顺序不同:
- 深度可分离卷积通常首先执行
channel-wise
空间卷积,然后再执行1x1
卷积。 Xception
块首先执行1x1
卷积,然后再进行channel-wise
空间卷积。
- 深度可分离卷积通常首先执行
第一次卷积操作之后是否存在非线性:
- 深度可分离卷积只有第二个卷积(
1x1
)使用了ReLU
非线性激活函数,channel-wise
空间卷积不使用非线性激活函数。 Xception
块的两个卷积(1x1
和3x3
)都使用了ReLU
非线性激活函数。
其中第二个差异更为重要。
- 深度可分离卷积只有第二个卷积(
对
Xception
进行以下的修改,都可以加快网络收敛速度,并获取更高的准确率:- 引入类似
ResNet
的残差连接机制。 - 在
1x1
卷积和3x3
卷积之间不加入任何非线性。
- 引入类似
Xception
的参数数量与Inception V3
相同,但是性能表现显著优于Inception V3
。这表明Xception
更加高效的利用了模型参数。根据论文
Xception: Deep Learning with Depthwise Separable Convolutions
,Inception V3
参数数量为 23626728,Xception
参数数量为 22855952 。在
ImageNet
上的benchmark
为(单个模型,单次crop
):
| 模型 | top-1 accuracy | top-5 accuracy |
| ------------ | -------------- | -------------- |
| VGG-16 | 71.5% | 90.1% |
| ResNet-152 | 77.0% | 93.3% |
| Inception V3 | 78.2% | 94.1% |
| Xception | 79.0% | 94.5% |
五、ResNet
ResNet
提出了一种残差学习框架来解决网络退化问题,从而训练更深的网络。这种框架可以结合已有的各种网络结构,充分发挥二者的优势。ResNet
以三种方式挑战了传统的神经网络架构:ResNet
通过引入跳跃连接来绕过残差层,这允许数据直接流向任何后续层。这与传统的、顺序的
pipeline
形成鲜明对比:传统的架构中,网络依次处理低级feature
到高级feature
。ResNet
的层数非常深,高达 1202 层。而ALexNet
这样的架构,网络层数要小两个量级。通过实验发现,训练好的
ResNet
中去掉单个层并不会影响其预测性能。而训练好的AlexNet
等网络中,移除层会导致预测性能损失。
在
ImageNet
分类数据集中,拥有 152 层的残差网络,以3.75% top-5
的错误率获得了ILSVRC 2015
分类比赛的冠军。很多证据表明:残差学习是通用的,不仅可以应用于视觉问题,也可应用于非视觉问题。
5.1 网络退化问题
学习更深的网络的一个障碍是梯度消失/爆炸,该问题可以通过
Batch Normalization
在很大程度上解决。ResNet
论文作者发现:随着网络的深度的增加,准确率达到饱和之后迅速下降,而这种下降不是由过拟合引起的。这称作网络退化问题。如果更深的网络训练误差更大,则说明是由于优化算法引起的:越深的网络,求解优化问题越难。如下所示:更深的网络导致更高的训练误差和测试误差。
理论上讲,较深的模型不应该比和它对应的、较浅的模型更差。因为较深的模型是较浅的模型的超空间。较深的模型可以这样得到:先构建较浅的模型,然后添加很多恒等映射的网络层。
实际上我们的较深的模型后面添加的不是恒等映射,而是一些非线性层。因此,退化问题表明:通过多个非线性层来近似横等映射可能是困难的。
解决网络退化问题的方案:学习残差。
5.2 残差块
假设需要学习的是映射$ \mathbf{\vec y}=H(\mathbf{\vec x}) ,$残差块使用堆叠的非线性层拟合残差:$\mathbf{\vec y}=F(\mathbf{\vec x},\mathbf W_i)+\mathbf{\vec x} 。$
其中:
$\mathbf{\vec x} $和 $\mathbf{\vec y} $是块的输入和输出向量。
$F(\mathbf{\vec x},\mathbf W_i) $是要学习的残差映射。因为 $F(\mathbf{\vec x},\mathbf W_i)=H(\mathbf{\vec x})-\mathbf{\vec x} ,$因此称 F 为残差。
+
:通过快捷连接
逐个元素相加来执行。快捷连接
指的是那些跳过一层或者更多层的连接。- 快捷连接简单的执行恒等映射,并将其输出添加到堆叠层的输出。
- 快捷连接既不增加额外的参数,也不增加计算复杂度。
相加之后通过非线性激活函数,这可以视作对整个残差块添加非线性,即 $\text{relu}(\mathbf{\vec y}) $。
前面给出的残差块隐含了一个假设:$F(\mathbf{\vec x},\mathbf W_i) $和 $\mathbf{\vec x} $的维度相等。如果它们的维度不等,则需要在快捷连接中对 $\mathbf{\vec x} $执行线性投影来匹配维度:$\mathbf{\vec y}=F(\mathbf{\vec x},\mathbf W_i)+\mathbf W_s\mathbf{\vec x} 。$
事实上当它们维度相等时,也可以执行线性变换。但是实践表明:使用恒等映射足以解决退化问题,而使用线性投影会增加参数和计算复杂度。因此 $\mathbf W_s $仅在匹配维度时使用。
残差函数 F 的形式是可变的。
层数可变:论文中的实验包含有两层堆叠、三层堆叠,实际任务中也可以包含更多层的堆叠。
如果 F 只有一层,则残差块退化线性层:$\mathbf{\vec y} = \mathbf W\mathbf{\vec x}+\mathbf{\vec x} 。$此时对网络并没有什么提升。
连接形式可变:不仅可用于全连接层,可也用于卷积层。此时 F 代表多个卷积层的堆叠,而最终的逐元素加法
+
在两个feature map
上逐通道进行。此时
x
也是一个feature map
,而不再是一个向量。
残差学习成功的原因:学习残差$ F(\mathbf{\vec x},\mathbf W_i) $比学习原始映射$ H(\mathbf{\vec x}) $要更容易。
当原始映射 H 就是一个恒等映射时,F 就是一个零映射。此时求解器只需要简单的将堆叠的非线性连接的权重推向零即可。
实际任务中原始映射 H 可能不是一个恒等映射:
- 如果 H 更偏向于恒等映射(而不是更偏向于非恒等映射),则 F 就是关于恒等映射的抖动,会更容易学习。
- 如果原始映射 H 更偏向于零映射,那么学习 H 本身要更容易。但是在实际应用中,零映射非常少见,因为它会导致输出全为 0。
如果原始映射 H 是一个非恒等映射,则可以考虑对残差模块使用缩放因子。如
Inception-Resnet
中:在残差模块与快捷连接叠加之前,对残差进行缩放。注意:
ResNet
作者在随后的论文中指出:不应该对恒等映射进行缩放。因此Inception-Resnet
对残差模块进行缩放。可以通过观察残差 F 的输出来判断:如果 F 的输出均为 0 附近的、较小的数,则说明原始映射 H 更偏向于恒等映射;否则,说明原始映射 H 更偏向于非横等映射。
5.3 ResNet 分析
Veit et al.
认为ResNet
工作较好的原因是:一个ResNet
网络可以看做是一组较浅的网络的集成模型。但是
ResNet
的作者认为这个解释是不正确的。因为集成模型要求每个子模型是独立训练的,而这组较浅的网络是共同训练的。论文
《Residual Networks Bahave Like Ensemble of Relatively Shallow Networks》
对ResNet
进行了深入的分析。通过分解视图表明:
ResNet
可以被视作许多路径的集合。通过研究
ResNet
的梯度流表明:网络训练期间只有短路径才会产生梯度流,深的路径不是必须的。通过破坏性实验,表明:
- 即使这些路径是共同训练的,它们也不是相互依赖的。
- 这些路径的行为类似集成模型,其预测准确率平滑地与有效路径的数量有关。
5.3.1 分解视图
考虑从输出$ \mathbf {\vec y}_0 $到$ \mathbf {\vec y}_3$ 的三个
ResNet
块构建的网络。根据:下图中:左图为原始形式,右图为分解视图。分解视图中展示了数据从输入到输出的多条路径。
对于严格顺序的网络(如
VGG
),这些网络中的输入总是在单个路径中从第一层直接流到最后一层。如下图所示。分解视图中, 每条路径可以通过二进制编码向量 $\mathbf {\vec b} =(b_1,b_2,\cdots,b_n),\quad b_i\in {0,1} $来索引:如果流过残差块$ f_i ,$则 $b_i=1 ;$如果跳过残差块$ f_i ,$则$ b_i=0 。$
因此
ResNet
从输入到输出具有$ 2^n$ 条路径,第 $i$ 个残差块$ f_i $的输入汇聚了之前的$ i-1 $个残差块的$ 2^{i-1} $条路径。普通的前馈神经网络也可以在单个神经元(而不是网络层)这一粒度上运用分解视图,这也可以将网络分解为不同路径的集合。
它与
ResNet
分解的区别是:- 普通前馈神经网络的神经元分解视图中,所有路径都具有相同的长度。
ResNet
网络的残差块分解视图中,所有路径具有不同的路径长度。
5.3.2 路径长度分析
ResNet
中,从输入到输出存在许多条不同长度的路径。这些路径长度的分布服从二项分布。对于 n 层深的ResNet
,大多数路径的深度为 $\frac n2 。$下图为一个 54 个块的
ResNet
网络的路径长度的分布 ,其中95%
的路径只包含 19 ~ 35 个块。
5.3.3 路径梯度分析
ResNet
中,路径的梯度幅度随着它在反向传播中经过的残差块的数量呈指数减小。因此,训练期间大多数梯度来源于更短的路径。对于一个包含 54 个残差块的
ResNet
网络:下图表示:单条长度为 k 的路径在反向传播到
input
处的梯度的幅度的均值,它刻画了长度为 k 的单条路径的对于更新的影响。因为长度为 k 的路径有多条,因此取其平均。
下图表示:长度为 k 的所有路径在反向传播到
input
处的梯度的幅度的和。它刻画了长度为 k 的所有路径对于更新的影响。它不仅取决于长度为 k 的单条路径的对于更新的影响,还取决于长度为 k 的单条路径的数量。
有效路径:反向传播到
input
处的梯度幅度相对较大的路径。ResNet
中有效路径相对较浅,而且有效路径数量占比较少。在一个 54 个块的ResNet
网络中:- 几乎所有的梯度更新都来自于长度为 5~17 的路径。
- 长度为 5~17 的路径占网络所有路径的 0.45% 。
论文从头开始重新训练
ResNet
,同时在训练期间只保留有效路径,确保不使用长路径。实验结果表明:相比于完整模型的 6.10% 的错误率,这里实现了 5.96% 的错误率。二者没有明显的统计学上的差异,这表明确实只需要有效路径。因此,
ResNet
不是让梯度流流通整个网络深度来解决梯度消失问题,而是引入能够在非常深的网络中传输梯度的短路径来避免梯度消失问题。和
ResNet
原理类似,随机深度网络起作用有两个原因:- 训练期间,网络看到的路径分布会发生变化,主要是变得更短。
- 训练期间,每个
mini-batch
选择不同的短路径的子集,这会鼓励各路径独立地产生良好的结果。
5.3.4 路径破坏性分析
在
ResNet
网络训练完成之后,如果随机丢弃单个残差块,则测试误差基本不变。因为移除一个残差块时,ResNet
中路径的数量从$ 2^n $减少到$ 2^{n-1},$留下了一半的路径。在
VGG
网络训练完成之后,如果随机丢弃单个块,则测试误差急剧上升,预测结果就跟随机猜测差不多。因为移除一个块时,VGG
中唯一可行的路径被破坏。删除
ResNet
残差块通常会删除长路径。当删除了 $k $个残差块时,长度为$ x $的路径的剩余比例由下式给定:$percent=\frac {C_{n-k}^x}{C_n^x} 。$
下图中:
- 删除 10 个残差模块,一部分有效路径(路径长度为
5~17
)仍然被保留,模型测试性能会部分下降。 删除 20 个残差模块,绝大部分有效路径(路径长度为
5~17
)被删除,模型测试性能会大幅度下降。
- 删除 10 个残差模块,一部分有效路径(路径长度为
ResNet
网络中,路径的集合表现出一种类似集成模型的效果。一个关键证据是:它们的整体表现平稳地取决于路径的数量。随着网络删除越来越多的残差块,网络路径的数量降低,测试误差平滑地增加(而不是突变)。如果在测试时重新排序网络的残差块,这意味着交换了低层映射和高层映射。采用
Kendall Tau rank
来衡量网络结构被破坏的程度,结果表明:随着Kendall Tau rank
的增加,预测错误率也在增加。
5.4 网络性能
plain
网络:一些简单网络结构的叠加,如下图所示。图中给出了四种plain
网络,它们的区别主要是网络深度不同。其中,输入图片尺寸 224x224 。ResNet
简单的在plain
网络上添加快捷连接来实现。FLOPs
:floating point operations
的缩写,意思是浮点运算量,用于衡量算法/模型的复杂度。FLOPS
:floating point per second
的缩写,意思是每秒浮点运算次数,用于衡量计算速度。相对于输入的
feature map
,残差块的输出feature map
尺寸可能会发生变化:输出
feature map
的通道数增加,此时需要扩充快捷连接的输出feature map
。否则快捷连接的输出feature map
无法和残差块的feature map
累加。有两种扩充方式:
- 直接通过 0 来填充需要扩充的维度,在图中以实线标识。
- 通过
1x1
卷积来扩充维度,在图中以虚线标识。
输出
feature map
的尺寸减半。此时需要对快捷连接执行步长为 2 的池化/卷积:如果快捷连接已经采用1x1
卷积,则该卷积步长为 2 ;否则采用步长为 2 的最大池化 。
计算复杂度:
| | VGG-19 | 34层 plain 网络 | Resnet-34 |
| ----------------- | ------------ | --------------- | ----------- |
| 计算复杂度(FLOPs) | 19.6 billion | 3.5 billion | 3.6 billion |
模型预测能力:在
ImageNet
验证集上执行10-crop
测试的结果。A
类模型:快捷连接中,所有需要扩充的维度的填充 0 。B
类模型:快捷连接中,所有需要扩充的维度通过1x1
卷积来扩充。C
类模型:所有快捷连接都通过1x1
卷积来执行线性变换。可以看到
C
优于B
,B
优于A
。但是C
引入更多的参数,相对于这种微弱的提升,性价比较低。所以后续的ResNet
均采用B
类模型。
| 模型 | top-1 误差率 | top-5 误差率 |
| ----------- | ------------ | ------------ |
| VGG-16 | 28.07% | 9.33% |
| GoogleNet | - | 9.15% |
| PReLU-net | 24.27% | 7.38% |
| plain-34 | 28.54% | 10.02% |
| ResNet-34 A | 25.03% | 7.76% |
| ResNet-34 B | 24.52% | 7.46% |
| ResNet-34 C | 24.19% | 7.40% |
| ResNet-50 | 22.85% | 6.71% |
| ResNet-101 | 21.75% | 6.05% |
| ResNet-152 | 21.43% | 5.71% |
六、ResNet 变种
6.1 恒等映射修正
- 在论文
《Identity Mappings in Deep Residual Networks》
中,ResNet
的作者通过实验证明了恒等映射的重要性,并且提出了一个新的残差单元来简化恒等映射。
6.1.1 新残差块
新的残差单元中,恒等映射添加到
ReLU
激活函数之后。它使得训练变得更简单,并且提高了网络的泛化能力。假设 $\mathbf{\vec x}l $是第$ l $个残差单元的输入特征$;\mathcal W_l={\mathbf W{l,k}\mid 1\le k \le K} $为一组与第$ l $个残差单元相关的权重(包括偏置项)$,K$ 是残差单元中的层的数量;$ \mathcal F $代表残差函数。则第$ l$ 个残差单元的输出为(它也等价于第$ l+1$ 个残差单元的输入):
$\mathbf{\vec x}_{l+1}=\mathbf{\vec x}_l+\mathcal F(\mathbf{\vec x}_l,\mathcal W_l)$
考虑递归,对于任意深的残差单元 L ,则有:
因此,对任意深的单元$ L $,其输入特征 $\mathbf{\vec x}L$ 可以表示为浅层单元$ l $的特征$ \mathbf{\vec x}_l $加上一个形如$ \sum{i=l}^{L-1}\mathcal F(\mathbf{\vec x}_i,\mathcal W_i) $的残差函数。
这意味着:任意单元$ L$ 和 $l $之间都具有残差性。
对于任意深的单元$ L ,$其输入特征$ \mathbf{\vec x}L$ 可以表示为$:\mathbf{\vec x}{L}=\mathbf{\vec x}{0}+\sum{i=0}^{L-1}\mathcal F(\mathbf{\vec x}_i,\mathcal W_i) $。即:之前所有残差函数输出的总和,再加上 $\mathbf{\vec x}_0 。$
与之形成鲜明对比的是常规网络中,输入特征$ \mathbf{\vec x}L $是一系列矩阵向量的乘积。即为:$\mathbf{\vec x}{L}=\prod_{i=0}^{L-1}\mathbf W_i\mathbf{\vec x_0} $(忽略了激活函数和
BN
)。新的残差单元也更具有良好的反向传播特性。对于损失函数$ \mathcal L ,$有:
可以看到:
梯度$ \frac{\partial \mathcal L}{\partial \mathbf{\vec x}_l} $可以分解为两个部分:
- $\frac{\partial \mathcal L}{\partial \mathbf{\vec x}_L} $:直接传递信息而不涉及任何权重。它保证了信息能够直接传回给任意浅层 l 。
- $\left(\frac{\partial \sum_{i=l}^{L-1}\mathcal F(\mathbf{\vec x}_i,\mathcal W_i)}{\partial \mathbf{\vec x}_l}\right)^T\frac{\partial \mathcal L}{\partial \mathbf{\vec x}_L} $:通过各权重层来传递。
在一个
mini-batch
中,不可能出现梯度消失的情况。可能对于某个样本,存在$ \frac{\partial \sum{i=l}^{L-1}\mathcal F(\mathbf{\vec x}_i,\mathcal W_i)}{\partial \mathbf{\vec x}_l}=-1 $的情况,但是不可能出现
mini-batch
中所有的样本满足 $\frac{\partial \sum{i=l}^{L-1}\mathcal F(\mathbf{\vec x}_i,\mathcal W_i)}{\partial \mathbf{\vec x}_l}=-1 。$这意味着:哪怕权重是任意小的,也不可能出现梯度消失的情况。
对于旧的残差单元,由于恒等映射还需要经过
ReLU
激活函数,因此当 $\mathbf{\vec x}+\mathcal F(\mathbf{\vec x},\mathcal W) <0$ 时饱和,其梯度为 0 。
根据
3.
和4.
的讨论表明:在前向和反向阶段,信号都能够直接传递到任意单元。
6.1.2 快捷连接验证
假设可以对快捷连接执行缩放(如线性的
1x1
卷积),第 l 个残差单元的缩放因子为$ \lambdal ,$其中$ \lambda_l$ 也是一个可以学习的参数。此时有:$\mathbf{\vec x}{l+1}=\lambdal\mathbf{\vec x}_l+\mathcal F(\mathbf{\vec x}_l,\mathcal W_l) ,以及:\mathbf{\vec x}{L}=(\prod_{i=l}^{L-1}\lambda_i)\mathbf{\vec x}_l+\sum{i=l}^{L-1}(\prod{j=i+1}^{L-1}\lambda_j)\mathcal F(\mathbf{\vec x}_i,\mathcal W_i) 。$令:$\hat { \mathcal F}(\mathbf{\vec x}i,\mathcal W_i) =(\prod{j=i+1}^{L-1}\lambda_j)\mathcal F(\mathbf{\vec x}_i,\mathcal W_i),$则有:
对于特别深的网络:如果$ \lambdai \gt 1,\text{for all} \;i ,$ 则$ \prod{i=l}^{L-1}\lambdai $发生梯度爆炸;如果 $\lambda_i \lt 1,\text{for all} \;i , $则 $\prod{i=l}^{L-1}\lambda_i $发生梯度消失。这会丧失快捷连接的好处。
如果对快捷连接执行的不是线性缩放,而是一个复杂的函数$ hl ,$则上式括号中第一部分变成$:\prod{i=l}^{L-1} h_i^{\prime} 。$其中 $h_i^\prime 为 h_i $的导数。
这也会丧失快捷连接的好处,阻碍梯度的传播。
下图所示为对快捷连接进行的各种修改:
为了简化,这里没有画出
BN
层。每个权重层的后面实际上都有一个BN
层。(a)
:原始的、旧的残差块。(b)
:对所有的快捷连接设置缩放。其中缩放因子$ \lambda=0.5 。$残差有两种配置:缩放(缩放因子 0.5)、不缩放。
(c)
:对快捷连接执行门控机制。残差由$ g$ 来缩放,快捷连接由 $1-g $来缩放。其中$ g(\mathbf{\vec x}) = \sigma(\mathbf W_g\mathbf{\vec x})+\mathbf{\vec b}_g , \sigma(z) = \frac{1}{1+e^{-z}} 。$
(d)
:对快捷连接执行门控机制,但是残差并不进行缩放。(e)
: 对快捷连接执行1x1
卷积。(f)
:对快捷连接执行dropout
,其中遗忘比例为 0.5 。在统计学上,它等效于一个缩放比例为 0.5 的缩放操作。
在
CIFAR-10
上利用ResNet-110
的测试误差如下:(fail
表示测试误差超过 20% )on shortcut
和on F
列分别给出了快捷连接、残差块上的缩放比例。
最终结果表明:快捷连接是信息传递最直接的路径,快捷连接中的各种操作都会阻碍信息的传递,以致于对优化造成困难。
理论上,对快捷连接执行
1x1
卷积,会引入更多的参数。它应该比恒等连接具备更强大的表达能力。事实上,其训练误差要比恒等连接的训练误差高的多。这意味着模型退化是因为优化问题,而不是网络表达能力的问题。
6.1.3 激活函数验证
设残差块之间的函数为 f ,即:
+
之后引入 f :$\mathbf{\vec y}l=\mathbf{\vec x}_l+\mathcal F(\mathbf{\vec x}_l,\mathcal W_l),\quad \mathbf{\vec x}{l+1} = f(\mathbf{\vec y}_l)$
前面的理论推导均假设$ f $为恒等映射 $f(z) = z ,$而上面的实验中 $f(z) = ReLU(z) $。因此接下来考察 f 的影响。
如下图所示,组件都相同,但是不同的组合导致不同的残差块或 $f 。$
(a)
:原始的、旧的残差块,$ f(z)=ReLU(z) 。$(b)
:将BN
移动到addition
之后$, f(z)=ReLU(BN(z)) 。$(c)
:将ReLU
移动到addition
之前$,f(z) = z。$这种结构问题较大,因为理想的残差块的输出范围是 $(-\infty,+\infty) 。$这里的残差块经过个
ReLU
之后的输出为非负,从而使得残差的输出为$ [0,+\infty),$从而使得前向信号会逐级递增。这会影响网络的表达能力。(d)
:将ReLU
移动到残差块之前,$f(z) = z。$(e)
: 将BN
和ReLU
移动到残差块之前$,f(z) = z。$
最终结果表明:
full pre-activation
效果最好。有两个原因:快捷连接通路是顺畅的,这使得优化更加简单。
对两个权重层的输入都执行了
BN
。所有其它四组结构中,只有第二个权重层的输入的到了标准化,第一个权重层的输入并未的到标准化。
6.1.4 网络性能
- 在
ILSVRC 2012
验证集上的评估结果:
| 方法 | 数据集增强 | train crop | test crop | top-1 误差 | top-5 误差 |
| ------------------------------- | ----------------- | ---------- | --------- | ---------- | ---------- |
| ResNet-152,原始残差块 | scale | 224x224 | 224x224 | 23.0% | 6.7% |
| ResNet-152,原始残差块 | scale | 224x224 | 320x320 | 21.3% | 5.5% |
| ResNet-152,full pre-activation | scale | 224x224 | 320x320 | 21.1% | 5.5% |
| ResNet-200,原始残差块 | scale | 224x224 | 320x320 | 21.8% | 6.0% |
| ResNet-200,full pre-activation | scale | 224x224 | 320x320 | 20.7% | 5.3% |
| ResNet-200,full pre-activation | scale + asp ratio | 224x224 | 320x320 | 20.1% | 4.8% |
| Inception v3 | scale + asp ratio | 299x299 | 299x299 | 21.2% | 5.6% |
6.2 ResNeXt
通常提高模型准确率的方法是加深网络深度或者加宽网络宽度,但这些方法会增加超参数的数量、参数数量和计算量。
ResNeXt
网络可以在不增加网络参数复杂度的前提下提高准确率,同时还减少了超参数的数量。ResNeXt
的设计参考了VGG
和Inception
的设计哲学。VGG
:网络通过简单地层叠相同结构的层来实现,因此网络结构简单。其缺点是网络参数太多,计算量太大。Inception
:通过执行分裂-变换-合并
策略来精心设计拓扑结构,使得网络参数较少,计算复杂度较低。这种分裂-变换-合并
行为预期能够达到一个大的dense
层的表达能力,但是计算复杂度要低的多。其缺点是:
- 每个“变换”中,滤波器的数量和尺寸等超参数都需要精细的设计。
- 一旦需要训练新的任务(如新任务是一个
NLP
任务),可能需要重新设计网络结构。因此可扩展性不高。
ResNeXt
结合了二者的优点:- 网络结构也是通过简单地层叠相同结构的层来实现。
- 网络的每一层都执行了
分裂-变换-合并
策略。
在相同的参数数量和计算复杂度的情况下,
ResNeXt
的预测性能要优于ResNet
。- 它在
ILSVRC 2016
分类任务中取得了第二名的成绩。 101
层的ResNeXt
就能够获得超过200
层ResNet
的准确率,并且计算量只有后者的一半。
- 它在
ResNeXt
改进了ResNet
网络结构,并提出了一个新的维度,称作“基数”cardinality
。基数是网络的深度和网络的宽度之外的另一个重要因素。作者通过实验表明:增加基数比增加网络的深度或者网络的宽度更有效。
6.2.1 分裂-变换-合并
考虑全连接网络中的一个神经元。假设输入为$ \mathbf{\vec x}=(x_1,x_2,\cdots,xD) ,$为一个一度的输入向量(长度为 D )。假设对应的权重为 $\mathbf{\vec w}=(w_1,w_2,\cdots,w_D)。$不考虑偏置和激活函数,则神经元的输出为:$\sum{i=1}^Dw_ix_i $。
它可以视作一个最简单的“分裂-变换-合并”:
- 分裂:输入被分割成$ D $个低维(维度为零)嵌入。
- 变换:每个低维嵌入通过对应的权重$ w_i$ 执行线性变换。
- 合并:变换之后的结果通过直接相加来合并。
Inception
的“分裂-变换-合并”策略:- 分裂:输入通过
1x1
卷积被分割成几个低维嵌入。 - 变换:每个低维嵌入分别使用一组专用滤波器(
3x3
、5x5
等) 执行变换。 - 合并:变换之后的结果进行合并(沿深度方向拼接)。
- 分裂:输入通过
对一个
ResNeXt
块,其“分裂-变换-合并”策略用公式表述为:$\mathcal F(\mathbf{\vec x}) = \sum_{i=1}^C\mathcal T_i(\mathbf{\vec x}),\quad \mathbf{\vec y}=\mathbf{\vec x}+\mathcal F(\mathbf{\vec x})$
其中:
- $\mathcal T_i$ 为任意函数,它将 $\mathbf{\vec x} $映射为$ \mathbf{\vec x} $的一个低维嵌入,并对该低维嵌入执行转换。
- $C$ 为转换的数量,也就是基数
cardinality
。
在
ResNeXt
中,为了设计方便$ \mathcal T_i $采取以下设计原则:所有的 $\mathcal T_i$ 具有相同的结构。这是参考了
VGG
的层叠相同结构的层的思想。$\mathcal T_i $的结构通常是:
- 第一层:执行
1x1
的卷积来产生 $\mathbf{\vec x}$ 的一个低维嵌入。 - 第二层 ~ 倒数第二层:执行卷积、池化等等变换。
- 最后一层:执行
1x1
的卷积来将结果提升到合适的维度。
- 第一层:执行
6.2.2 ResNeXt 块
一个
ResNeXt
模块执行了一组相同的“变换”,每一个“变换”都是输入的一个低维嵌入,变换的数量就是基数C
。如下所示:左图为
ResNet
块;右图为ResNeXt
块。ResNeXt
模块有两种等效的形式:图(a)
为标准形式,图(b)
类似Inception-ResNet
模块。其中图(b)
的拼接是沿着深度方向拼接。等效的原因是:输入通道数为
128
的1x1
卷积可以如下拆分:( 设输入张量为$ \mathbf I ,$输出张量为$ \mathbf O,$核张量为$ \mathbf K )$经过这种拆分,图
(b)
就等效于图(a)
。其中:$i $表示输出单元位于 $i$ 通道,$s$ 表示输入单元位于$ s$ 通道,$j,k$ 表示通道中的坐标。本质原因是
1x1
卷积是简单的对通道进行线性相加。它可以拆分为:先将输入通道分组,然后计算各组的子通道的线性和(1x1
卷积);然后将所有组的和相加。图
(b)
与Inception-ResNet
模块的区别在于:这里每一条路径都是相同的。图
(c)
是一个分组卷积的形式,它就是用分组卷积来实现图(b)
。它也是图(b)
在代码中的实现方式。
通常
ResNeXt
模块至少有三层。事实上它也可以有两层,此时它等效于一个宽的、密集模块。- 此时并没有通过
1x1
卷积进行降维与升维,而是在降维的过程中同时进行变换,在升维的过程中也进行变换。 如下图所示,它等价于图
(c)
中,去掉中间的变换层(128,3x3,128
层),同时将第一层、第三层的1x1
替换为3x3
卷积层。
- 此时并没有通过
ResNeXt
的两种重要超参数是:基数C
和颈宽d
。- 基数
C
:决定了每个ResNeXt
模块有多少条路径。 颈宽(
bottleneck width
)d
:决定了ResNeXt
模块中第一层1x1
卷积降维的维度。这二者也决定了
ResNeXt
模块等价形式中,通道分组卷积的通道数量为Cxd
。
- 基数
ResNeXt
的网络参数和计算量与同等结构的ResNet
几乎相同。以ResNet-50
为例(输入图片尺寸224x224
):ResNeXt-50(32x4d)
意思是:基数C=32
,颈宽d=4
。在
ImageNet
上进行的对比实验(验证集误差,single crop
):- 基数 vs 颈宽:基数越大越好。
| 模型 | 配置 | top-1 error(%) |
| ----------- | -------- | -------------- |
| ResNet-50 | C=1,d=64 | 23.9 |
| ResNeXt-50 | C=2,d=40 | 23.0 |
| ResNeXt-50 | C=4,d=24 | 22.6 |
| ResNeXt-50 | C=8,d=14 | 22.3 |
| ResNeXt-50 | C=32,d=4 | 22.2 |
| ResNet-101 | C=1,d=64 | 22.0 |
| ResNeXt-101 | C=2,d=40 | 21.7 |
| ResNeXt-101 | C=4,d=24 | 21.4 |
| ResNeXt-101 | C=8,d=14 | 21.3 |
| ResNeXt-101 | C=32,d=4 | 21.2 |
- 基数 vs 深度/宽度:基数越大越好。
![img](http://www.huaxiaozhuan.com/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/imgs/dl_cnn_classification/resnetx_width_deep.png)
与其它模型的预测能力比较(验证集误差,
single crop
):ResNet/ResNeXt
的图片尺寸为224x224
和320x320
;Inception
的图片尺寸为299x299
。
6.3 随机深度网络
随机深度网络提出了训练时随机丢弃网络层的思想,从而能够让网络深度增加到超过 1000 层,并仍然可以减少测试误差。
如图所示:在
CIFAR-10
上,1202
层的ResNet
测试误差要高于110
层的ResNet
,表现出明显的过拟合。而1202
层的随机深度网络(结合了ResNet
)的测试误差要低于110
层的ResNet
。神经网络的表达能力主要由网络深度来决定,但是过深的网络会带来三个问题:反向传播过程中的梯度消失、前向传播过程中的
feature
消失、训练时间过长。虽然较浅的网络能够缓解这几个问题,但是较浅的网络表达能力不足,容易陷入欠拟合。
随机深度网络解决这一矛盾的策略是:构建具有足够表达能力的深度神经网络(具有数百层甚至数千层),然后:
在网络训练期间,对每个
mini batch
随机地移除部分层来显著的减小网络的深度。移除操作:删除对应的层,并用跳跃连接来代替。
在网络测试期间,使用全部的网络层。
随机深度的思想可以和
ResNet
结合。因为ResNet
已经包含了跳跃连接,因此可以直接修改。
6.3.1 随机深度
假设
ResNet
有 L 个残差块,则有:$\mathbf{\vec x}_{l+1}=\mathbf{\vec x}_l+\mathcal F(\mathbf{\vec x}_l,\mathcal W_l),\quad l=0,1,\cdots,L-1 。$其中:- $\mathbf{\vec x}_{l+1} $表示第$ l $个残差块的输出$,\mathbf{\vec x}_l $为第 $l$ 个残差块的输入(它也是第 $l-1 $个残差块的输出)。
- $\mathcal Wl={\mathbf W{l,k}\mid 1\le k \le K}$ 为一组与第 $l $个残差单元相关的权重(包括偏置项)$,K $是残差单元中的层的数量。
- $\mathcal F$ 代表残差函数。
假设第$ l $个残差块是否随机丢弃由伯努利随机变量$ b_l\in {0,1} $来指示:当$ b_l=0 $时,第$ l $个残差块被丢弃;当 $b_l=1 $时,第$ l $个残差块被保留。
因此有:$\mathbf{\vec x}_{l+1}=\mathbf{\vec x}_l+b_l\times \mathcal F(\mathbf{\vec x}_l,\mathcal W_l),\quad l=0,1,\cdots,L-1 。$
对随机变量$ b_l ,$令:
$P(b_l)=\begin{cases} p_l,&b_l=1\ 1-p_l ,&b_l=0 \end{cases}$
其中$ p_l$ 称做保留概率或者存活概率,它是一个非常重要的超参数。
$p_l $的选择有两个策略:
所有残差块的存活概率都相同:$p_0=p_1=\cdots=p{L-2}=p{L-1} 。$
所有残差块的存活概率都不同,且根据残差块的深度进行线性衰减:
$p_l=1-\frac {l+1}L(1-p_L),\quad l=0,1,\cdots,L-1$
其背后的思想是:靠近输入的层提取的是被后续层使用的低级特征,因此更应该被保留下来。
给定第 $l $个残差块的保留概率$ pl ,$则网络的深度$ \tilde L$ 的期望为(以残差块数量为单位)$:\mathbb E(\tilde L) = \sum{l=1}^L p_l 。$
对于均匀存活:$\mathbb E(\tilde L) = p_L\times L$
对于线性衰减存活:
$\mathbb E(\tilde L)=\frac{(1+p_L)\times L-(1-p_L)}{2}$
当 p_L \lt 1 时,无论是均匀存活还是线性衰减存活,都满足$ \mathbb E(\tilde L) \lt L 。$因此随机深度网络在训练时具有更短的期望深度,从而节省了训练时间。
$p_l $的选择策略,以及$ p_L $的大小的选取需要根据实验仔细选择。
- 根据作者的实验结果,作者推荐使用线性衰减存活概率,并选择 $p_L=0.5 。$此时有:$ \mathbb E(\tilde L)=\frac {(3L-1)}{4}$
如果选择更小的 $p_L $将会带来更大的测试误差,但是会更大的加速训练过程。
测试时,需要调整残差块的输出:$\mathbf{\vec x}_{l+1}^{test}=\mathbf{\vec x}_l^{test}+p_l\times \mathcal F(\mathbf{\vec x}_l^{test},\mathcal W_l),\quad l=0,1,\cdots,L-1 。$
随机深度网络能够大大减少训练时间和测试误差。
训练时间减小是因为:网络训练时,期望深度减小。
测试误差减小是因为:
- 网络训练时期望深度的减少,使得梯度链变短,从而加强了反向传播期间靠近输入层的梯度。
- 随机深度网络可以被理解为一系列不同深度的网络的隐式集成的集成模型。
随机深度网络可以视作 2^L 个隐式的神经网络的集成,这些被集成的网络都是权重共享的,类似于
Dropout
。- 在训练时,对每个
mini batch
,只有其中之一得到了权重更新。 - 在测试时,取所有被集成的网络的平均。
- 在训练时,对每个
随机深度网络和
Dropout
都可以被理解为一系列网络的隐式集成。- 随机深度集网络成了一系列具有不同深度的神经网络,而
Dropout
集成了一系列具有不同宽度的神经网络。 Dropout
与BN
配合使用时会失效,而随机深度可以和BN
配合使用。
- 随机深度集网络成了一系列具有不同深度的神经网络,而
在随机深度网络中,由于训练时的随机深度,模型的测试误差的抖动相对于
ResNet
会偏大。
6.3.2 网络性能
对
ResNet
(固定深度和随机深度)在三个数据集上进行比较,测试误差的结果如下:+
表示执行了数据集增强。随机深度网络采用 p_L=0.5 。
CIFAR10/100
采用 110 层ResNet
,ImageNet
采用 152 层ResNet
。虽然在
ImageNet
上随机深度模型没有提升,但是作者表示这是因为网络本身比较简单(相对ImageNet
数据集)。如果使用更深的ResNet
,则容易看到随机深度模型的提升。虽然这里模型的测试误差没有提升,但是训练速度大幅提升。
| 网络 | CIFAR10+ | CIFAR100+ | ImageNet |
| ------------------ | -------- | --------- | -------- |
| ResNet(固定深度) | 6.41 | 27.76 | 21.78 |
| ResNet(随机深度) | 5.25 | 24.98 | 21.98 |
在
CIFAR-10
上,ResNet
随机深度网络的深度 L 、概率 p_L 与测试集误差的关系:
七、SENet
SENet
提出了一种新的架构单元来解决通道之间相互依赖的问题。它通过显式地对通道之间的相互依赖关系建模,自适应的重新校准通道维的特征响应,从而提高了网络的表达能力。SENet
以2.251% top-5
的错误率获得了ILSVRC 2017
分类比赛的冠军。SENet
是和ResNet
一样,都是一种网络框架。它可以直接与其他网络架构一起融合使用,只需要付出微小的计算成本就可以产生显著的性能提升。
7.1 SE 块
SE
块(Squeeze-and-Excitation
)是SENet
中提出的新的架构单元,它主要由squeeze
操作和excitation
操作组成。对于给定的任何变换 $\mathbf F_{tr}: \mathbf X \rightarrow \mathbf U,$其中:$\mathbf X\in \mathbb R^{W^\prime\times H^\prime\times C^\prime} $为输入
feature map
,其尺寸为$ W^\prime\times H^\prime,$通道数为$ C ^\prime;\mathbf U\in \mathbb R^{W\times H\times C} $为输出feature map
,其尺寸为 $W\times H,$通道数为$ C。$可以构建一个相应的
SE
块来对输出feature map
$\mathbf U $执行特征重新校准:- 首先对输出
feature map
$\mathbf U $squeeze
操作,它对每个通道的全局信息建模,生成一组通道描述符。 - 然后是一个
excitation
操作,它对通道之间的依赖关系建模,生成一组权重信息(对应于每个通道的权重)。 最后输出
feature map
$\mathbf U $被重新加权以生成SE
块的输出。
- 首先对输出
SE
块可以理解为注意力机制的一个应用。它是一个轻量级的门机制,用于对通道关系进行建模。通过该机制,网络学习全局信息(全通道、全空间)来选择性的强调部分特征,并抑制其它特征。
设$ \mathbf U=[\mathbf u_1,\mathbf u_2,\cdots,\mathbf uC] , \mathbf u_c $为第 $c $个通道,是一个$ W\times H $的矩阵;设 $\mathbf X=[\mathbf x_1,\mathbf x_2,\cdots,\mathbf x{C^\prime}] , \mathbf x_j $为第 $j $个通道,是一个$ W^\prime\times H^\prime $的矩阵。
需要学习的变换$ \mathbf F_{tr}=[\mathbf V_1,\mathbf V_2,\cdots,\mathbf V_C] $就是一组卷积核。 \mathbf V_c 为第 c 个卷积核,记做: $\mathbf V_c=[\mathbf v_c^{(1)},\mathbf v_c^{(2)},\cdots,\mathbf v_c^{(C^\prime)}] ,\mathbf v_c^{(j)} $为第 $c$ 个卷积核的第 $j $通道,是一个二维矩阵。则:
$\mathbf uc = \mathbf V_c \mathbf X = \sum_{j=1}^{C^\prime} \mathbf vc^{(j)}\mathbf x_j$
这里
*
表示卷积。同时为了描述简洁,这里忽略了偏置项。输出$ \mathbf u_c $考虑了输入 $\mathbf X$ 的所有通道,因此通道依赖性被隐式的嵌入到 $\mathbf V_c $中。
7.1.1 squeeze 操作
squeeze
操作的作用是:跨空间$ W\times H $聚合特征来产生通道描述符。该描述符嵌入了通道维度特征响应的全局分布,包含了全局感受野的信息。
每个学到的滤波器都是对局部感受野进行操作,因此每个输出单元都无法利用局部感受野之外的上下文信息。
在网络的低层,其感受野尺寸很小,这个问题更严重。
为减轻这个问题,可以将全局空间信息压缩成一组通道描述符,每个通道对应一个通道描述符。然后利用该通道描述符。
通常基于通道的全局平均池化来生成通道描述符(也可以考虑使用更复杂的聚合策略)。
设所有通道的通道描述符组成一个向量$ \mathbf{\vec z} \in \mathbb R^C 。$则有:
$\mathbf {\vec z}=[z_1,z_2,\cdots,z_C]\ z_c=\frac{1}{W\times H}\sum{i=1}^W\sum{j=1}^Hu_c(i,j);\quad c=1,2,\cdots,C$
.
7.1.2 excitation 操作
excitation
操作的作用是:通过自门机制来学习每个通道的激活值,从而控制每个通道的权重。excitation
操作利用了squeeze
操作输出的通道描述符 $\mathbf{\vec z} 。$首先,通道描述符$ \mathbf{\vec z} $经过线性降维之后,通过一个
ReLU
激活函数。降维通过一个输出单元的数量为 $\frac Cr$ 的全连接层来实现,其中 $r $为降维比例。
然后,
ReLU
激活函数的输出经过线性升维之后,通过一个sigmoid
激活函数。升维通过一个输出单元的数量为$ C$ 的全连接层来实现。
通过对通道描述符$ \mathbf{\vec z} $进行降维,显式的对通道之间的相互依赖关系建模。
设
excitation
操作的输出为向量$ \mathbf{\vec s},$则有:$\mathbf{\vec s} = \sigma(\mathbf W_2 \text{ReLU}(\mathbf W_1\mathbf {\vec z})) 。$其中:$\sigma $为
sigmoid
激活函数,$\mathbf W_1 \in \mathbb R^{C/r\times C} $为降维层的权重$,\mathbf W_2 \in \mathbb R^{C\times C/r} $为升维层的权重,$r $为降维比例。在经过
excitation
操作之后,通过重新调节 $\mathbf U $得到SE
块的输出。设
SE
块的最终输出为$ \widetilde {\mathbf X}=[\widetilde{\mathbf x}_1,\widetilde{\mathbf x}_2,\cdots,\widetilde{\mathbf x}_C],$则有:$\widetilde{\mathbf x}_c=s_c\times \mathbf{ u}_c,\quad c=1,2,\cdots,C $。这里$ s_c$ 为excitaion
操作的输出结果,它作为通道 $c $的权重。$s_c $不仅考虑了本通道的全局信息(由 $z_c$ 引入),还考虑了其它通道的全局信息(由$ \mathbf W_1,\mathbf W_2 引入)$。
7.1.3 SE 块使用
有两种使用
SE
块来构建SENet
的方式:简单的堆叠
SE
块来构建一个新的网络。在现有网络架构中,用
SE
块来替代原始块。下图中,左侧为原始
Inception
模块,右侧为SE-Inception
模块。下图中,左侧为原始残差模块,右侧为
SE-ResNet
模块。
如果使用
SE
块来替代现有网络架构中的原始块,则所有额外的参数都包含在门机制的两个全连接层中。引入的额外参数的数量为:$\frac 2r\sum_{s=1}^S C_s^2 。$其中:$r $表示降维比例(论文中设定为 16),$S $指的是
SE
块的数量,$C_s $表示第 $s$ 个SE
块的输出通道的维度。如:
SE-ResNet-50
在ResNet-50
所要求的大约 2500 万参数之外,额外引入了约 250 万参数,相对增加了 10%。超参数 $r $称作减少比率,它刻画了需要将通道描述符组成的向量压缩的比例。它是一个重要的超参数,需要在精度和复杂度之间平衡。
网络的精度并不会随着 $r $的增加而单调上升,因此需要多次实验并选取其中最好的那个值。
如下所示为
SE-ResNet-50
采用不同的 r 在ImageNet
验证集上的预测误差(single-crop
)。original
表示原始的ResNet-50
。虽然
SE
块可以应用在网络的任何地方,但是它在不同深度中承担了不同的作用。在网络较低的层中:对于不同类别的样本,特征通道的权重分布几乎相同。
这说明在网络的最初阶段,特征通道的重要性很可能由不同的类别共享。即:低层特征通常更具有普遍性。
在网络较高的层中:对于不同类别的样本,特征通道的权重分布开始分化。
这说明在网络的高层,每个通道的值变得更具有类别特异性。即:高层特征通常更具有特异性。
在网络的最后阶段的
SE
块为网络提供重新校准所起到的作用,相对于网络的前面阶段的SE
块来说,更加不重要。这意味着可以删除最后一个阶段的
SE
块,从而显著减少总体参数数量,仅仅带来一点点的损失。如:在SE-ResNet-50
中,删除最后一个阶段的SE
块可以使得参数增加量下降到 4%,而在ImageNet
上的top-1
错误率的损失小于0.1%
。因此:
Se
块执行特征通道重新校准的好处可以通过整个网络进行累积。
7.2 网络性能
网络结构:其中
fc,[16,256]
表示SE
块中的两个全连接层的输出维度。在
ImageNet
验证集上的计算复杂度和预测误差比较(single-crop
)。original
列:从各自原始论文中给出的结果报告。re-implementation
列:重新训练得到的结果报告。SENet
列:通过引入SE
块之后的结果报告。GFLOPs/MFLOPs
:计算复杂度,单位为G/M FLOPs
。MobileNet
采用的是1.0 MobileNet-224
,ShuffleNet
采用的是1.0 ShuffleNet 1x(g=3)
。数据集增强和归一化:
- 随机裁剪成
224x224
大小(Inception
系列裁剪成299x299
)。 - 随机水平翻转。
- 输入图片沿着通道归一化:每个像素减去本通道的像素均值。
- 随机裁剪成
在
ImageNet
验证集上的预测误差比较(single-crop
):其中
SENet-154(post-challenge)
是采用320x320
大小的图片来训练的。
八、 DenseNet
DenseNet
不是通过更深或者更宽的结构,而是通过特征重用来提升网络的学习能力。ResNet
的思想是:创建从“靠近输入的层” 到 “靠近输出的层” 的直连。而DenseNet
做得更为彻底:将所有层以前馈的形式相连,这种网络因此称作DenseNet
。DenseNet
具有以下的优点:- 缓解梯度消失的问题。因为每层都可以直接从损失函数中获取梯度、从原始输入中获取信息,从而易于训练。
- 密集连接还具有正则化的效应,缓解了小训练集任务的过拟合。
- 鼓励特征重用。网络将不同层学到的
feature map
进行组合。 - 大幅度减少参数数量。因为每层的卷积核尺寸都比较小,输出通道数较少 (由增长率 k 决定)。
DenseNet
具有比传统卷积网络更少的参数,因为它不需要重新学习多余的feature map
。传统的前馈神经网络可以视作在层与层之间传递
状态
的算法,每一层接收前一层的状态
,然后将新的状态
传递给下一层。这会改变
状态
,但是也传递了需要保留的信息。ResNet
通过恒等映射来直接传递需要保留的信息,因此层之间只需要传递状态的变化
。DenseNet
会将所有层的状态
全部保存到集体知识
中,同时每一层增加很少数量的feture map
到网络的集体知识中
。
DenseNet
的层很窄(即:feature map
的通道数很小),如:每一层的输出只有 12 个通道。
8.1 DenseNet 块
具有 L 层的传统卷积网络有 L 个连接,每层仅仅与后继层相连。
具有 L 个残差块的
ResNet
在每个残差块增加了跨层连接,第 l 个残差块的输出为:$\mathbf{\vec x}{l+1}=\mathbf{\vec x}_l+\mathcal F(\mathbf{\vec x}_l,\mathcal W_l) 。$其中$ \mathbf{\vec x}_l $是第 $l $个残差块的输入特征$;\mathcal W_l={\mathbf W{l,k}\mid 1\le k \le K} $为一组与第$ l $个残差块相关的权重(包括偏置项)$,K$ 是残差块中的层的数量$; \mathcal F $代表残差函数。具有 $L$ 个层块的
DenseNet
块有$ \frac {L(L+1)}{2} $个连接,每层以前馈的方式将该层与它后面的所有层相连。对于第 l 层:所有先前层的feature map
都作为本层的输入,第 l 层具有 l 个输入feature map
;本层输出的feature map
都将作为后面 L-l 层的输入。假设
DenseNet
块包含 $L$ 层,每一层都实现了一个非线性变换$ H_l(\cdot) ,$其中$ l $表示层的索引。假设
DenseNet
块的输入为 $\mathbf x_0 ,$DenseNet
块的第$ l $层的输出为 $\mathbf x_l $,则有:$\mathbf x{l}=H_l([\mathbf x_0,\mathbf x_1,\cdots,\mathbf x{l-1}])$
其中 $[\mathbf x0,\mathbf x_1,\cdots,\mathbf x{l-1}] $表示 $0,\cdots,l-1 $层输出的
feature map
沿着通道方向的拼接。ResNet
块与它不同。在ResNet
中,不同feature map
是通过直接相加来作为块的输出。当
feature map
的尺寸改变时,无法沿着通道方向进行拼接。此时将网络划分为多个DenseNet
块,每块内部的feature map
尺寸相同,块之间的feature map
尺寸不同。
8.1.1 增长率
DenseNet
块中,每层的 $H_l(\cdot) $输出的feature map
通道数都相同,都是 $k$ 个。$k$ 是一个重要的超参数,称作网络的增长率。第 l 层的输入
feature map
的通道数为$: k_0+k\times(l-1) 。$其中 k_0 为输入层的通道数。DenseNet
不同于现有网络的一个重要地方是:DenseNet
的网络很窄,即输出的feature map
通道数较小,如:$ k=12。$一个很小的增长率就能够获得不错的效果。一种解释是:
DenseNet
块的每层都可以访问块内的所有早前层输出的feature map
,这些feature map
可以视作DenseNet
块的全局状态。每层输出的feature map
都将被添加到块的这个全局状态中,该全局状态可以理解为网络块的“集体知识”,由块内所有层共享。增长率 k 决定了新增特征占全局状态的比例。因此
feature map
无需逐层复制(因为它是全局共享),这也是DenseNet
与传统网络结构不同的地方。这有助于整个网络的特征重用,并产生更紧凑的模型。
8.1.2 非线性变换$ H_l$
- $H_l(\cdot) $可以是包含了
Batch Normalization(BN)
、ReLU
单元、池化或者卷积等操作的复合函数。 - 论文中$ H_l(\cdot)$ 的结构为:先执行
BN
,再执行ReLU
,最后接一个3x3
的卷积,即:BN-ReLU-Conv(3x3)
。
8.1.3 bottleneck
尽管
DenseNet
块中每层只产生 k 个输出feature map
,但是它具有很多输入。当在$ H_l(\cdot)$ 之前采用1x1
卷积实现降维时,可以减小计算量。$H_l(\cdot) $的输入是由第 $0,1,2,\cdots,l-1 $层的输出
feature map
组成,其中第0
层的输出feature map
就是整个DensNet
块的输入feature map
。
事实上第 $1,2,\cdots,l-1 $层从DensNet
块的输入feature map
中抽取各种特征。即 H_l(\cdot) 包含了DensNet
块的输入feature map
的冗余信息,这可以通过 1x1
卷积降维来去掉这种冗余性。
因此这种1x1
卷积降维对于DenseNet
块极其有效。
如果在$ H_l(\cdot) $中引入
1x1
卷积降维,则该版本的DenseNet
称作DenseNet-B
。其 $H_l(\cdot) $结构为:先执行BN
,再执行ReLU
,再接一个1x1
的卷积,再执行BN
,再执行ReLU
,最后接一个3x3
的卷积。即:BN-ReLU-Conv(1x1)-BN-ReLU-Conv(3x3)
。其中
1x1
卷积的输出通道数是个超参数,论文中选取为$ 4\times k 。$
8.2 过渡层
一个
DenseNet
网络具有多个DenseNet
块,DenseNet
块之间由过渡层连接。DenseNet
块之间的层称为过渡层,其主要作用是连接不同的DenseNet
块。过渡层可以包含卷积或池化操作,从而改变前一个
DenseNet
块的输出feature map
的大小(包括尺寸大小、通道数量)。论文中的过渡层由一个
BN
层、一个1x1
卷积层、一个2x2
平均池化层组成。其中1x1
卷积层用于减少DenseNet
块的输出通道数,提高模型的紧凑性。如果不减少
DenseNet
块的输出通道数,则经过了 N 个DenseNet
块之后,网络的feature map
的通道数为:$k_0+N\times k\times (L-1) ,$其中 $k_0$ 为输入图片的通道数, $L $为每个DenseNet
块的层数。如果
Dense
块输出feature map
的通道数为 $ m$ ,则可以使得过渡层输出feature map
的通道数为$ \theta m $ ,其中$ 0 \lt\theta \le 1 $ 为压缩因子。当 $ \theta =1$ 时,经过过渡层的
feature map
通道数不变。当$ \theta \lt 1 $ 时,经过过渡层的
feature map
通道数减小。此时的DenseNet
称做DenseNet-C
。结合了
DenseNet-C
和DenseNet-B
的改进的网络称作DenseNet-BC
。
8.3 网络性能
网络结构:
ImageNet
训练的DenseNet
网络结构,其中增长率 k=32 。- 表中的
conv
代表的是BN-ReLU-Conv
的组合。如1x1 conv
表示:先执行BN
,再执行ReLU
,最后执行1x1
的卷积。 DenseNet-xx
表示DenseNet
块有xx
层。如:DenseNet-169
表示DenseNet
块有 L=169 层 。- 所有的
DenseNet
使用的是DenseNet-BC
结构,输入图片尺寸为224x224
,初始卷积尺寸为7x7
、输出通道2k
、步长为2
,压缩因子 \theta=0.5 。 在所有
DenseNet
块的最后接一个全局平均池化层,该池化层的结果作为softmax
输出层的输入。
- 表中的
在
ImageNet
验证集的错误率(single-crop/10-crop
):
| 模型 | top-1 error(%) | top-5 error(%) |
| ------------ | -------------- | -------------- |
| DenseNet-121 | 25.02/23.61 | 7.71/6.66 |
| DenseNet-169 | 23.80/22.08 | 6.85/5.92 |
| DenseNet-201 | 22.58/21.46 | 6.34/5.54 |
| DenseNet-264 | 22.15/20.80 | 6.12/5.29 |
DenseNet
的参数数量和计算量相对ResNet
明显减少。
下图是DenseNet
和ResNet
在ImageNet
验证集的错误率的比较(single-crop
)。左图为参数数量,右图为计算量。从实验可见:
DenseNet
的参数数量和计算量相对ResNet
明显减少。- 具有
20M
个参数的DenseNet-201
与具有40M
个参数的ResNet-101
验证误差接近。 - 和
ResNet-101
验证误差接近的DenseNet-201
的计算量接近于ResNet-50
,几乎是ResNet-101
的一半。
- 具有
DenseNet
在CIFAR
和SVHN
验证集的表现:C10+
和C100+
:表示对CIFAR10/CIFAR100
执行数据集增强,包括平移和翻转。- 在
C10/C100/SVHN
三列上的DenseNet
采用了Dropout
。 DenseNet
的Depth
列给出的是 L 参数。从实验可见:
不考虑压缩因子和
bottleneck
,L 和 k 越大DenseNet
表现更好。这主要是因为模型容量相应地增长。网络可以利用更大、更深的模型提高其表达学习能力,这也表明了
DenseNet
不会受到优化困难的影响。DenseNet
的参数效率更高,使用了压缩因子和bottleneck
的DenseNet-BC
的参数利用率极高。这带来的一个效果是:
DenseNet-BC
不容易发生过拟合。事实上在
CIFAR10
上,DenseNet
从$ k=12\rightarrow k=24 $ 中,参数数量提升了 4 倍但是验证误差反而5.77
下降到5.83
,明显发生了过拟合。而DenseNet-BC
未观察到过拟合。
DenseNet
提高准确率的一个可能的解释是:各层通过较短的连接(最多需要经过两个或者三个过渡层)直接从损失函数中接收额外的监督信息。
8.4 内存优化
8.4.1 内存消耗
虽然
DenseNet
的计算效率较高、参数相对较少,但是DenseNet
对内存不友好。考虑到GPU
显存大小的限制,因此无法训练较深的DenseNet
。假设
DenseNet
块包含 L 层,对于第 l 层有:$ \mathbf x{l}=H_l([\mathbf x_0,\mathbf x_1,\cdots,\mathbf x{l-1}]) $ 。假设每层的输出
feature map
尺寸均为 $ W \times H 、$ 通道数为 $ k ,$ $ H_l $ 由BN-ReLU-Conv(3x3)
组成,则:- 拼接
Concat
操作$ [\cdots] :$ 需要生成临时feature map
作为第 l 层的输入,内存消耗为$ WHk\times l $ 。 BN
操作:需要生成临时feature map
作为ReLU
的输入,内存消耗为$ WHk\times l 。$ReLU
操作:可以执行原地修改,因此不需要额外的feature map
存放ReLU
的输出。Conv
操作:需要生成输出feature map
作为第 l 层的输出,它是必须的开销。因此除了第$ 1,2,\cdots,L $ 层的输出
feature map
需要内存开销之外,第 $ l $ 层还需要$ 2WHkl$ 的内存开销来存放中间生成的临时feature map
。整个
DenseNet Block
需要 $ WHk(1+L)L$ 的内存开销来存放中间生成的临时feature map
。即DenseNet Block
的内存消耗为$ O(L^2),$ 是网络深度的平方关系。
- 拼接
拼接
Concat
操作是必须的,因为当卷积的输入存放在连续的内存区域时,卷积操作的计算效率较高。而DenseNet Block
中,第 l 层的输入feature map
由前面各层的输出feature map
沿通道方向拼接而成。而这些输出feature map
并不在连续的内存区域。另外,拼接
feature map
并不是简单的将它们拷贝在一起。由于feature map
在Tensorflow/Pytorch
等等实现中的表示为$ \mathbb R^{n\times d\times w\times h} $ (channel first
),或者 $ \mathbb R^{n\times w\times h\times d}$ (channel last
),如果简单的将它们拷贝在一起则是沿着mini batch
维度的拼接,而不是沿着通道方向的拼接。DenseNet Block
的这种内存消耗并不是DenseNet Block
的结构引起的,而是由深度学习库引起的。因为Tensorflow/PyTorch
等库在实现神经网络时,会存放中间生成的临时节点(如BN
的输出节点),这是为了在反向传播阶段可以直接获取临时节点的值。这是在时间代价和空间代价之间的折中:通过开辟更多的空间来存储临时值,从而在反向传播阶段节省计算。
除了临时
feature map
的内存消耗之外,网络的参数也会消耗内存。设 H_l 由BN-ReLU-Conv(3x3)
组成,则第 l 层的网络参数数量为:$ 9lk^2 $ (不考虑BN
)。整个
DenseNet Block
的参数数量为 $ \frac{9k^2(L+1)L}{2} ,$ 即 $ O(L^2)。$ 因此网络参数的数量也是网络深度的平方关系。- 由于
DenseNet
参数数量与网络的深度呈平方关系,因此DenseNet
网络的参数更多、网络容量更大。这也是DenseNet
优于其它网络的一个重要因素。 - 通常情况下都有 $ WH\gt \frac{9k}{2} ,$ 其中 $ W,H $ 为网络
feature map
的宽、高,$ k$ 为网络的增长率。所以网络参数消耗的内存要远小于临时feature map
消耗的内存。
- 由于
8.4.2 内存优化
论文
《Memory-Efficient Implementation of DenseNets》
通过分配共享内存来降低内存需求,从而使得训练更深的DenseNet
成为可能。其思想是利用时间代价和空间代价之间的折中,但是侧重于牺牲时间代价来换取空间代价。其背后支撑的因素是:
Concat
操作和BN
操作的计算代价很低,但是空间代价很高。因此这种做法在DenseNet
中非常有效。传统的
DenseNet Block
实现与内存优化的DenseNet Block
对比如下(第 l 层,该层的输入feature map
来自于同一个块中早前的层的输出):左图为传统的
DenseNet Block
的第 l 层。首先将feature map
拷贝到连续的内存块,拷贝时完成拼接的操作。然后依次执行BN
、ReLU
、Conv
操作。该层的临时
feature map
需要消耗内存 $ 2WHkl,$ 该层的输出feature map
需要消耗内存 $ WHk $ 。- 另外某些实现(如
LuaTorch
)还需要为反向传播过程的梯度分配内存,如左图下半部分所示。如:计算BN
层输出的梯度时,需要用到第 l 层输出层的梯度和BN
层的输出。存储这些梯度需要额外的 $ O(l k) $ 的内存。 - 另外一些实现(如
PyTorch,MxNet
)会对梯度使用共享的内存区域来存放这些梯度,因此只需要 $ O(k) $ 的内存。
- 另外某些实现(如
右图为内存优化的
DenseNet Block
的第 l 层。采用两组预分配的共享内存区Shared memory Storage location
来存Concate
操作和BN
操作输出的临时feature map
。
第一组预分配的共享内存区:
Concat
操作共享区。第 $ 1,2,\cdots,L $ 层的Concat
操作的输出都写入到该共享区,第$ l+1$ 层的写入会覆盖第 l 层的结果。对于整个
Dense Block
,这个共享区只需要分配 $ WHkL $ (最大的feature map
)的内存,即内存消耗为 $ O(kL)$ (对比传统DenseNet
的 $ O(kL^2))。$后续的
BN
操作直接从这个共享区读取数据。由于第$ l+1$ 层的写入会覆盖第$ l $ 层的结果,因此这里存放的数据是临时的、易丢失的。因此在反向传播阶段还需要重新计算第$ l $ 层的
Concat
操作的结果。因为
Concat
操作的计算效率非常高,因此这种额外的计算代价很低。
第二组预分配的共享内存区:
BN
操作共享区。第 $ 1,2,\cdots,L$ 层的BN
操作的输出都写入到该共享区,第 l+1 层的写入会覆盖第 l 层的结果。对于整个
Dense Block
,这个共享区也只需要分配 $ WHkL $ (最大的feature map
)的内存,即内存消耗为 $ O(kL) $ (对比传统DenseNet
的$ O(kL^2))$ 。后续的卷积操作直接从这个共享区读取数据。
与
Concat
操作共享区同样的原因,在反向传播阶段还需要重新计算第 l 层的BN
操作的结果。BN
的计算效率也很高,只需要额外付出大约 5% 的计算代价。
由于
BN
操作和Concat
操作在神经网络中大量使用,因此这种预分配共享内存区的方法可以广泛应用。它们可以在增加少量的计算时间的情况下节省大量的内存消耗。
8.4.3 优化结果
如下图所示,
DenseNet
不同实现方式的实验结果:Naive Implementation(LuaTorch)
:采用LuaTorch
实现的,不采用任何的内存共享区。Shared Gradient Strorage(LuaTorch)
:采用LuaTorch
实现的,采用梯度内存共享区。Shared Gradient Storage(PyTorch)
:采用PyTorch
实现的,采用梯度内存共享区。Shared Gradient+BN+Concat Strorate(LuaTorch)
:采用LuaTorch
实现的,采用梯度内存共享区、Concat
内存共享区、BN
内存共享区。Shared Gradient+BN+Concat Strorate(PyTorch)
:采用LuaTorch
实现的,采用梯度内存共享区、Concat
内存共享区、BN
内存共享区。注意:
PyTorch
自动实现了梯度的内存共享区。内存消耗是参数数量的线性函数。因为参数数量本质上是网络深度的二次函数,而内存消耗也是网络深度的二次函数。
如前面的推导过程中,
DenseNet Block
参数数量 $ P=\frac{9k^2(L+1)L}{2},$ 内存消耗 M=WHk(1+L)L。因此 $ M=\frac{2WH}{9k} P,$ 即 $ M=O(P) 。$
如下图所示,
DenseNet
不同实现方式的训练时间差异(NVIDIA Maxwell Titan-X
):- 梯度共享存储区不会带来额外时间的开销。
Concat
内存共享区、BN
内存共享区需要额外消耗 15%(LuaTorch
) 或者 20% (PyTorch
) 的时间。
如下图所示,不同
DenseNet
的不同实现方式在ImageNet
上的表现(single-crop test
):DenseNet cosine
使用 $ \cos(\cdot) $ 学习率。经过内存优化的
DenseNet
可以在单个工作站(8 NVIDIA Tesla M40 GPU
)上训练 264 层的网络,并取得了top-1 error=20.26%
的好成绩。网络参数数量:232 层
DenseNet
:k=48,55M
参数。 264 层DenseNet
:k=32,33M
参数;k=48,73M
参数。
九、小型网络
目前神经网络领域的研究基本可以概括为两个方向:探索模型更好的预测能力,关注模型在实际应用中的难点。
事实上卷积神经网络在图像识别领域超越了人类的表现,但是这些先进的网络需要较高的计算资源。这些资源需求超出了很多移动设备和嵌入式设备的能力(如:无人驾驶),导致实际应用中难以在这些设备上应用。
小型网络就是为解决这个难点来设计的。
小型网络的设计和优化目标并不是模型的准确率,而是在满足一定准确率的条件下,尽可能的使得模型小,从而降低对计算资源的需求,降低计算延迟。
小型高效的神经网络的构建方法大致可以归为两类:对已经训练好的网络进行压缩,直接训练小网络模型。
模型参数的数量决定了模型的大小,所谓的
小型网络
指的是网络的参数数量较少。小型网络具有至少以下三个优势:
较小的模型具有更高效的分布式训练效率。
Worker
与PS
以及Worker
与Worker
之间的通信是神经网络分布式训练的重要限制因素。在分布式数据并行训练中,通信开销与模型的参数数量成正比。较小的模型需要更少的通信,从而可以更快的训练。较小的模型在模型导出时开销更低。
当在
tensorflow
等框架中训练好模型并准备部署时,需要将模型导出。如:将训练好的模型导出到自动驾驶汽车上。模型越小,则数据导出需要传输的数据量越少,这样可以支持更频繁的模型更新。较小的模型可以在
FPGA
和嵌入式硬件上部署。FPGA
通常只有小于10MB
的片上内存,并且没有外部存储。因此如果希望在FPGA
上部署模型,则要求模型足够小从而满足内存限制。
9.1 SqueezeNet 系列
9.1.1 SqueezeNet
squeezenet
提出了Fire
模块,并通过该模型构成一种小型CNN
网络,在满足AlexNet
级别准确率的条件下大幅度降低参数数量。CNN
结构设计三个主要策略:策略 1:部分的使用
1x1
卷积替换3x3
卷积。因为1x1
卷积的参数数量比3x3
卷积的参数数量少了9
倍。策略 2:减少
3x3
卷积输入通道的数量。这会进一步降低网络的参数数量。策略 3:将网络中下采样的时机推迟到网络的后面。这会使得网络整体具有尺寸较大的
feature map
。其直觉是:在其它不变的情况下,尺寸大的
feature map
具有更高的分类准确率。策略
1、2
是关于在尽可能保持模型准确率的条件下减少模型的参数数量,策略3
是关于在有限的参数数量下最大化准确率。
9.1.1.1 Fire 模块
一个
Fire
模块由一个squeeze
层和一个expand
层组成。squeeze
层:一个1x1
卷积层,输出通道数为超参数$ s_{1\times 1} $ 。- 通常选择超参数 $ s{1\times 1} $ 满足:$ s{1\times 1}\lt e{1\times 1}+e{3\times 3} 。$
- 它用于减少
expand
层的输入通道数,即:应用策略 2 。
expand
层:一个1x1
卷积层和一个3x3
卷积层,它们卷积的结果沿着深度进行拼接。1x1
卷积输出通道数为超参数 $ e{1\times 1} ,$3x3
卷积输出通道数为超参数 $ e{3\times 3} 。$- 选择
1x1
卷积是应用了策略 1 。
9.1.1.2 网络性能
网络设计:
SqueezeNet
从一个独立的卷积层(conv1
)开始,后跟 8 个Fire
模块(fire2~9
),最后连接卷积层conv10
、全局平均池化层、softmax
输出层。- 从网络开始到末尾,每个
Fire
模块的输出通道数逐渐增加。 - 在
conv1、fire4、fire8
之后执行最大池化,步长为 2。这种相对较晚的执行池化操作是采用了策略 3。 - 在
expand
层中的3x3
执行的是same
卷积,即:在原始输入上下左右各添加一个像素,使得输出的feature map
尺寸不变。 在
fire9
之后使用Dropout
,遗忘比例为 0.5 。
网络参数:
- $ s{1\times1}$
(#1x1 squeeze)
列给出了超参数$ s{1\times1} ,e_{1\times1}$(#1x1 expand)
列给出了超参数 e{1\times1} ,e{3\times 3}(#3x3 expand)
列给出了超参数 e*{3\times 3} 。 - $ s{1\times 1}\; \text{sparsity} ,e{1\times 1}\; \text{sparsity},e_{3\times 3}\; \text{sparsity},\text
- $ s{1\times1}$