写点什么

深度学习之解构卷积

  • 2022 年 5 月 01 日
  • 本文字数:3526 字

    阅读完需:约 12 分钟

1. 卷积神经网络组成

卷积神经网络(Convolutional Neural Network)在深度学习特别是机器视觉(CV)任务中有着重要的作用。Yann Lecun 在 1998 年第一次提出了基于卷积神经网络的手写字符识别网络 LeNet-5,采用了基于梯度的反向传播算法来训练,模型包括简单的 2 个卷积层(2 个 pooling 层)和 3 个全连接。由于算力的问题,LeNet-5 没有得到推广,直到 2012 年 AlexNet 网络配合 GPU 算力的支持,以卷积神经网络为基础的深度学习开始普及。



上图可知,LeNet-5 已经具备基本的卷积神经网络的雏形了,卷积层负责提取特征,全连接层负责分类识别。卷积神经网络的组成部分如下:

  • 卷积层

  • pooling 层:下采样层(max pooling 和 avg pooling)

  • 激活函数

  • 全连接层



其中卷积层以扫窗的方式,通过卷积核(Conv kernel)对图像进行卷积操作,提取局部的特征;每个卷积层可以多个卷积核,每个核对应一个输出通道(feature map),可以提取不同的特征,而共享一个卷积核的参数;卷积核的值,是通过学习得到。卷积操作来源数字图像处理的卷积即点乘后加和,涉及参数有卷积核大小kernel_size 填充padding 卷积移动步长stride



卷积神经网络相比传统人工神经网络有如下特点:

  • 连接稀疏(sparsity of connections):卷积操作是提取局部的信息,共享一个卷积核的参数,减少参数量。同时这符合视觉的特点,人眼不需要一次查看整张图,可以只看部分图,就可以做出辨识

  • 参数共享(parameters sharing):不同位置的相同特征可以用同一个卷积核进行提取特征

  • pooling 下采样层:降低维度,减少参数。也符合视觉的特点,一副图通过下采样 2 倍后,并不影响人眼做出辨识

卷积神经网络有效的提取特征的同时,大大的降低了参数量,提高了效率,配合 GPU 高效的计算能力,使得深度学习不断的普及。

以下为卷积神经网络提取到特点示例:



随着深度学习不断发展,出现了不同类型的卷积操作,本文和大家一起分享当前主流的卷积操作和实现,主要有:

  • 空洞卷积

  • 1*1 卷积

  • 反卷积

  • 深度可分离卷积

  • 可变形卷积

  • 3D 卷积


2. 卷积操作

2.1 空洞卷积

通常,一个 3x3 的卷积核具备 3*3 的感受野(receptive field),不断的堆叠卷积层,逐渐加大感受野,感受野越大提取到特征接收的信息越多。为了增加单个卷积核的感受野,Multi-scale context aggregation with dilated convolutions 提出了空洞卷积。空洞卷积顾名思义就是在常规卷积核中加入空洞(补 0)。如下图所示,a 是普通 3x3 卷积,b 是空洞率为 2 的 3x3 卷积核,具备 7x7 的感受野;c 是空洞率为 4 的 3x3 卷积核,具备 15x15 的感受野。



在实现上,有效的 kernel value 还是 3x3 的值,只是在做点乘操作时,点乘的对应的 feature map 值的位置改变了。这样就可以达到不改变参数量的情况下,增大感受野。

空洞卷积除了增大感受野的同时,配合普通卷积可以捕捉不同感受野的信息,获取了多尺度信息,对于一些检测和分割任务来说是很重要的。

import torchfrom torch import nn as nninput = torch.randn(1, 256, 12, 12)dilation_conv = nn.Conv2d(256, 64, kernel_size=3, stride=1, padding=0, dilation=2, groups=1, bias=True, padding_mode='zeros')output = dilation_conv(input)output.size()# torch.Size([1, 64, 8, 8])
复制代码

2.2 1x1 卷积

卷积层中的卷积核基本是 3x3, 5x5,1x1 卷积最早是在 Network in Network 中提出,后来在 googlenet 的 Inception 系列和 Reset 中被广泛应用。一个维度为(h, w, c)的输入 feature map, 经过(1, 1, cout)卷积核后,得到(h, w, cout)。可知,1x1 的卷积和普通卷积在计算熵没什么区别,但是 1x1 有它独特的特点:

  • 改变输出维度:当 cout>c, 达到升维目的;当 cout<c,达到减维目的;可以方便的改变维度的数量而保存大小不变

  • 通道融合:根据卷积操作(点乘后汇总),1x1 卷积其实是将所有的 channel 上的值汇总,达到通道融合的特点。

Inception v2 中的 1x1 卷积:



Resnet 中 1x1 卷积:



import torchfrom torch import nn as nninput = torch.randn(1, 256, 12, 12)one_by_one_conv = nn.Conv2d(256, 64, kernel_size=1, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros')output = one_by_one_conv(input)output.size()# torch.Size([1, 64, 12, 12])
复制代码

2.3 反卷积或转置卷积

反卷积顾名思义是卷积的反操作,比较科学说法是转置卷积(transposed convolution operator), 通常应用于上采样操作比如超分任务,分割任务等等。 普通卷积如果没有 padding 情况下,feature map 的尺度是不断的变小的(降采样),而转置卷积是上采样,尺度变大,所以才说是反卷积。

from torch import nn as nninput = torch.randn(1, 16, 12, 12)downsample = nn.Conv2d(16, 16, 3, stride=2, padding=1)upsample = nn.ConvTranspose2d(16, 16, 3, stride=2, padding=1)h = downsample(input)h.size()# torch.Size([1, 16, 6, 6])output = upsample(h, output_size=input.size())output.size()# torch.Size([1, 16, 12, 12])
复制代码

2.4 深度可分离卷积

深度可分离卷积是在 Xception 提出,在 MoblieNet 系列等轻量级模型中广泛应用,主要是为了减少参数量。

对于输入是 channel 是 M 的 feature map, 想提取 N 个输出 channel 的结果,普通卷积如下图所示是采用 N 个卷核(Dk, Dk),由于输入 M 个 channel,所以实际上每个卷积的维度是(Dk,Dk, M),可知参数量为 DkDkM*N:


而深度可分离卷积,首先对卷积核维度进行分离,即每个卷积的维度是(Dk,Dk, M)分离成 M 个(Dk,Dk,1),分别对应到的 M 个 channel 的每一个 channel,这样分别相乘计算卷积,这样得到的是输出的 channel 是 M,参数量是 DkDkM,此时的问题是输出 channel 不对,而且原始输入的 channel 之间是分离计算的。



此时就要对特征进行融合和输出想要的 channel 数,这个时候 1x1 卷积出场了。pointwise 操作利用 N 个 1x1 卷积,就生成 channel 为 N 的 feature map。而这一步的参数量是 MN,全部的参数量( DkDkM + MN),相比 DkDkM*N,参数量降低的非常多。



pytorch 实现其实很简单,分离卷积通过分组(groups)的方式

import torchfrom torch import nn as nninput = torch.randn(1, 256, 12, 12)dw_conv = nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=0, dilation=1, groups=256, bias=False, padding_mode='zeros')one_by_one_conv = nn.Conv2d(256, 64, kernel_size=1, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros')dw_output = dw_conv(input)print(dw_output.size())# torch.Size([1, 256, 10, 10])output = one_by_one_conv(dw_output)output.size()# torch.Size([1, 64, 10, 10])
复制代码

2.5 可变形卷积

普通的卷积通常是规则形状的,对于分割或目标检测任务来说物体的形状通常是不规则的,deformable convolution 可变形卷积(Deformable Convolutional Networks)通过增加位置偏移使得卷积核值的位置变得不规则,来提取更有效的不规则特征,能够自动调整尺度或者感受野。



从上图可知,可变形卷积对普通卷积核的每个位置增加一个方向参数,使得同样参数情况下,可以学习不规则的形状,同时也会有可变的感受野。在实现上,通过一个卷积来学习偏离的值(offset),进行卷积的时候,普通的卷积核和 offset 值,进行卷积操作。可想而知,offset 是位置偏移,可能是小数,这样卷积核位置就无法和 feature map 的值一一对应,此时采用插值算法进行对应位置来进行卷积操作,如下图所示



具体实现基于 cuda 的方式来实现,参见:https://github.com/4uiiurz1/pytorch-deform-conv-v2

2.6 3D 卷积

从前面章节的卷积都是二维卷积(2D)对应的维度为(h, w, c), 而 3D 卷积就是多一个维度(t, h, w, c);3D 卷积通常用在视频图像处理上,在空间维度上增加一个时间维度,比较出名的算法是 C3D(Learning Spatiotemporal Features with 3D Convolutional Networks)。2D 和 3D 的区别如下图,输出是立体:



动态操作如下(来自网络):



import torchfrom torch import nn as nn# With square kernels and equal stridem = nn.Conv3d(16, 33, 3, stride=2)# non-square kernels and unequal stride and with paddingm = nn.Conv3d(16, 33, (3, 5, 2), stride=(2, 1, 1), padding=(4, 2, 0))input = torch.randn(20, 16, 10, 50, 100)output = m(input)output.size()# torch.Size([20, 33, 8, 50, 99])
复制代码

3. 总结

本文和大家分享卷积神经网络中各种不同的卷积操作和作用,希望对大家有帮助,总结如下:

  • CNN 三剑客:卷积层+pooling 下采样+激活函数(非线性)

  • 空洞卷积:增大感受野,多尺度信息

  • 1*1 卷积:方便的工具卷积,进行通道融合

  • 反卷积:上采样卷积

  • 深度可分离卷积:先分离,再融合,降低参数

  • 可变形卷积:给卷积加上位置偏差,结合插值进行卷积,识别可变形态

  • 3D 卷积:给 2D 卷积增加一维





发布于: 刚刚阅读数: 2
用户头像

公众号:人工智能微客(weker) 2019.11.21 加入

人工智能微客(weker)长期跟踪和分享人工智能前沿技术、应用、领域知识,不定期的发布相关产品和应用,欢迎关注和转发

评论

发布
暂无评论
深度学习之解构卷积_人工智能_AIWeker-人工智能微客_InfoQ写作社区