【我的第一个目标检测课题—建筑材料识别计数系统思考与总结】1、课

2021-01-08  本文已影响0人  2016年的夏天

2020.12.28晚记


写在前面

今天验收完图像处理课程的结课课题——建筑材料识别课题了。晚上决定趁热打铁,记录一下完成这次课题的全过程,还有一点自己的收获和感悟吧。自己也想要好好地对自己的这次完成情况做一次梳理。这篇博客算是一个验收后的回顾与总结,也算是提前为正式写课题报告拟个提纲,或者说,把做过的事情,总结的经验都先归纳起来,到时候方便写报告。当然,如果能对同样刚刚入门目标检测的朋友能有所帮助的话,那就更好了。

其实这也是我们专业的一个比赛,应用越新的网络越能够在保证高精度的情况下获得更高速度的检测能力。比如周围的同学很多使用的其实都是YOLOv5的目标检测算法。也许是觉得大家都选择一样的网络,那么所有的竞争点都在调整参数上了,还有一点是自己觉得这一次的比赛得不得奖并不是最重要的,学习目标检测算法(毕竟这学期才接触机器学习),学习训练网络,理解其算法背后的理论和意义才是最重要的。所以最终我们组并没有选择YOLOv5,而是选择了2017年年底提出的拥有经典one-stage检测模型和高检测精度,但是检测速度较慢的Retinanet目标检测算法。Retinanet其实不是我们原来决定的最终拿去验收的算法,而是我们选定的入门目标检测的算法。在Retinanet之前其实也有很多目标检测算法,one-stage的,two-stage的,之后也有很多新的优秀的目标检测算法,为什么选择Retinanet作为入门学习的算法,将在下面具体论述。那为什么最后还是拿运行速度并不够快的Retinanet算法去验收了呢?这其实比较意外。我们在了解并实现Retinanet之后,也发现了其运行速度慢的问题,于是去寻找提升速度的改进方案。最后看到了一张性能对比图,发现Efficiendet的运行速度会快得多而且检测精度也很高。最重要的是,Efficiendet其实是以Retinanet的结构为baseline对其特征提取部分和特征加强部分进行进一步优化的网络,所以基本结构非常相似。但是当我们具体实现之后,确实发现这个网络loss很小,检测精度很高,可惜的是,在我的电脑上跑的预测速度是Retinanet的几乎三倍。所以最后还是把训练得比较好的Retinanet拿去验收了。

这里有一点需要提一下。作为仅上过几节机器学习的介绍课,仅仅用CNN做过手写数字识别的入门小白来说,对于复杂的目标检测网络的入门,找到一个好的领路人特别重要。幸运的是,当前人工智能算法的研究也是实火,CSDN及很多平台都有非常好的入门资料以及算法实现的介绍,可以说,对于机器学习的入门小白来说,领路人有千千万。而对于我,我是跟着一个博主[Bubbliiiing](https://blog.csdn.net/weixin_44791964/article/list/1)来学习的。这个博主会发详细的算法实现介绍,并且在B站上传了对应网络实现的博客讲解视频(B站也是同名),有博客还有视频讲解,还有算法实现的代码和预训练权重都可以在博主提供的github及百度网盘链接下载到。我在此次课题的学习过程中,一共跟着博主学习并实现了Retinanet、Efficiendet、YOLOv4这三个网络的Keras实现。此外,自己还额外实现了Yolov5(跟着CSDN上面的大神们走的)。上面提到的博主一般会对一个算法提供Keras、TensorFlow以及PyTorch三个实现版本,有助于我们比较学习。而且,这个博主写的代码对应工程文件的架构都差不多,在实现一个网络之后,很快也就知道了怎么实现另一个网络(这里指的是理解代码,完成训练及预测的步骤,并不是自己编写出代码啦)还有,我这次的学习记录中也用到了该博主博客中部分的图片。
提前预警一下,这篇博客不是课题报告而是学习记录,所以可能会有很多啰嗦的大白话记录自己的感受和思考。这一过程确实做了很多事情,不管是在具体的代码上还是理论的理解学习上,所以应该也会分集来写。此外,自己不是以比赛的思路来做的(直接选择最新的效能最好的算法来训练数据),而是以学习目标检测的思路来完成这个课题的,所以会循序渐进来介绍自己学习的网络。内容包括网络结构理解到具体程序部分(自己同时也在学习Python),并且涉及到很多基础内容。
还有,我也是刚刚入门,如果文中有哪里描述不当的,也希望各路大侠能多多指教!当然有朋友按照我的步骤走出现问题的,欢迎大家来找我一起交流啊~~

好了,说了这么多,终于可以开始进入正题。


一、课题介绍

1、背景说明

建筑工地使用的建筑材料,如条状钢筋、钢筋圈一般堆放于露天的码垛,以往需要人工点数估计库存情况,并根据每日用量估计及时补充库存。人工盘点库存的方式费工费力、劳动强度大、效率低。基于上述原因,拟采用信息化技术代替人工,实现自动估计建筑材料数量的目的。

2、任务

主办方将提供训练模型的图片数据集,该数据集由固定的监控摄像头在建筑工地现场拍摄,数据集中主要包含钢筋圈,钢筋条及砌体等三种建筑材料,如下图所示:



钢筋条
钢筋圈
砌体

参赛团队需要设计深度学习模型,通过上述数据的训练使模型能够正确识别钢筋条,钢筋圈及砌体三种建筑材料,并对图片中出现的材料个数进行计数,其中钢筋圈和砌体的计数单位均为个,而钢筋条的计数单位为捆。

3、数据集说明

训练图像集包含钢筋条、钢筋圈及砌体等建筑材料,每种提供500幅的经过预处理的实拍图像(场地摄像头位置没有变化,建筑材料摆放在不同位置拍摄的代表性图像),共1500副图像供各参赛队研究使用,可以使用OpenCV、MATLAB或其他实验环境进行研究,其groundtruth文件为shape groundtruth.txt。测试集包括三种建筑材料各200副图,比赛期间不提供给参赛队,只在测试时供各参赛队测试算法性能时使用。

实际情况:一共提供了884张图片,分为第一批和第二批。第二批图片的标签是我们可以直接输入网络训练的标签(含目标框的位置信息和类别信息),第一批的标签只有物体的数量及对应类别的信息,我们自己使用labelimg进行第一批图片目标框的标注,得到对应的.xml标签文件。

课题分析:该课题其实就是目标检测问题。先对图片中的存在目标进行定位和分类,然后对图片中的所有目标框进行计数,就得到了每张图片中物体的类别和数量。然后按照格式(我们验收要的文件格式)将检测结果(具体某张图片的类别及数量)放入一个txt文件。最后通过检测这个txt文件获得目标检测的AP值和Error rate。一开始第一批数据的标签如何利用,一直没想明白,在初期,它起到的作用仅仅是对照着检查自己标记的数量是否符合官方的认定(去询问了助教,助教提到了弱监督的问题,但是在网上查找了一下,都只有理论介绍,并没有具体的代码实现可以参照,于是该思路也就搁置了),而在后期,就有了一点其他的似乎可执行的想法,这一点放到后面来说。

利用labelimg进行目标框标注

2020.12.29下午记


二、环境配置

要进行深度学习网络的训练,不管是使用Tensorflow还是Keras还是Pytorch实现,很重要的一个环节就是环境配置,Python的开源库一直都在更新换代,所以很可能会出现版本不兼容的问题。这也就再次体现了跟着上面那个博主进行不同网络的实现学习的好处了,该博主每个网络的三个版本需要的库版本都是固定的,所以不需要在实现不同网络的时候更换环境,变动需要的包的版本。
在这次课题的完成过程中,我主要选择的是用Keras实现,而在YOLOv5的实现中,使用的是Pytorch(因为官方的实现版本只有Pytorch的)。为什么选择Keras呢?理由很简单,因为它对入门的小白来说真的很友好,代码可读性很高,容易理解。在我完整地研究透彻Retinanet的keras代码之后,再去看Efficiendet的代码,很快就能看懂了。(一方面也是因为Efficiendet是以Retinanet为baseline进行优化和改进的吧,所以整体架构差不多,只是多了一些tricks来强化,这个也放后面再具体介绍)。

1、深度学习框架选择

配置环境前,首先要选好搭建网络的工具。用不同的工具,需要配备不同的包。那么,Keras,TensorFlow,Pytorch这三个热门的深度学习框架要选择哪个好?
Keras:Keras是一个高层神经网络API,Keras由纯Python编写而成并基TensorFlow、Theano以及CNTK后端。所以我们也可以直接使用TensorFlow调用Keras。它以其易用性和语法简单性而受到青睐,有助于快速开发。
以下是从Keras中文文档中的摘录:

Keras的设计原则:
用户友好:用户的使用体验始终是我们考虑的首要和中心内容。Keras遵循减少认知困难的最佳实践:Keras提供一致而简洁的API, 能够极大减少一般应用下用户的工作量,同时,Keras提供清晰和具有实践意义的bug反馈。
模块性:模型可理解为一个层的序列或数据的运算图,完全可配置的模块可以用最少的代价自由组合在一起。具体而言,网络层、损失函数、优化器、初始化策略、激活函数、正则化方法都是独立的模块,你可以使用它们来构建自己的模型。
易扩展性:添加新模块超级容易,只需要仿照现有的模块编写新的类或函数即可。创建新模块的便利性使得Keras更适合于先进的研究工作。
与Python协作:Keras没有单独的模型配置文件类型(作为对比,caffe有),模型由python代码描述,使其更紧凑和更易debug,并提供了扩展的便利性。

Keras中文文档

TensorFlow:作为Google开发维护的深度学习工具,TensorFlow应该是目前最为流行和使用率最高的深度学习计算框架了。它是用C ++ / Python编写的,提供Python,R、Java,Go和Java API。TensorFlow虽然很棒,但对于初学者来说并不友好,初学者用TensorFlow来搭建神经网络需要一个思维转变,总体来说TensorFlow没那么容易。
Pytorch:PyTorch是一款可以媲美于 TensorFlow 优秀的深度学习计算框架,但又相比于 TensorFlow 在语法上更具备灵活性。PyTorch原生于一款小众语言lua,而后基于python 版本后具备了强大的生命力。作为一款基于 python 的深度学习计算库,PyTorch提供了高于 numpy 的强大的张量计算能力和兼具灵活度和速度的深度学习研究功能。

Keras vs Tensorflow
Pytorch

基于以上的资料,我最终选择了Keras,Keras具备搭建神经网络各个零部件高度集成的API,对新手非常友好。也许Pytorch和TensorFlow程序运行的速度确实比Keras更快,但是基于入门学习的循序渐进来看,我最终还是选择了Keras。当然,等到通过Keras入门深度学习了,还是需要再去学习一下其他的工具的。

参考资料:
[深度学习框架的比较:Keras vs Tensorflow vs Pytorch]
https://my.oschina.net/u/4047540/blog/4481723
https://www.sohu.com/a/297453670_455817

2、相关包的安装

我们小组是一人在Ubuntu18.04上实验,一人在Windows进行实验,但是相关包的配置环节都差不多。整体搭配是Anaconda+Pycharm。Anaconda用来帮助进行不同环境的包管理,这一点我看很多博主说是非常好用的。不同的工程可能需要不同的环境,当然你也可以把所有需要的包放在同一个环境下,但这样就会显得很杂乱,而且有时候不同的程序需要的同一个包的版本还不同,所以最好还是选择Anaconda来进行环境管理,我们可以创建不同的环境,并根据需要在不同的环境中配备不同的包。而Pycharm也是一款非常好用而且友好的编程IDLE。

上面提到的博主的Keras实现需要的包及版本
keras实现代码对应的tensorflow版本为1.13.2,keras版本是2.1.5。
如果使用GPU进行训练的话,需要安装tensorflow-gpu==1.13.2
注意由于h5py库的更新,安装过程中会自动安装h5py=3.0.0以上的版本,会导致decode(“utf-8”)的错误!所以一定要在安装完tensorflow后利用命令装h5py=2.10.0!

(刚刚去看了这个链接才发现博主更新的这个问题,之前没看博客就去直接安装对应版本的包了,后来去验收的机子上配置环境的时候一直出现这个错误,还是查了好久最后在贴吧找到的答案......)
安装包的话,可以直接在Pycharm中的setting处在指定环境下安装,也可以打开cmd执行语句:

conda  activate +环境名
pip install +包名称==对应版本号 或 conda install + 包名称==对应版本号

(语句后面还可以指定镜像源进行下载,一般使用镜像源下载会快一点点吧,但是网络经常断连,我们去给测试的机子配置环境的时候整整装了一个晚上,就是因为网络太差,一直安装不上包......)

3、GPU的配置

这里分享一下最开始无知的我做了什么傻事吧......之前就有看到一些博客说训练神经网络最好使用GPU,速度会比较快。但是!之前做手写数字识别的时候用CPU跑的速度还是可以的,所以,我也不想那么麻烦,一开始就没管。最关键的是,同一组的同学在Ubuntu上配置GPU的时候直接黑屏自动关机了,后来再开电脑就一直进不去Ubuntu,只好重装Ubuntu系统。吓得我...直接放弃在Ubuntu配置,当然,windows也不敢配置了...于是我就这么兴冲冲地在把需要的包配置好后,开始跟着博主的指导进行训练,但是速度是真的慢,我的电脑开了整整一天才训练十三轮...当然我一开始并没有在电脑设置不睡眠,非常期待地跑去睡觉然后非常期待地起床后,发现我在睡觉后电脑也睡了...而且在路途的运输过程中电脑合上的时候也没法进行训练。就这样断断续续地运行了十三轮(超过最开始的冻结某些参数的总轮数了),我终于放弃,停止程序,准备配置GPU。只是没想到,这个第十三轮的模型我一直都保留着,因为这比起之后我用GPU训练但是训练不到参数解冻后的模型,效果好太多!

那么为什么用GPU来训练网络速度会快呢?
在此之前,我只知道CPU,并不了解GPU,GPU是做什么的?

GPU(Graphics processing unit),中文全称图形处理器。
GPU(图形处理器)是图形系统结构的重要元件,是连接计算机和显示终端的纽带。一个光栅显示系统离不开图形处理器(GPU)。 应该说有显示系统就有图形处理器,但是早期的显卡只包含简单的存储器和帧缓冲区,它们实际上只起了一个图形的存储和传递作用,一切操作都必须由CPU来控制。这对于文本和一些简单的图形来说是足够的,但是当要处理复杂场景特别是一些真实感的三维场景,单靠这种系统是无法完成任务的。所以后来发展的显卡都有图形处理的功能。它不单单存储图形,而且能完成大部分图形功能,这样就大大减轻了CPU的负担,提高了显示能力和显示速度。
图形处理器可单独与专用电路板以及附属组件组成显卡,或单独一片芯片直接内嵌入到主板上,或者内置于主板的北桥芯片中,现在也有内置于CPU上组成SoC的。个人电脑领域中,在2007年,90%以上的新型台式机和笔记本电脑拥有嵌入式绘图芯片,但是在性能上往往低于不少独立显卡。

(摘自https://zhuanlan.zhihu.com/p/106669828
GPU非常适合并行计算,并且神经网络是高度并行的(神经网络又无数的卷积运算构成),而这就是为什么深度学习要使用它们。深度学习和神经网络的每个计算任务都是独立于其他计算的,任何计算都不依赖于任何其他计算的结果,可以采用高度并行的方式进行计算。而GPU相比于CPU拥有更多独立的大吞吐量计算通道,较少的控制单元使其不会受到计算以外的更多任务的干扰,拥有比CPU更纯粹的计算环境,所以深度学习和神经网络模型在GPU的加持下会更高效地完成计算任务。

接下来就是配置GPU环境的总过程了。
主要参考:https://blog.csdn.net/weixin_44791964/article/details/104702142
博主使用的是tensorflow-gpu=1.13.2,因此会用到cuda10.0,与cuda10.0对应的cudnn是7.4.1.5,这个组合博主也试验过了,绝对是可以用的。
还有一点注意的是,我查了一些其他的博客,很多博主都说不要用cuda10.1。
当然,要使用GPU,电脑要配备有独立显卡,可以通过

此电脑-->属性-->设备管理器-->显示适配器 进行查看

查看独立显卡

还可以通过英伟达控制面板查看独立显卡的具体信息


查看独立显卡信息

步骤如下:
(1)下载cuda及cudnn
(下载什么东西都最好下载到全英文的路径下,不是全英文容易出问题)

下载并解压缩包后得到
(2)打开cuda_10的exe文件进行安装 安装cuda

此处选择自定义


下面的做法跟博主博客里面讲的略有不同,如果全都勾选的话,就包含Visual Studio Integration,而一旦勾选这个,后面就会显示下载不成功。而且CSDN上很多博主也都说不需要下载Visual Studio Integration这一项。至于后面的Driver components和Other components,我并不了解他们的作用,以防万一还是下载了。这么做最后都挺顺利的。


博主的做法 把Visual Studio Integration去掉可以成功安装
(3)安装完后在C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0可以找到根目录。

把最开始下载的压缩包进行解压

解压后文件夹中的内容

把解压后的四个文件放到上述C盘的目录下


这样就OK了。使用这个方法,不需要像其他的博客里面说到的改变环境变量什么的,就直接可以运行了。安装完后,训练的时候默认会使用GPU进行训练。以下有几个方法可以证明GPU驱动程序安装完毕。
方法一:新建一个,py文件,运行如下代码:

 import tensorflow as tf
 a = tf.constant([1.2, 2.3, 3.6], shape=[3], name='a')
 b = tf.constant([1.2, 2.3, 3.6], shape=[3], name='b')
 c = a + b
 session = tf.Session(config=tf.ConfigProto(log_device_placement=True))
 print(session.run(c))

如果出现下面的结果,就说明上面的安装没有问题


测试GPU

方法二:运行train.py文件,在训练的时候
第一是查看执行窗是否出现GPA的相关信息,如下所示可以看到我的电脑显存是2G


第二还可以打开任务管理器,查看GPU的工作情况,如下图所示,GPU1一直有在工作中
训练时GPU正常工作
而平常不训练的时候,是下面这样的
不训练时的GPU

最最明显的是,如果使用GPU进行训练,会发现训练速度大大提升,基本上很快一个epoch就走完了,进度条会一直有变化。
不得不说,当我配置成功运行的时候,看到那快速变化的进度条,真的太激动了!!!
所以说还是要用于尝试呢!!

这里还得提醒大家,在用GPU进行训练的时候,电脑一定要插着电,训练网络实在是耗费电脑资源,最开始的时候我并不清楚,就没有插电,没过多久,电脑突然黑屏了!!之前我的电脑就出过一点小问题,我还以为是使用GPU导致了什么故障了,会不会windows被我跑崩了,我都准备做好最坏的打算再次去找惠普售后预约时间了...当时同一组的赵同学问是不是电脑没电了,我总觉得没那么简单,毕竟我就是看它的电量还很充足所以没一边充电一边运行的!!当时还在助教的办公室,办公室里也没有别的插座,最后我去了一楼的保安室试着接通电源。谢天谢地,还真只是因为没电了才黑屏,真是吓死我了!!

对于本机的GPU配置和相关包的安装其实已经梳理完了。但是后来我们在训练的时候,由于我的轻薄本显存只有2G,实在是太弱小了,而且训练的图片数量很多,分辨率也都很高,参数量太大,所以训练的batch size只能调个2或者4(对GPU来说,batch size设置为2的次方数有利于它运行),一到8就内存溢出了。我们的epoch分为两轮,第一轮冻结了某些参数,第二轮把之前冻结的参数解冻了参与训练,一到第二轮,即使是batch size=2的情况,投入全部的数据集(884张),也内存溢出了。而如果不参与解冻后的epoch,只取前面训练时保存的模型,效果还不如之前用CPU训练的第十三轮的数据。

因此,我们决定采用老师分享到群里的解决办法:薅一把Google的羊毛!羊毛可以免费薅,但是需要爬个好的梯子出去才薅得到。其实就是使用Google的Colabratory链接谷歌云盘,使用Google的服务器,享受免费且强大的16G显存在线进行训练。听起来真的很棒啊,我们决定试一试!

小记:
第一次写这么长的博文,
从下午三点写到晚上八点多了,
但是发现越写越有干劲,也不饿,
真是奇怪。
坚持看到这里的朋友们都是了不起的好汉hhh。

上一篇下一篇

猜你喜欢

热点阅读