深度学习基础之 - 行人检测SSD

时间:2021-10-02 15:15:29

       Faster-RCNN 虽然在效果上做到了 State-Of-The-Art,但效率问题无法做到实时,YOLO 在此基础上提出了改进:

一. Region Proposal

       Region Proposal 过程的优点是能够初步检测有效的 Candidate,缺点是带来效率的降低(Faster构造了两级网络)。

       YOLO去掉了 Faster的 RPN 过程,直接预测物体的种类和位置。

       这是一个里程碑似的 Idea!


二. 直接训练

       YOLO 将目标的分类与定位进行合并,将对应位置的信息 通过网络,对应到最后面的 7*7的格子上,每个格子对应一个30维的向量,分别代表 分类与定位信息。对应图中 30维向量 = (B*5 + C),B是每个Grid对应Bound Box数量,Paper中值为2,C为分类数,值为20。

       YOLO 网络图参考如下:

深度学习基础之 - 行人检测SSD


三. SSD 剖析

SSD全称是:Single Shot MultiBox Detector,作者是 UNC教堂山的 Wei Liu

论文下载地址:http://www.cs.unc.edu/~wliu/papers/ssd.pdf

深度学习基础之 - 行人检测SSD


1. 开山绝技 - 多尺度

     这是对YOLO最大的改进,也是本算法的核心。

     YOLO基于最后一张 Feature Map(特征图)进行提取和分类,某些细节特征的丢失导致精度下降和小目标遗漏。

深度学习基础之 - 行人检测SSD

    与YOLO不同的是,SSD 在多个尺度(Feature Map)上进行了回归,低层的 feature map 蕴含更多的信息,有利于细节保留 及 训练误差回传,提高了精度及小目标的适应能力。

深度学习基础之 - 行人检测SSD

       对于上图(b)(c)所对应 不同分辨率的 Feature Map,同样 3*3 的区域 代表了原图(a)上的目标,蓝色与红色框 的对应关系。

       通过多尺度,对检测效果由很大的提升,在不使用 conv4_3的情况下,mAP 下降到了 68.1%


2. 拿来主义 - 宽高比和Anchor

    SSD 借鉴了 Faster的锚 ,假定以目标中心作为Location,以该中心以不同宽高比进行 Rect 扩展(1:1  1:2  2:1),再结合三种不同尺度,这样我们就得到了9种不同的Scale(不考虑太特殊的比例)。

深度学习基础之 - 行人检测SSD

    不同的Aspect Ratio & Scale 对预测目标进行覆盖,对于每一个feature map来讲,每个Grid Cell对应多个 Predict Boxes,我们假设为K(对应上面K=9,3种尺度*3种宽高比),所有中心落在该Grid的目标,都由该Grid进行回归Predict

    So 我们需要预测的结果就是:这K个Box每个对应的 分类(概率,C种)和 相对默认Rect的偏移(Offset,4个):

    Fature Map Grid  =>  (C+4)*K

    对于一张 m*n 大小的 Feature Map,能够得到 m*n *  (C+4)*K个输出结果(SSD 中默认使用了 6 个 default boxes)。


3. 各司其责 - Ground Truth与训练样本采集

    3.1 Ground Truth 映射

          这是与YOLO类似的方法,通过将Ground Truth映射到对应的Grid(参考下图),得到与之最接近的一个Default Box(K个选一个):

          我们得到了该目标在对应 Feature Map的Location,以及对应Box的偏移(Offset)

          下图最后一幅即是我们得到的输出结果信息。每一个位代表一个信息(1-20表示20种Class每种类别的Score,Last4 表示当前Rect偏移),是端到端训练的依据。

深度学习基础之 - 行人检测SSD

    3.2 加权的目标函数

          确定了端到端的对应,我们再来看目标函数。

          有个问题要明确:对于 每个 ground truth box,有可能有多个 default box与其相匹配(根据 IOU>0.5 )。

                 PS:不熟悉IOU者请自行补充知识。

          总的目标损失函数(objective loss function)是由 分类误差(confidence loss)定位误差( localization loss)加权求和得到:

深度学习基础之 - 行人检测SSD

         有几个点要说明:

          1)L(conf)为分类误差,采用多分类Softmax实现;

               “c” for Ground Truth Type。

          2)L(loc)为回归定位误差(Rect对应的Offset),类似Fast R-CNN 中 Smooth L1 Loss;

               “l”  for predict &  “g” for Ground Truth。

          3)权值α作为两个误差的均衡系数,并没有完全解决分类与定位的问题,还是与YOLO一致;

          4)N 即是上面提到的与 ground truth相匹配的 default boxes 个数。

    3.3 负样本选取

         训练过程中副样本的选取是个技术活,针对Ground Truth的预测结果中,有许多Box是与Ground Truth不match的,通常可以选择这些Box作为副样本。

         实际上 负样本的数量要远远多于正样本,容易造成样本比例比均衡,导致训练时难以收敛。针对这个问题,通常将每一个物体位置上对应的负样本进行排序,

   只保留最前面的一部分,根据经验值,负样本、正样本的配比通常在 3:1


4. 奇技淫巧 - Data Augmentation(数据增广)

    数据增广 是对训练数据进行某些自定义加工,以提高网络对数据的适应能力,特别是在数据不足的时候,可以借此来避免过拟合的问题。

    通常的数据增广的做法是对样本 添加噪声、旋转拉伸、光照明暗、色度处理等。

    本例中的做法是对每一张训练图像,随机的进行如下几种选择:

a)使用原始的图像;

b)采样一个 patch,与物体之间最小的 jaccard overlap 为:0.1,0.3,0.5,0.7 与 0.9

c)随机采样一个 patch

            采样的 patch 占原始图像大小范围[0.1,1],aspect ratio范围是[0.5,2]。

            当 groundtruth box 的 中心(center)在采样的 patch 中时,保留重叠部分。

            在这些采样步骤之后,每一个采样的 patch 被 resize 到固定的大小,并且以 0.5 的概率随机的 水平翻转(horizontally flipped)

     通过数据增广,本文将 mAP 从 65.4% 提升到了 72.1%,提升了 6.7%。


5. 事实胜于雄辩 - 实验效果

    给出性能参考:

深度学习基础之 - 行人检测SSD


下面是根据caffe生成的网络图,可以作为参考,重点看从 conv7_2 到 conv7_2_mbox_loc 和 conv7_2_mbox_conf

完整的网络图也可以从下面下载:

http://download.csdn.net/detail/linolzhang/9800328

深度学习基础之 - 行人检测SSD

三. 训练自定义数据集

       训练时需要准备以下数据:

1)demo中预训练好的VGGnet model, VGG_ILSVRC_16_layers_fc_reduced.caffemodel

    在 $CAFFE_ROOT/models/VGGNet 下。

2)建立原始数据集

     a)按照 VOC格式, 采用 labelImage 进行标注; 【Github

     b)在 data/VOCdevkit 目录下创建 自己的目录 zz_test,存放上面的标注数据;

          注:需要保留 Annotations(标注) 、ImageSets(图像集合) JPEGImages(图片)三个文件夹。

          ImageSets下面只需要 Main文件夹,存放后面训练要用到的 trainval.txt 和 test.txt。

     c)在 examples 目录下创建 zz_test 目录,存放指向生成的 lmdb 数据的软链接;

     d)在 data 目录下创建 自己的目录 zz_test,存放数据转换命令;

         将 data/VOC0712 下的 create_list.sh, create_data.sh, labelmap_voc.prototxt 这三个文件copy到 zz_test 目录下,重命名为:

         create_list_zz.sh,create_data_zz.sh, labelmap_zz.prototxt

     e)对上面三个文件进行修改;

         将 create_list_zz.sh 里的 for name in VOC2007 VOC2012 修改为  for name in zz_test,

         修改 create_data_zz.sh

    dataset_name="zz_test"    mapfile="$root_dir/data/$dataset_name/labelmap_zz.prototxt"

         修改 labelmap_zz.prototxt,假设只检测车和人。

    item {      name: "none_of_the_above"      label: 0      display_name: "background"    }    item {      name: "car"      label: 1      display_name: "car"    }    item {      name: "person"      label: 2      display_name: "person"    }
     e)执行创建命令;
    ./data/zz_test/create_list_zz.sh  # 对应生成3个文件 trainval.txt test.txt 和 test_name_size.txt    ./data/zz_test/create_data_zz.sh
     到对应文件夹下(examples/zz_test)查看文件是否生成。

3)训练脚本ssd_pascal.py

     在 $CAFFE_ROOT/examples/SSD 下,可以copy一份,重命名为 ssd_pascal_zz.py,有几个地方要修改:

     a) train_data和test_data修改成指向自己的数据集LMDB;

   train_data = "examples/zz_test/zz_test_trainval_lmdb"

            test_data = "examples/zz_test/zz_test_test_lmdb"

     b)修改 name_size_file 和 label_map_file 的路径;

          name_size_file = "data/zz_test/test_name_size.txt"
          label_map_file = "data/zz_test/labelmap_zz.prototxt"

     c)修改 num_classes(标签数量+1) 和 num_test_image(测试数据个数);

     d)修改 batch_size 为自己的 16,根据自己的GPU性能;

4)执行训练命令

     python examples/ssd/ssd_pascal_zz.py


系统安装参考:系统配置