目标检测算法上手实战
从广义上说,计算机视觉就是“赋予机器自然视觉能力”的学科。计算机视觉与人工智能有密切联系,但也有本质的不同。人工智能更强调推理和决策,但至少计算机视觉目前还主要停留在图像信息表达和物体识别阶段。计算机视觉的研究内容,大体可以分为物体视觉(object vision)和空间视觉(spatial vision)二大部分. 物体视觉在于对物体进行精细分类和鉴别,而空间视觉在于确定物体的位置和形状,为“动作(action)” 服务。
基于学习的视觉,是指以机器学习为主要技术手段的计算机视觉研究。基于学习的视觉研究,大体上可分为二个阶段:本世纪初的以流形学习( manifold Learning)为代表的子空间法( subspace method)和目前以深度神经网络和深度学习(deep neural networks and deep learning)为代表的视觉方法。深度学习( LeCun et al.2015)的成功,主要得益于数据积累和计算能力的提高以及一些创新设计:relu[1]、dropout[2]等。深度学习在静态图像物体识别方面已经成熟,这也是为什么在ImageNet上的物体分类竞赛已不再举行的缘故。
本次主要实战上手三个基础的目标检测网络算法:ssd-keras、yolo、faster-rcnn-tf。
一. 写在前面:先简单列出一些基本网络结构、网络模型与网络框架。
1. 基本网络结构:VGG NET[*], ResNet系列[*], Alexnet, ZFNet(DeconvNet思想)等。
2. 网络框架:tensorflow[*], affe, pytorch, keras[*]等。
3. 网络模型:one-stage[3]:SSD[*](基于VGG或Resnet), Retinanet(基于Resnet的FPN), Yolo[*]系列(darknet19、darknet53等); two-stage[3]:Rcnn[*]系列。
二.实战
1. SSD-keras[4]实战:
实现ssd-keras实时目标检测算法,并收集了十张图片作为小测试集测试网络鲁棒性。效果一般。ssd算法是继faster-rcnn与yolo之后的又一力作。来自UNC团队2016年发表在ECCV上。SSD最大的特点就是在较高的准确率下实现较好的检测准确度。并分为两种模型:SSD300(300*300输入图片) SSD500(512*512输入图片)。当然输入图片的尺寸越大,往往会得到更好的检测准确率,但同时也带来显存开销过大与设备性能要求较高等问题。在实际的上手操作中,测试效果一般。因为是直接在github上clone -recursive下来,并按照说明进行配置运行。而且还没有整理好自己的数据集,故也就不需要训练和验证并fine-tine超参数等一系列操作。同时也没有什么好的想法去在SSD基础卷积网络结构上做改进优化的tricks和结合更实际的运用场景迁移。所以笔者这次只是展现一些运行实战结果。因为训练遇到问题故用的是在voc07+12上SSD300训练好的模型。并用了下voc2007测试集简单跑了下结果。修改路径函数实现了几张本地图片的检测。中间遇到的麻烦是因为笔者用的显卡是GTX1060,只有6G显存,当时训练报错out of memory也是很郁闷。尝试简单改小batch_size再次尝试训练还是out of memory于是就放弃了训练。而且,另外用ssd500测试的时候也出样同种情况。当然git主不只提供了基于VOC的训练模型,同时也提供COCO与ILSVRC的预训练模型。这主要根据自己的真实需求选择不同的训练模型,类别数依次递增。
载入voc07+12plus与voc07+12的pre-training模型:
载入本地图片:
部分测试结果:
从上图可以看出在右图有误识别,可能是因为ssd采取从多个尺度特征图产生多个尺度的预测与通过宽高比来明确地分离预测的方式实现高精度检测的方法导致的。240000的训练量让ssd300有个更高的检测精度。
两种训练模型均没有识别出右侧的sheep。
2. Yolo[5]实战
下面进行yolo的实现,yolo是目前检测方面速度最快的算法之一。直接使用的官方yolo-darknet19。配置比较简单,修改makefile文件令opencv=1 GPU=1 cuda=1。运行cfg文件实现摄像头实时检测与视频检测。另外,官方在今天放出了更新yolov3,号称在精度与速度都有了一定提升,并提出了larger的网络darknet53.
在yolo的护城河慢慢被Retinanet侵蚀的时候,虽然v3没有带人较大突破,笔者认为这篇更新也是无奈之举吧。当然在损失部分精度的前提下,yolo系列还是最快的目标检测方法之一。尤其对于输入尺寸较低的情况。下图是yolov3的表现:
使用的pre-training的 yolo与tiny yolo模型:(左图yolo右图tiny-yolo)
实时调用摄像头:(摄像头略次,略朦胧)
表现:
另外实际上手yolov3,表现更好一点:
在视频上跑:
从上图可以看出,yolo的表现明显更好,tiny-yolo为了达到较高的识别速度从而导致识别精度较低。
3. tf-faster-rcnn[6]实战
使用的是训练于voc07+12(120000)的pre-training Resnet101模型。
表现:
从上图可以看出,two-stage(两步)的faster-rcnn算法在识别准确率上优于one-stage单步检测的ssd算法,对比图四中的结果上图明细那更好,可以识别出来sheep。
总结:一入检测深似海,基于学习的检测近几年可谓是发展迅速。学习永远在路上。
相关概念:
[1] RELU:常用relu代替sigmoid激活函数。原因: 第一,采用sigmoid等函数,算激活函数时(指数运算),计算量大,反向传播求误差梯度时,求导涉及除法,计算量相对大,而采用Relu激活函数,整个过程的计算量节省很多。第二,对于深层网络,sigmoid函数反向传播时,很容易就会出现梯度消失的情况(在sigmoid接近饱和区时,变换太缓慢,导数趋于0,这种情况会造成信息丢失),从而无法完成深层网络的训练。第三,Relu会使一部分神经元的输出为0,这样就造成了网络的稀疏性,并且减少了参数的相互依存关系,缓解了过拟合问题的发生。
[2] Dropout:通过一种-随机使网络某些隐含层节点的权重不工作(暂时不更新)的方式来提高神经网络性能。引用一段经典的解释:dropout可以阻止过拟合就像性别在生物进化中所起到的作用一样,可以避免环境改变时物种可能面临的灭亡。maxout与dropconnecrt都是其衍生版本。
[3] 目前目标检测的框架一般分为两种:基于候选区域的two-stage的检测框架(比如r-cnn系列),基于回归的one-stage的检测框架(yolo,ssd这种),two-stage的效果好,one-stage的快但是效果差一些。对于two-stage的检测器而言,通常分为两个步骤,第一个步骤即产生合适的候选区域,而这些候选区域经过筛选,一般控制一个比例(比如正负样本1:3),另外还通过hard negatiive mining(OHEM),控制难分样本占据的比例,以解决样本类别不均衡的问题。 对于one-stage的检测器来说,尽管可以采用同样的策略(OHEM)控制正负样本,但是还是有缺陷。
[4] ssd-keras: https://github.com/pierluigiferrari/ssd_keras
[5] Yolo: https://pjreddie.com/darknet
[6] tf-faster-rcnn: https://github.com/endernewton/tf-faster-rcnn
[*] *代表实战实现过程中有用到。
原创文章,作者:fendouai,如若转载,请注明出处:https://panchuang.net/2018/03/27/6b187cf034/