- 什么是 CNN
卷积神经网络(Convolutional Neural Networks, CNN)是一类包含卷积计算且具有深度结构的前馈神经网络(Feedforward Neural Networks),是深度学习(deep learning)的代表算法之一。
我们先来看卷积神经网络各个层级结构图:
上图中 CNN 要做的事情是:给定一张图片,是车还是马未知,是什么车也未知,现在需要模型判断这张图片里具体是一个什么东西,总之输出一个结果:如果是车 那是什么车。
- 最左边是数据输入层 (input layer),对数据做一些处理,比如去均值(把输入数据各个维度都中心化为 0,避免数据过多偏差,影响训练效果)、归一化(把所有的数据都归一到同样的范围)、PCA / 白化等等。CNN 只对训练集做 “去均值” 这一步。
- CONV:卷积计算层 (conv layer),线性乘积求和。
- RELU:激励层 (activation layer),下文有提到:ReLU 是激活函数的一种。
- POOL:池化层 (pooling layer),简言之,即取区域平均或最大。
- FC:全连接层 (FC layer)。
这几个部分中,卷积计算层是 CNN 的核心。
1.1 输入层
在做输入的时候,需要把图片处理成同样大小的图片才能够进行处理。
常见的处理数据的方式有:
去均值 (常用)
- AlexNet:训练集中 100 万张图片,对每个像素点求均值,得到均值图像,当训练时用原图减去均值图像。
- VGG:对所有输入在三个颜色通道 R/G/B 上取均值,只会得到 3 个值,当训练时减去对应的颜色通道均值。(此种方法效率高)
TIPS: 在训练集和测试集上减去训练集的均值。
归一化
幅度归一化到同样的范围。
PCA / 白化 (很少用)
- 用 PCA 降维
- 白化是对数据每个特征轴上的幅度归一化。
1.2 卷积计算层 (conv)
对图像(不同的数据窗口数据)和滤波矩阵(一组固定的权重:因为每个神经元的多个权重固定,所以又可以看做一个恒定的滤波器 filter)做内积(逐个元素相乘再求和)的操作就是所谓的『卷积』操作,也是卷积神经网络的名字来源。
滤波器 filter 是什么呢!请看下图。图中左边部分是原始输入数据,图中中间部分是滤波器 filter,图中右边是输出的新的二维数据。
不同的滤波器 filter 会得到不同的输出数据,比如颜色深浅、轮廓。 相当于提取图像的不同特征,模型就能够学习到多种特征。 用不同的滤波器 filter,提取想要的关于图像的特定信息:颜色深浅或轮廓。如下图所示。
在 CNN 中,滤波器 filter(带着一组固定权重的神经元)对局部输入数据进行卷积计算。每计算完一个数据窗口内的局部数据后,数据窗口不断平移滑动,直到计算完所有数据。这个过程中,有这么几个参数:
- 深度 depth:神经元个数,决定输出的 depth 厚度。同时代表滤波器个数。
- 步长 stride:决定滑动多少步可以到边缘。
- 填充值 zero-padding:在外围边缘补充若干圈 0,方便从初始位置以步长为单位可以刚好滑倒末尾位置,通俗地讲就是为了总长能被步长整除。
参数共享机制
假设每个神经元连接数据窗的权重是固定对的。固定每个神经元连接权重,可以看做模板,每个神经元只关注一个特性 (模板),这使得需要估算的权重个数减少:一层中从 1 亿到 3.5 万。
一组固定的权重和不同窗口内数据做内积:卷积
作用在于捕捉某一种模式,具体表现为很大的值。
卷积操作的本质特性包括稀疏交互和参数共享。
1.3 激励层
把卷积层输出结果做非线性映射。
激活函数有:
- sigmoid:在两端斜率接近于 0,梯度消失。
- ReLu:修正线性单元,有可能出现斜率为 0,但概率很小,因为 mini-batch 是一批样本损失求导之和。
TIPS:
- CNN 慎用 sigmoid!慎用 sigmoid!慎用 sigmoid!
- 首先试 RELU,因为快,但要小心点。
- 如果 RELU 失效,请用 Leaky ReLU 或者 Maxout。
- 某些情况下 tanh 倒是有不错的结果,但是很少。
1.4 池化层
也叫下采样层,就算通过了卷积层,纬度还是很高 ,需要进行池化层操作。
- 夹在连续的卷积层中间。
- 压缩数据和参数的量,降低维度。
- 减小过拟合。
- 具有特征不变性。
方式有:Max pooling、average pooling
Max pooling
取出每个部分的最大值作为输出,例如上图左上角的 4 个黄色方块取最大值为 3 作为输出,以此类推。
average pooling
每个部分进行计算得到平均值作为输出,例如上图左上角的 4 个黄色方块取得平均值 2 作为输出,以此类推。
1.5 全连接层
全连接层的每一个结点都与上一层的所有结点相连,用来把前边提取到的特征综合起来。由于其全连接的特性,一般全连接层的参数也是最多的。
- 两层之间所有神经元都有权重连接
- 通常全连接层在卷积神经网络尾部
1.6 层次结构小结
CNN 层次结构 | 作用 |
---|---|
输入层 | 卷积网络的原始输入,可以是原始或预处理后的像素矩阵 |
卷积层 | 参数共享、局部连接,利用平移不变性从全局特征图提取局部特征 |
激活层 | 将卷积层的输出结果进行非线性映射 |
池化层 | 进一步筛选特征,可以有效减少后续网络层次所需的参数量 |
全连接层 | 用于把该层之前提取到的特征综合起来。 |
1.7 CNN 优缺点
优点:
- 共享卷积核,优化计算量。
- 无需手动选取特征,训练好权重,即得特征。
- 深层次的网络抽取图像信息丰富,表达效果好。
- 保持了层级网络结构。
- 不同层次有不同形式与功能。
缺点:
- 需要调参,需要大样本量,GPU 等硬件依赖。
- 物理含义不明确。
与 NLP/Speech 共性:
都存在局部与整体的关系,由低层次的特征经过组合,组成高层次的特征,并且得到不同特征之间的空间相关性。
- 典型 CNN 发展历程
- LeNet,这是最早用于数字识别的 CNN
- AlexNet, 2012 ILSVRC 比赛远超第 2 名的 CNN,比 LeNet 更深,用多层小卷积层叠加替换单大卷积层。
- ZF Net, 2013 ILSVRC 比赛冠军
- GoogLeNet, 2014 ILSVRC 比赛冠军
- VGGNet, 2014 ILSVRC 比赛中的模型,图像识别略差于 GoogLeNet,但是在很多图像转化学习问题 (比如 objectdetection) 上效果很好
- ResNet(深度残差网络(Deep Residual Network,ResNet)), 2015ILSVRC 比赛冠军,结构修正 (残差学习) 以适应深层次 CNN 训练。
- DenseNet, CVPR2017 best paper,把 ResNet 的 add 变成 concat
- 图像相关任务
3.1 图像识别与定位
classification:C 个类别识别
- input:Image
- Output:类别标签
- Evaluation metric:准确率
Localization 定位)
Input:Image
Output:物体边界框 (x,y,w,h)
Evaluation metric:交并准则 (IOU) > 0.5 图中阴影部分所占面积
3.1.1 思路 1:识别 + 定位过程
识别可以看作多分类问题 (用 softmax),用别人训练好的 CNN 模型做 fine-tune
定位的目标是 (x,y,w,h) 是连续值,当回归问题解决(mse)
在 1 的 CNN 尾部展开 (例如把最后一层拿开),接上一个(x,y,w,h) 的神经网络,成为 classification+regression 的模型。
更细致的识别可以提前规定好有 k 个组成部分,做成 k 个部分的回归,
例如: 框出两只眼睛和两条腿,4 元祖 * 4=16(个连续值)
Regression 部分用欧氏距离损失,使用 SGD 训练。
3.1.2 思路 2:图窗 + 识别
- 类似刚才的 classification+regression 思路
- 咱们取不同大小的 “框”
- 让框出现在不同的位置
- 判定得分
- 按照得分的高低对 “结果框” 做抽样和合并
3.2 物体检测 (object detection)
3.2.1 过程
当图像有很多物体怎么办的?难度可是一下暴增啊。
那任务就变成了:多物体识别 + 定位多个物体,那把这个任务看做分类问题?
看成分类问题有何不妥?
- 你需要找很多位置, 给很多个不同大小的框
- 你还需要对框内的图像分类
- 当然, 如果你的 GPU 很强大, 恩, 那加油做吧…
边缘策略: 想办法先找到可能包含内容的图框 (候选框),然后进行分类问题的识别。
方法:根据 RGB 值做区域融合。fast-CNN,共享图窗,从而加速候选框的形成。
R-CNN => fast-CNN => faster-RCNN 速度对比
3.2.2 R-CNN
R-CNN 的简要步骤如下:
- 输入测试图像。
- 利用选择性搜索 Selective Search 算法在图像中从下到上提取 2000 个左右的可能包含物体的候选区域 Region Proposal。
- 因为取出的区域大小各自不同,所以需要将每个 Region Proposal 缩放(warp)成统一的 227x227 的大小并输入到 CNN,将 CNN 的 fc7 层的输出作为特征。
- 将每个 Region Proposal 提取到的 CNN 特征输入到 SVM 进行分类。
3.2.3 SPP-Net
SPP:Spatial Pyramid Pooling(空间金字塔池化),SPP-Net 是出自 2015 年发表在 IEEE 上的论文。
众所周知,CNN 一般都含有卷积部分和全连接部分,其中,卷积层不需要固定尺寸的图像,而全连接层是需要固定大小的输入。所以当全连接层面对各种尺寸的输入数据时,就需要对输入数据进行 crop(crop 就是从一个大图扣出网络输入大小的 patch,比如 227×227),或 warp(把一个边界框 bounding box(红框) 的内容 resize 成 227×227)等一系列操作以统一图片的尺寸大小,比如 224_224(ImageNet)、32_32(LenNet)、96*96 等。
所以才如你在上文中看到的,在 R-CNN 中,“因为取出的区域大小各自不同,所以需要将每个 Region Proposal 缩放(warp)成统一的 227x227 的大小并输入到 CNN”。
但 warp/crop 这种预处理,导致的问题要么被拉伸变形、要么物体不全,限制了识别精确度。没太明白?说句人话就是,一张 16:9 比例的图片你硬是要 Resize 成 1:1 的图片,你说图片失真不?
SPP Net 的作者 Kaiming He 等人逆向思考,既然由于全连接 FC 层的存在,普通的 CNN 需要通过固定输入图片的大小来使得全连接层的输入固定。那借鉴卷积层可以适应任何尺寸,为何不能在卷积层的最后加入某种结构,使得后面全连接层得到的输入变成固定的呢?
这个 “化腐朽为神奇” 的结构就是 spatial pyramid pooling layer。
它的特点有两个:
结合空间金字塔方法实现 CNNs 的多尺度输入。
SPP Net 的第一个贡献就是在最后一个卷积层后,接入了金字塔池化层,保证传到下一层全连接层的输入固定。
换句话说,在普通的 CNN 机构中,输入图像的尺寸往往是固定的(比如 224*224 像素),输出则是一个固定维数的向量。SPP Net 在普通的 CNN 结构中加入了 ROI 池化层(ROI Pooling),使得网络的输入图像可以是任意尺寸的,输出则不变,同样是一个固定维数的向量。
简言之,CNN 原本只能固定输入、固定输出,CNN 加上 SSP 之后,便能任意输入、固定输出。神奇吧?
只对原图提取一次卷积特征
在 R-CNN 中,每个候选框先 resize 到统一大小,然后分别作为 CNN 的输入,这样是很低效的。
而 SPP Net 根据这个缺点做了优化:只对原图进行一次卷积计算,便得到整张图的卷积特征 feature map,然后找到每个候选框在 feature map 上的映射 patch,将此 patch 作为每个候选框的卷积特征输入到 SPP layer 和之后的层,完成特征提取工作。
如此这般,R-CNN 要对每个区域计算卷积,而 SPPNet 只需要计算一次卷积,从而节省了大量的计算时间,比 R-CNN 有一百倍左右的提速。
3.2.4 Fast R-CNN
SPP Net 真是个好方法,R-CNN 的进阶版 Fast R-CNN 就是在 R-CNN 的基础上采纳了 SPP Net 方法,对 R-CNN 作了改进,使得性能进一步提高。
R-CNN 有一些相当大的缺点(把这些缺点都改掉了,就成了 Fast R-CNN)。
大缺点: 由于每一个候选框都要独自经过 CNN,这使得花费的时间非常多。
解决: 共享卷积层,现在不是每一个候选框都当做输入进入 CNN 了,而是输入一张完整的图片,在第五个卷积层再得到每个候选框的特征。
原来的方法:许多候选框(比如两千个)—>CNN—> 得到每个候选框的特征 —> 分类 + 回归
现在的方法:一张完整图片 —>CNN—> 得到每张候选框的特征 —> 分类 + 回归
所以容易看见,Fast R-CNN 相对于 R-CNN 的提速原因就在于:不过不像 R-CNN 把每个候选区域给深度网络提特征,而是整张图提一次特征,再把候选框映射到 conv5 上,而 SPP 只需要计算一次特征,剩下的只需要在 conv5 层上操作就可以了。
算法步骤:
- 在图像中确定约 1000-2000 个候选框 (使用选择性搜索)。
- 对整张图片输进 CNN,得到 feature map。
- 找到每个候选框在 feature map 上的映射 patch,将此 patch 作为每个候选框的卷积特征输入到 SPP layer 和之后的层。
- 对候选框中提取出的特征,使用分类器判别是否属于一个特定类。
- 对于属于某一类别的候选框,用回归器进一步调整其位置。
3.2.5 Faster R-CNN
Fast R-CNN 存在的问题:存在瓶颈:选择性搜索,找出所有的候选框,这个也非常耗时。那我们能不能找出一个更加高效的方法来求出这些候选框呢?
解决:加入一个提取边缘的神经网络,也就说找到候选框的工作也交给神经网络来做了。
所以,rgbd 在 Fast R-CNN 中引入 Region Proposal Network(RPN) 替代 Selective Search,同时引入 anchor box 应对目标形状的变化问题(anchor 就是位置和大小固定的 box,可以理解成事先设置好的固定的 proposal)。这就是 Faster R-CNN。
算法步骤:
- 对整张图片输进 CNN,得到 feature map。
- 卷积特征输入到 RPN,得到候选框的特征信息。
- 对候选框中提取出的特征,使用分类器判别是否属于一个特定类。
- 对于属于某一类别的候选框,用回归器进一步调整其位置。
3.2.6 YOLO
Faster R-CNN 的方法目前是主流的目标检测方法,但是速度上并不能满足实时的要求。YOLO 一类的方法慢慢显现出其重要性,这类方法使用了回归的思想,利用整张图作为网络的输入,直接在图像的多个位置上回归出这个位置的目标边框,以及目标所属的类别。
我们直接看上面 YOLO 的目标检测的流程图:
- 给个一个输入图像,首先将图像划分成 7*7 的网格。
- 对于每个网格,我们都预测 2 个边框(包括每个边框是目标的置信度以及每个边框区域在多个类别上的概率)。
- 根据上一步可以预测出 7_7_2 个目标窗口,然后根据阈值去除可能性比较低的目标窗口,最后 NMS 去除冗余窗口即可。
小结:YOLO 将目标检测任务转换成一个回归问题,大大加快了检测的速度,使得 YOLO 可以每秒处理 45 张图像。而且由于每个网络预测目标窗口时使用的是全图信息,使得 false positive 比例大幅降低(充分的上下文信息)。
但是 YOLO 也存在问题:没有了 Region Proposal 机制,只使用 7*7 的网格回归会使得目标不能非常精准的定位,这也导致了 YOLO 的检测精度并不是很高。
3.2.7 SSD
SSD: Single Shot MultiBox Detector。上面分析了 YOLO 存在的问题,使用整图特征在 7*7 的粗糙网格内回归对目标的定位并不是很精准。那是不是可以结合 region proposal 的思想实现精准一些的定位?SSD 结合 YOLO 的回归思想以及 Faster R-CNN 的 anchor 机制做到了这点。
上图是 SSD 的一个框架图,首先 SSD 获取目标位置和类别的方法跟 YOLO 一样,都是使用回归,但是 YOLO 预测某个位置使用的是全图的特征,SSD 预测某个位置使用的是这个位置周围的特征(感觉更合理一些)。
那么如何建立某个位置和其特征的对应关系呢?可能你已经想到了,使用 Faster R-CNN 的 anchor 机制。如 SSD 的框架图所示,假如某一层特征图 (图 b) 大小是 88,那么就使用 33 的滑窗提取每个位置的特征,然后这个特征回归得到目标的坐标信息和类别信息(图 c)。
不同于 Faster R-CNN,这个 anchor 是在多个 feature map 上,这样可以利用多层的特征并且自然的达到多尺度(不同层的 feature map 3*3 滑窗感受野不同)。
小结:SSD 结合了 YOLO 中的回归思想和 Faster R-CNN 中的 anchor 机制,使用全图各个位置的多尺度区域特征进行回归,既保持了 YOLO 速度快的特性,也保证了窗口预测的跟 Faster R-CNN 一样比较精准。SSD 在 VOC2007 上 mAP 可以达到 72.1%,速度在 GPU 上达到 58 帧每秒。
3.3 语义 (图像) 分割
识别图上 pixel 的类别,用全卷积网络。
- 代码实现 CNN
- 参考文献
作者:@mantchs
GitHub:github.com/NLP-LOVE/ML…