卷积备忘录

freeopen 2019-01-05 · 最后更新时间:  2021-02-17 [机器学习] #notes

学习了一段时间卷积,到了该整理的时候了。这是一篇不会写完的文章,它将跟进卷积技术的发展和演变,进行增补。

卷积的数学原理

在图像处理中,卷积计算属于二维卷积的离散形式,公式如下: $$(f*g)[n_1, n_2] = \sum_{m_1 = -\infty}^{+\infty}\sum_{m_2 = -\infty}^{+\infty}f[m_1, m_2]\cdot g[n_1 - m_1, n_2 - m_2]$$

其中,

离散的二维卷积计算表现为卷积核(也称 过滤器 )在二维平面上平移, 且卷积核的每个元素与被卷积的图像像素点数值对位相乘,再求和。 为什么简单的相乘再求和运算,就能抽取出图像的特征呢?因为这种计算方式就是两个向量的内积计算,线性代数中两个向量的余弦相似度即是两个向量求内积再除以它们的模,或者先把两个向量标准化后再求它们的内积,所以卷积计算即是对相似度的衡量,其输出的值表示某区域图像与过滤器的相似程度。

卷积的表示

在机器学习中,我们常以四个超参数来定义卷积,它们分别是:

如果要表示空洞卷积,还需要一个表示空洞数量的超参数,我喜欢把它记为 $D$。

卷积的输出尺寸

卷积输出的空间尺寸的公式为:

$$ O = \lfloor {I - K + 2P \over S} + 1 \rfloor$$

其中,

假如我们有一张 32x32x3 的输入图像,我们使用 10 个尺寸为 3x3x3 的过滤器,单步幅和零填充。根据上式的符号约定, $W=32,K=3,P=0,S=1$, 输出深度等于过滤器的数量 10, 输出尺寸大小为 $((32 - 3 + 0)/1) + 1 = 30$, 因此输出尺寸是 30x30x10

卷积网络的感受野

感受野( Receptive Field )表示经过卷积网络输出的一个点能看到原始输入的范围大小。对仅有一层的卷积网络来说,感受野的大小就是卷积核的大小,但对于层叠网络来说,感受野的计算就会稍微复杂些。习惯上,我们把层叠模型中靠近原始输入端的叫做低层,把靠近最终结果的层称为高层,计算感受野的公式为:

$$r^{(l)} = r^{(l-1)} + (k^{(l)}-1)*j^{(l-1)} = r^{(l-1)} + (k^{(l)}-1)*\prod_{i=1}^{l-1}s^{(i)}$$

其中,

卷积的进化

卷积形式经过各种排列组合,诞生了不少经典神经网络结构,我想要探索的不仅仅是这些结构本身,更想要搞明白这些结构设计的初衷,以及带来的好处是什么。

这里讨论的卷积结构,我分为两类,一类叫卷积单元,表示单个卷积,一类叫卷积结构,表示多个卷积的组合。


分类一:卷积单元

常规卷积(Convolution)

如前所述的基本原理,即为常规卷积。简而言之,即矩阵和卷积核进行对应元素的相乘并求和,一次卷积的结果输出一个数,然后卷积核在矩阵上边滑动边计算,当遍历完矩阵时,会输出一个结果矩阵。

空洞卷积(Dilated Conv)

空洞卷积 (Dilated Convolution) 又叫膨胀卷积 ( Atrous Convolution), 它的想法是在卷积核中增加“空洞”, 从而在不增加参数量的情况下捕捉到更远的距离。换种说法就是空洞卷积能增加感受野。

空洞卷积核的设计很简单,其实就是对卷积核的插 0 操作, 比如由“111”变为“10101”这样。空洞卷积常用于一维卷积的场景,比如 NLP 的语义分割、文本抽取等任务,语音合成等任务。

空洞卷积在不增加参数的前提下增加感受野,我们举个例子算一下。设有4层网络,第0层为一维序列,第1层为普通卷积(核尺寸,步幅数,空洞数) = $(k,s,d)$ = $(3,1,1)$,第2层为普通卷积$(3,2,1)$,第3层为空洞卷积$(3,1,3)$,那么第3层的感受野为 $13$,计算步骤如下:

$$r^{(0)} = 1$$ $$r^{(1)} = r^{(0)} + (k^{(1)}-1)*j^{(0)}=1 + (3-1)*1 = 3$$ $$r^{(2)} =r^{(1)} + (k^{(2)}-1)*j^{(1)}= 3 + (3-1)*1 = 5$$ $$r^{(3)} =r^{(2)} + d^{(3)}*(k^{(3)}-1)*j^{(2)}=5 + 2*(3-1)*2= 13$$

反卷积(Deconvolution Conv)

反卷积的英文名为 Deconvolution 或 Transposed Convolution 或 Fractional-strided Convolutions, 它将特征图从低分辨率映射到大分辨率,用于扩大图像尺寸。

反卷积是一种特殊的正向卷积,而不是卷积的反过程。那么反卷积如何增加尺寸呢?方法和空洞卷积类似,只是 反卷积是在输入端填入空洞,来增加输入的尺寸,而空洞卷积是在卷积核填入空洞,来减少参数数量。

沿用前面的符号约定,我来描述一下反卷积令输出尺寸增大的过程。

设输入$I=3$, 卷积核$K=3$, 填充$P=1$, 步幅$S=1$, 空洞$D=1$,考虑二维的情况:

求得该反卷积的输出尺寸为 5x5。

瓶颈卷积(Pointwise Conv)

常被称为瓶颈层( Bottleneck Layer),用来缩减参数量,瓶颈层的叫法很形象,就像漏斗一样。瓶颈层的计算方式也常被称为 Pointwise 操作,所以瓶颈卷积也叫做 Pointwise Convolution。

举例解释一下参数如何被降低的。

$$input;256d \to 1\times 1\times 64 \to 3\times 3\times 64 \to 1\times1\times 256 \to output; 256d$$

上面的结构,256维的输入先经过一个1×1×64的卷积层,再经过一个3×3×64的卷积层,最后经过一个1×1×256的卷积层,输出256维。参数量为: $$256\times 1\times 1\times 64 + 64\times 3\times 3\times 64 + 64\times 1\times 1\times 256 = 69,632$$

如果采用传统方案:

$$input; 256d \to 3\times 3\times 256 \to output; 256d$$

其参数量为:$256\times 3\times 3\times 256 = 589,824$, 瓶颈卷积的参数较传统方案降低了约 8.5 倍。

仔细想一想,发现瓶颈层在计算上的效果和全连接层一样,通过一个权重变换达到降维目的。

深度卷积(Depthwise Conv)

深度卷积( Depthwise Convolution )的想法是一个卷积核仅对一个通道进行计算,且输入通道数等于输出通道数,这种计算方式又被叫做 depthwise 操作。之所以叫做深度卷积,是因为通道这个维度常被称为深度,比如一个RGB图像,我们可以用高x宽x深度(或通道数)来标定它的尺寸。 注意,深度卷积并不是什么特别的想法,它只是组卷积的极端形式,组卷积是把通道数分成了几组,深度卷积的分组数量等于输入的通道数量。

对于 Depthwise Convolution 的公式,我认为表达得比较好的版本是这个:

$$O_{i,c} = DepthwiseConv(X,W_{c,:},i,c) = \sum_{j=1}^k W_{c,j}\cdot X_{(i+j-\lceil{k+1\over 2}\rceil),c}$$

其中,

轻权重卷积(Lightweight Conv)

轻权重卷积(Lightweight Convolution) 由 Depthwise 卷积进化而来,如果你理解了深度卷积的公式,那么你就能根据轻权重卷积的公式立即明白它改进了什么。

$$LightConv(X, W_{\lceil{cH\over d}\rceil, :}, i, c) = DepthwiseConv(X, softmax(W_{\lceil{cH\over d}\rceil, :}), i, c)$$

解释一下,这里的权重 $W$ 即卷积核 ( $W\in R^{H\times k}$ ) ,Depthwise时,卷积核的数量有 d 个,Lightweight 时,卷积核的数量被降低到 H 个。没错,就是对卷积核分组,把原来的 $d\over H$ 个卷积核融合成一个卷积核,外部再套一个 softmax 函数是归一化的考虑。经过这样调整后,参数量继续被降低到一个相当的程度。

H 表示共分多少组,$\lceil{cH\over d}\rceil$ 向上取整,算出分组编号 h , 这时 softmax 函数的公式为:

$$ softmax(W\rparen_{h,j} = \cfrac {exp W_{h,j}} {\sum_{j’=1}^k exp W_{h,j’}} $$

对比深度可分离卷积,如果不考虑 Pointwise 部分,在一个感受野下,轻权重卷积的参数量由 Depthwise 卷积的 $k\cdot c$ 降低到 $k\cdot H$。

动态卷积(Dynamic Conv)

动态卷积 ( Dynamic Convolution ) 继续在卷积核上做文章,前面的卷积核仅仅是个可训练的权重,动态卷积把它发展为一个随输入 X 中元素变化的线性函数。 $$DynamicConv(X, i, c) = LightConv(X, f(X_i\rparen_{h,:}, i, c)$$ 其中, $$f(X_i) = \sum_{c=1}^d W_{h,j,c}^Q X_{i,c}$$ 这里的 $W^Q \in R^{H\times k\times d}$ ,因此对于一个感受野,参数量为 $k\cdot H \cdot d$。

观察轻权重卷积和动态卷积的构成,我认为都属于 depthwise 卷积家族,它们的不同点仅在于对卷积核上施加了不同的函数。对于轻权重卷积而已,它通过减少卷积核数量,同时兼顾卷积核中其他元素的相关性,进一步降低了参数量;对于动态卷积而言,它在轻权重卷积基础上,又多兼顾了通道间的相关性,但参数量有所增加。

可变形卷积(Deformable Conv)

可变形卷积 (Deformable Convolution) 的想法是在卷积核上做文章。卷积核一般的形状为正方形或长方形,由于图像中我们感兴趣的区域往往是不规则图形,如果让卷积核的形状能根据关注区域的形状发生形变,那么是否会获得更好的性能呢?比如针对缩放的物体,就训练出能缩放的卷积核,对于旋转的物体,就训练出能旋转的卷积核,这样抽取出的特征将有更好的泛化性。

该想法的提出来自微软亚洲研究院。它的方法是在原来的卷积核前面再加一层过滤器(记为偏移过滤器),这层过滤器学习的是下一层卷积核的位置偏移量。假设输入的形状为 [H,W,C],经过偏移过滤器后输出的形状为 [H, W, 2 x C],这里的通道变为原来的两倍。因为我们需要在这个偏移区域( offset field )里面取一组卷积核的偏移坐标(记为 offsets ),而一个offset肯定不能一个值就表示的,最少也要用两个值(x 方向上的偏移和 y 方向上的偏移)。取完了这些值,就可以顺利使卷积核形变,后面再按常规卷积操作即可。

该卷积网络在自动驾驶的图像语义分割任务上获得了 5 个点的提升。


分类二:卷积结构

组卷积(Grouped Conv)

组卷积(Grouped Convolution)曾被用于 AlexNet 中,将模型分布在两个 GPU 上以解决内存处理问题。用一个 32 通道的例子来解释一下组卷积:把 32 个输入通道平均分为 4 组,每组拥有 8 个通道,并分别对 4 组单独做卷积运算。这样的好处是参数较少可以提升计算速度,但是同时,由于每组卷积之间不存在交互,不同组的输出通道与输入通道并不相关。

混合卷积

传统的层叠式网络,基本上都是一个个卷积层的堆叠,每层只用一个尺寸的卷积核。于是有人想,如果每层用多个尺寸的卷积核,是否能提炼到更好的特征呢?

Google的研究员首次在 Inception 家族的结构中采用了这种想法,把上层的输入分别同时经过 1x1、3x3、5x5 的卷积核进行处理,得出的特征再组合起来,传到下一层。这种方法确实令模型的性能有所提高,但紧接而来的副作用是,由于卷积核的数量增多,参数量暴增。

深度可分离卷积(Depthwise separable Conv)

深度可分离卷积 (Depthwise Separable Convolution) 的流行来自谷歌 Xception 结构的流行。这种卷积的思想是把过去一个卷积核对多通道的计算变为一个卷积核仅针对一个通道,被称为 Depthwise 操作,然后再用1x1卷积将每个通道输出的特征图( Feature map) 1进行融合,这被称为 Pointwise 操作,也即是前面提到的瓶颈卷积。 因此,深度可分离卷积实质上是 Depthwise Convolution 和 Pointwise Convolution 的组合。

深度可分离卷积可以看成是交错组卷积的特例,相较于常规卷积操作,显著降低了参数量和运算成本,从而增加了神经网络性能。假设卷积核的尺寸为 k,输入的通道和卷积核的数量均为 c ,则对于一个感受野来说,所需的参数量为 $k\cdot c + c^2$,而传统卷积的参数量为 $k\cdot c^2$。

举例说明:

假设有一个3×3大小的卷积层,其输入通道为16、输出通道为32。常规卷积的做法是,32个3×3大小的卷积核会遍历16个通道中的每个数据,从而产生16×32=512个特征图谱,进而通过叠加每个输入通道对应的特征图谱后融合得到1个特征图谱, 最后得到32个输出通道。涉及的参数有16×32×3×3=4608个。

深度可分离卷积的方式为,用16个3×3大小的卷积核分别遍历16通道的数据,得到了16个特征图谱。接着用32个1×1大小的卷积核遍历这16个特征图谱,进行相加融合。这个过程使用了16×3×3+16×32×1×1=656个参数, 远少于上面的参数个数。

1

特征图( Feature map)是卷积过滤器的输出结果,也叫通道(Channel) ,表示之前输入上某个特征分布的数据。

交错组卷积(Interleaved Group Conv)

交错组卷积( Interleaved Group Convolution ) 的思路由微软研究院提出。前面提到,组卷积中不同组的输出与输入通道之间缺乏相关性,要增加这种相关性,只需要把其他组的输出通道叠加进来,再次进行卷积运算即可。

具体方法为,做两次组卷积,第一次还是和一般组卷积一样,然后把所有组卷积的输出交错排列后,作为第二次组卷积的输入,以达到交错互补的目的。交错组卷积增加了网络的宽度,同时增加了通道间的相关性,自然模型性能会提升。

多头自注意力(Multi-Head Self-Attention)

没错,你没看错,如果你参悟透了多头自注意力结构,它实质仍然是卷积计算。 多头自注意力(Multi-Head Self-Attention,以下简称“MHSA“) 来自 Google Brain 的大作。2018年底,在这个基础上又诞生了 Bert 模型,当时拿下 11 项 NLP 任务最高分。

首先看看 MHSA 到底有什么用?宏观上,当机器理解一句话时,对于句中一个词,MHSA 可以告诉这个词,句中其他词跟它的亲疏程度。换句话说,MHSA 的输出结果用来衡量当前词和其他词之间的关系。多头自注意力机制的主要公式如下:

$$ Attention(Q, K, V) = softmax({QK^T\over \sqrt{d_k}})V \tag 1$$ $$ MultiHead(Q, K, V ) = Concat(head_1, \ldots, head_h)W^O \tag 2$$

其中,

在公式 (1) 中,Q、K、V 分别表示查询向量、键向量和值向量,这三个向量是通过词嵌入与三个权重矩阵相乘后求得。注意力机制本身就是一个打分函数,目标是告诉当前词,句中其他词与当前词的亲疏程度。这里,查询向量代表当前词,键向量代表用来比较的其他词,值向量代表其他词的表达。$QK^T$ 这步运算,你可以把 Q 看成卷积核,然后依次与其他词 K 做卷积运算,计算出向量相似度,下面除以 $\sqrt{d_k}$ ,外面再 softmax 相当于先规范化再归一化,把相似度转成概率值。下一步,把对每个词的相似度权重分别乘以该词的表达向量 V, 最后在求和,这时得出的向量对于当前词来说,它不仅包含了当前词的语义,还包含了当前词与其他词的关系,它是融入句子语境的单词表达。

还要多说一句,为什么叫做自注意力?请注意,公式 (1) 中有三个向量 Q、K、V,它们其实都是单词的语义表达,降低参数量是我们不变的追求,那么对于一个单词而言,令$Q =K=V$,就是自注意力名称的由来。

在公式 (2) 中,将 (1) 式重复做 h 次,再把结果拼接起来,乘以一个权重得到一个维度为 $d_{model}$ 的向量。这里的重复次数就好比一个卷积核的多个通道,它算出当前词向量表达的不同方面的特征。观察动态卷积的设计,发现和多头自注意力的设计似有借鉴之处。

残差网络(Residual Net)

当卷积的层数加深时,网络的表现会越来越差,很大程度上的原因是因为当层数加深时,梯度消散得越来越严重,以至于反向传播很难训练到浅层的网络(靠近输入层的网络)。残差网络 ( Resnet ) 思想是在原来层叠网络的基础上增加跳线连接,在跳线的末端那层同时接入上层输入和跳线过来的输入(即前面某层的输出)。

下面解释一下残差结构为什么能解决梯度消散问题。

$$ a^{l+2} = g(z^{l+2} + a^l) = g(W^{l+2} a^{l+1} + b^{l+2} + a^l)$$ 其中:$a^{l}$ 表示第 $l$ 层的激活值,$g(\cdot)$ 表示激活函数 。

若 $W^{l+2} \approx 0 , b^{l+2} \approx 0$, 激活函数为ReLU, 则: $$ a^{l+2} = ReLU( a^l) \approx a^l $$

从效果上说,相当于直接忽略了 $a^l$ 之后的第 $l+1$ 和第 $l+2$ 两层神经网络,实现了隔层传递。即如果残差网络能训练得到非线性关系,就会忽略跳线输入(short cut 或 skip connection), 否则(发生梯度消失时)忽略非线性层,保留线性层,故能连接更深的网络。

这里还有一个问题,为什么不在 $a^l$ 前加个参数了,并且让这个参数参与学习。残差网络的作者 kaiming 在 papper 中有解释: 假如不是 $x$ 而是 $\lambda_i{x}$ 的话, 梯度里会有一项 $\prod_{i=l}^{L-1}\lambda_i$, 就是从输出到当前层之间经过的 shortcut 上的所有 $\lambda_i$ 相乘,假如 都大于 1 那经过多层之后就会爆炸,都小于 1 就会趋向于 0 而变得和没有 shortcut 一样了。

那如果 $a^l$ 和 $a^{l+2}$ 的维度不同,则 ${W_s}\cdot{a^l}$ 使维度与 $a^{l+2}$ 一致。$W_s$ 有两种方法来得到:

  1. 将 $W_s$ 作为学习参数训练得到;
  2. 固定 $W_s$ 值( 类似单位矩阵 ) ,${W_s} \cdot {a^l}$ 仅使 $a^l$ 截断或补零。

特征重标定卷积(SE Conv)

图像的特征通过卷积核抽取出来,形成一个个特征通道,那么每个特征通道的作用都同等重要么?显然不是。如果有办法通过学习的方式自动获取每个特征通道的重要程度,然后依照计算出来的重要程度去提升有用的特征,抑制用处不大的特征,这就是特征重标定卷积思想的由来。该思路构建的模型结构叫做Squeeze-and-Excitation Network,简称 SENet,曾是 ImageNet 2017 竞赛的冠军模型。

SENet 结构为:首先做普通卷积,输出一个特征图,它的形状为[C,H,W],再分两条路线,第一条直接通过( 类似残差结构的跳线 ),第二条首先进行压缩( Squeeze )操作( 全局平均池化 Global Average Pooling ),把每个通道 2 维的特征压缩成 1 维,得到长度为 C 的特征通道向量(每个数字代表对应通道的特征);然后进行激发( Excitation )操作,即对特征通道向量加两个全连接层( FC Layer ),和非线性映射( Sigmoid ),建模出特征通道间的相关性,得到的输出其实就是每个通道对应的权重, 把这些权重加权到原来的特征上(第一条路),这样就完成了特征通道的权重分配。最后是赋权操作,论文里叫做 scale 操作,把特征通道的权重先归一化,然后加权到每个通道的特征上。

具体分为三个步骤:

不完全小结

神经网络恒古不变的追求其实就一条,减少参数并提升性能。 观察上述各种卷积的变化,发现确有规律可循,它们包括:

其实,对于卷积网络,还可以讨论的方面有激活函数的选择,卷积网络的宽度和深度如何平衡,池化层和dropout的考虑等等,但考虑到上述有些问题目前还没定论,有些内容写在这里,可能会冲淡主题,所以暂时略过,以后发现有必要时再增补。

参考文献

Back to top