卷积神经网络 CNN 笔记 - 目标探测

介绍目标探测的基本方法,传统方法 DPM,神经网络分类 R-CNN 系列方法和神经网络回归 YoLo 系列方法。

目标探测

先来看下什么是目标探测,下图矩形框(running box)表示的物体都可以作为目标探测的对象。不止矩形框,椭圆形框在某些场合更适合做目标探测,因为它能更好的捕捉对象,并对物体朝向做相应调整,机变性更好。
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B.png

目标探测的任务一般分为单目标探测多目标探测。目的一是找到目标的位置坐标,二是判定目标类别。
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/%E4%BB%BB%E5%8A%A1.png

目标探测的应用场景有安防、自动驾驶等。从技术方面讲,目标探测传统方法用的是DPM,虽然目前已经被神经网络超越,但是很多思想可以借鉴。神经网络大体上有两类方法,一类是分类方法主要是RCNN系列方法 ,先找到若干候选区,然后一个区域一个区域排查,判断有没有要找的物体;另一类是回归方法主要是YoLo系列方法,直接找到区域,以及区域有什么物体。

下面来看下目标探测的两个直接思路。

直接思路一:回归问题

一类思路是把目标探测看作是一个回归问题。直接生成 class score,也就是判断是该类别(物品)的 confidence value,和 box coordinates,也就是检测框的坐标值。整个任务的损失函数其实是位置差和分类差的一个组合。
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/%E7%9B%B4%E6%8E%A5%E6%80%9D%E8%B7%AF.png

直接思路二:局部识别问题

另一类思路是在很多位置上尝试识别,能够完成识别的地方就是目标位置。如下图,我们生成潜在的候选区域(proposal),然后采用分类器逐个判别这些区域内图像是不是目标物体,如果是,可以把候选区域做延展(用 regression),看有没有更合适的候选框。
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/cat1.png

一个问题是怎样找到这些候选位置?
一种方法是用不同 scale 的 sliding windows 来遍历所有的位置,这种方法代价太高,另一种更有效的方法是直接计算候选区域。现在有很多算法能够有效的产生候选区域,比较常用的是 EdgeBoxes(在 RCNN 中使用)。
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/%E5%80%99%E9%80%89%E5%8C%BA%E5%9F%9F%E4%BA%A7%E7%94%9F.png

传统方法-DPM

传统方法主要包括 3 个步骤:

  1. 利用不同尺度的滑动窗口在图像上进行区域搜索,定位候选区域;
  2. 对候选区域进行特征提取,如sift,hog,haar等;
  3. 利用分类器进行分类识别,svm等

主要思路就是提取图像特征,制作出激励模板,在原始图像滑动计算,得到激励效果图,然后根据激励分布确定目标位置。如下图人物识别把人为设计的激励模板和 HOG 特征图结合,如果有人,会得到加强的激励,然而同样的,柱子也会得到激励。

DPM(Deformable Part Model)可以看做是HOG(Histograms of Oriented Gradients)+SVM(Surpport Vector Machine) 方法的扩展,大体思路是一致的 — 先计算梯度方向直方图,然后用 SVM 训练得到物体的梯度模型。有了这样的模板就可以直接用来分类了,简单理解就是模型和目标匹配。DPM 只是在模型上做了很多改进工作。
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/dpm1.png

由于目标可能会形变,之前模型不能很好的适应复杂场景的探测,所以一个改进是各个部分单独考虑,对物体的不同部分单独进行学习,所以DPM把物体看成了多个组成部件(比如说人脸的鼻子,嘴巴等),用部件间的关系来描述物体,这个特点非常符合自然界许多物体的非刚性特征。基本思路如下:

  1. 产生多个模板,整体模板(root filter)以及不同局部模板(part filter)
    root filter 包含目标的整体信息,而 part filter 采用高分辨率的细节建模,看的梯度会更加精细
  2. 不同模板同输入图片“卷积”产生特征图
  3. 特征图组合形成融合特征
  4. 对融合特征进行传统分类,回归,得到目标位置
  5. 模型在图像特定位置和尺度的得分, 等于 root filter 的得分加上各个 part filter 得分的总和。每个 part filter 的得分等于该 part 在所有空间位置的得分的最大值,而部件在某位置的得分等于 part filter 在此位置的得分减去此位置的变形代价(也就是 part 偏离其理想位置的程度)
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/dpm2.jpg

DPM 的优点是方法比较直观、简单,运算速度快,也可以适应运动物体变形,很好的处理遮挡、非刚性可变和视觉变换问题,到 2012 年前,是最好的方法。然而 DPM 也有一些缺点

  • 性能一般
  • 激励特征人为设计,表达能力有限,工作量大,难以进行迁移学习
  • 大幅度旋转无法适应,稳定性差

神经网络分类: R-CNN 系列方法

R-CNN(CVPR2014, TPAMI2015)

算法

神经网络的分类思想是对多个位置,不同尺寸,用卷积神经网络判断区域内图片是不是某物候选位置(proposal)提出方法一般用 EdgeBox
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/rcnn1.png

R-CNN 最初提出的时候选择 20 类进行探测,是在 ImageNet 模型的基础上,把 1000 类的分类模型变成能识别 21 类(20类+other)的 Fine-tune 分类模型。
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/rcnn2.jpg
=>
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/rcnn3.jpg

特征的提取过程: 对图片计算候选区域;对候选区域切分图片,对切分部分进行 resize 变成输入大小;提取相应高级特征;存储特征(大容量,200-300G空间存储图片)
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/rcnn4.jpg

单独目标探测器训练:对每一类进行单独训练,保证每一类训练数据平衡,每一类都是 binary 分类(yes/no)。比如猫的分类器,可能大部分图片没有一个理想的猫,只有一个耳朵,这不算猫,我们要与真值进行比较,看左上右下区域,如果重合(共有区域)比较多,就认为是猫的图片。每一类都有很多的正例反例(1/0)。
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/rcnn5.jpg

单独目标回归器训练-基于候选区域微调: 同样的,每一类单独训练,保证每一类训练数据平衡,这里是每一类做 BBOX 回归。目的是在知道是不是猫以及位置的偏移后,用回归对位置进行 offset,离真值(ground truth)更近,最终的探测精度会更高。
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/rcnn6.jpg

总的来说,R-CNN 的测试过程就是

  1. 对每个图像生成 1k-2k 个候选区域
  2. 对每个候选区域,使用深度网络进行特征计算
  3. 特征喂给每一类的 svm 分类器,判别是否属于该类分类;同时用回归修正候选框位置
  4. 后续处理%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/rcnn7.jpg

常用数据集

%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/%E6%95%B0%E6%8D%AE%E9%9B%86.jpg

评估方法

  • MAP(mean average precision)
  • IoU,真值和预测值多重叠部分与两者的并集的比值,一般大于 0.5 就认为是正确的%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/IoU.jpg

R-CNN 结果对比

Regionlets(2013) 并没有经过 fine-tune,R-CNN(2014, AlexNet) 用事先训练好的分类器进行了 fine-tune,R-CNN+bbox reg(AlexNet),用了 regression,加了 offset 对检测框做了范围调整,R-CNN(vgg-16)把 base model 改成了 vgg

总的来说,主要是从下面三个角度进行了模型的调整

  1. Finetune
  2. 回归微调
  3. Base 模型%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/crnn9.jpg

优缺点

优点:

  1. CNN 用于目标探测,利 用了 CNN 高效识别能力, 大大提高性能
  2. 摆脱人为设计物品模版, 方法具有通用性
  3. 分类+回归,有了找到精确位置的可能

缺陷:

  1. 为了检测一个目标,所有候选区域计算,大量卷积运算,非常慢
    对于速度慢这个问题,SPP-NET 给出了解决方案。R-CNN 对图像提完 region proposal(2k 左右)之后将每个 proposal 当成一张图像进行后续处理(CNN提特征+SVM分类),实际上对一张图像进行了2000次提特征和分类的过程!SPP-NET 对图像提一次卷积层特征,然后将 region proposal 在原图的位置映射到卷积层特征图上,这样对于一张图像只需要提一次卷积层特征,然后将每个 region proposal 的卷积层特征输入到全连接层做后续操作
  2. SVM 训练与CNN 断裂, SVM Loss 没办法用于 CNN Loss,有效信息不能用于优化模型, not end-to-end
  3. 每一类单独训练,异常繁琐

Fast R-CNN(ICCV2015)

Fast R-CNN 的三个进步

  • 共享卷积计算
    增加 ROI pooling layer
  • 完整训练(end-to-end)
    用 softmax 代替 svm 分类,用多目标损失函数加入候选框回归,除 region proposal 提取外实现了 end-to-end
  • 多目标一起学习%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/fast%20rcnn.jpg

共享卷积计算

Fast R-CNN 在最后一个卷积层后加了一个 ROI pooling layer,实际上就是上面提到的 SPP-NET 的一个精简版,特点是:

  1. 卷积计算保持空间位置
  2. 共同区域的卷积计算只需进行一次
  3. 切割候选区+提取特征图=计算完整特征图+切割对应候选区
    把图片的 region proposal 切割出来,resize,提取特征,其实就等同于在原图特征图里找到 region proposal%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/%E5%85%B1%E4%BA%AB%E5%8D%B7%E7%A7%AF.jpg

一个重要的问题是不同区域的特征如何保持一致?
全连接层要求接的区域形状一致;所以要特征图里区域的一致性处理,也就是做一个 pooling
特征一致化 - Max Pooling
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/%E7%89%B9%E5%BE%81%E4%B8%80%E8%87%B4%E5%8C%96.jpg

局部区域
100x50 =>按 4:2 pooling
50x100 => 按 2:4 pooling
=> 25x25 feature
=> 225 FC

如果 pooling size 不完美,其实也没有问题,pooling 本身就是填充 pooling 后的图的每一个 pixel,只要从 pooling 前某区域选一个 pixel 值即可,不一定要规整

位置 + 类别联合学习

图片 => cnn feature map计算 => proposal应用 => feature map相应区域做 region pooling 得到固定大小的 feature map => classification & regression
用 softmax 代替 svm 分类,使用多任务损失函数(multi-task loss),将候选框回归直接加入到 cnn 网络中训练,除去 region proposal 的提取阶段,这样的训练过程是端到端的(end-to-end),整个网络的训练和测试十分方便
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/fast%20rcnn.png

性能提升

看一下性能提升的情况
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/%E6%80%A7%E8%83%BD.jpg
然而前提是 不考虑候选区域(proposal)的生成,如果加上候选区域(proposal)的时间
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/%E6%80%A7%E8%83%BD2.jpg
region proposal 的提取使用 selective search,目标检测时间大多消耗在这上面(提region proposal 2~3s,而提特征分类只需0.32s),无法满足实时应用,那么,怎么解决候选区域的计算呢?一个方法是也靠神经网络。

Faster R-CNN(NIPS2015)

RPN(Region Proposal Network)

用神经网络来解决候选区域的生成问题,主要是神经网络特征增加一组输出 RPN(Region Proposal Network)候选区域网络

  1. 直接产生候选区域,无需额外生成
    本质上是 sliding window,RPN 只需在最后的卷积层上滑动一遍,因为 anchor 机制和候选框回归可以得到多尺度多长宽比多 region proposal
  2. 直接用于后续特征图切割

最后的特征图中有很多个 pixel,每个 pixel 和卷积核进行计算,生成 k 个可能的 prpoposal(实际中 k 往往=9,一个区域可能同时被多个物体占用,所以尽可能把可能分布的形状都生成),每个 proposal 有个 score 的计算。如图,左边是 3x3 的卷积网络的特征图,右边是 k 个 anchor box(相当于小的候选生成单元)。我们对特征图进行 sliding window 的计算,每个 pixel 生成 256 长的向量(向量长度其实是自己设计的,vgg 建议 512-d),这个向量用来生成 k 个 proposal 的值,以及对应的 2k score(是/不是目标物体),4k 个 coordinates(上下左右坐标)。
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/faster%20rcnn1.jpg

网络输出的值:

  1. 是不是一个目标
  2. 覆盖范围的相对位置

k=9(3种尺寸,3种长宽比)个 anchor,能产生多少个 proposal?
特征图 size HxW -> HWx9 in paper 2400x9

如果是 VGG conv5 作为特征图,3x3 区域对应的原始图像区域?
经过了 4 个 pooling,往前推,6x6 -> 12x12 -> 24x24 -> 48x48,也就是 16 倍的一个缩放

Anchor的平移不变怎么理解
较小的平移 pooling 过程中忽略,3 个 pixel 的移动经过 4 层的 pooling,移动后的位置和原位置相差可以忽略

Anchor 同外接 Proposal 区别
数量:1-2个数量级减少;性能:更高效;
速度:10x

Anchor 设计的借鉴意义?
神经网络有能力找到最终量,也有能力找到很多中间量。只用 Anchor 判断是不是目标,会不会存在大材小用,能够判断更多吗?或者说,能在是不是目标的基础上,判断是什么目标吗,也就是直接拟合

为了让RPN的网络和Fast R-CNN网络实现卷积层的权值共享,训练 RPN 和 Fast R-CNN的时候用了4阶段的训练方法:

  1. 使用在 ImageNet 上预训练的模型初始化网络参数,微调 RPN 网络;
  2. 使用(1)中RPN网络提取 region proposal 训练 Fast R-CNN网络;
  3. 使用(2)的 Fast R-CNN 网络重新初始化 RPN, 固定卷积层进行微调;
  4. 固定(2)中 Fast R-CNN 的卷积层,使用 (3) 中 RPN 提取的 region proposal 微调网络%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/faster%20rcnn2.jpg

Faster R-CNN 用了直接联合学习(joint learning) 的方法,如上图,一个网络有 4 个损失函数

  1. Anchor 是不是目标
  2. Anchor 回归候选区域回归
  3. Fast R-CNN 分类
  4. Fast R-CNN 基于候选位置回归
    联合学习的方法产生了更少的候选区,但是精度不会受到影响,速度却快了 10 倍,接近于实时处理(@K40 GPU, 12G)。

性能提升

%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/faster%20rcnn3.jpg

接近于实时处理,然而还是很难实时的目标探测,下面的 YOLO 这类方法可以达到实时性。

神经网络回归: YoLo 系列方法

YoLo

算法

YoLo 将目标探测任务看作目标区域预测和类别预测的回归问题,用单个神经网络直接预测物品边界和类别分数,可以直接找到物体是什么,在哪里
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/YoLo.jpg

把图片分成 SxS 的格子(grid cell),一般是 7x7 的网络,每个网格生成:

  1. B 个 Bbox,4 个 coordinates + 1 个 confidence score
  2. N 个类别分数 $Pr(Class_i|Object)$
    与 Anchor 不同的是,这里有 N 个分数,表示属于每一类的分数分别是多少

S=7, B=2, N=20
总共的回归目标: SxSx(5B+N)
​ 2x5+20=30 个参数,49x30=1470 个数值,用来回归
候选区域个数: (B=2) 98 个 << Faster R-CNN
每个小区域生成 2 个候选区,一个小的区域就是一个粗糙的 proposal,对小区域进行大范围的 regression,找到目标
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/yolo2.jpg

损失函数:
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/yolo3.png

性能

性能:

  • 实时运行
  • 精度稍微下降
  • 定位精度较差

经过大量的 pooling,位置的响应会有一定弱化
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/yolo4.png

Limitations

  1. YoLo 的每一个网格只预测两个 boxes,一种类别。这导致模型对相邻目标预测准确率下降。因此,YOLO 对成队列的目标(如一群鸟)识别准确率较低。
  2. YoLo 是从数据中学习预测 bounding boxes,因此,对新的或者不常见角度的目标无法识别。
  3. YoLo 的损失函数对small bounding boxes 和 large bounding boxes 的 error 平等对待,影响了模型识别准确率。因为对于小的 bounding boxes,small error影响更大。

SSD: The Single Shot Detector

SSD 分类更细,网络结构有点像 resnet。中间多层特征参与位置、种类计算,在不同 layer 输出的不同尺寸的 feature map 划格子,在格子上提“anchor”,弥补了 Yolo 只在最后一层分 7x7 的框漏掉的部分。和 Yolo 相比,更快更准确。

  • 候选区 98 vs 8732
  • 速度 21:46 (vgg base)
  • 精度 66.4:74.3
%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-%E7%9B%AE%E6%A0%87%E6%8E%A2%E6%B5%8B/ssd.jpg

参考链接:
目标检测方法——从RCNN、Fast-RCNN到Faster-RCNN
YOLO:实时快速目标检测

徐阿衡 wechat
欢迎关注:徐阿衡的微信公众号
客官,打个赏呗~