首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)

缘由

2021年的暑假辅导学生参加首届长三角人工智能算法擂台赛。
初赛为基于AI开发平台ModelArts,使用Python语言编写代码,完成包括党徽、国徽、国旗、军礼、军徽、少先队徽、红领巾、团徽的党史图像检测挑战。

初赛小结

我们自行在网上找了1500张相关图片,并在ModelArts中开始标注,完成后用ModelArts内置的算法开始训练并打榜,有YOLOv3,v5以及Fast-RCNN。由于经费及每日打榜次数的限制,加上初赛时我们经验的不足,最终的成绩是0.52(满分为1,初高中分别排名,非官方参赛队不计入名次),幸好在我们组入围了决赛。

首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第1张图片

**PS1:**本以为训练集是不提供的,所以自行在网上找图片。后来官方提供了训练集,但此时不忍心丢弃已标注的图片,就在官方的训练集中挑选了300张,加之自行寻找的,共1800张进行训练的。

**PS2:**初赛的训练集中有一些图片是否需要标注给我们带来了很大的困扰:如黑白的、红色的、镂空的,卡通的党徽团徽队徽等等。标了担心对成绩有反作用(测试集不公开的),不标有担心测试集中有。

事后想想若我们对训练集精心挑选+标注一下,也许初赛的成绩会更好一些。

决赛赛题

主要考核点有交通信号灯识别、车道线检测、斑马线检测、限速标志识别、施工标志识别、障碍物检测等,其中交通信号灯、斑马线、限速标志检测算法需要基于AI开发平台ModelArts开发。

重点部分:
1、禁用内置YOLOv5
2、官方提供的数据集中有标志样例
3、官方明确表示,训练集和测试集中没有过分夸张的图片

因为决赛禁用内置YOLOv5,我们推测YOLOv5识别率相对会高一些,加之初赛我们组用了Fast-RCNN(费用较高,训练一次在100元左右),结果不甚理想,所以我们组决定尝试自行搭建本地YOLOv5的环境。

自行搭建本地YOLOv5的环境

Windows中安装深度学习环境pytorch+paddle(Anaconda+Pycharm)

在CSDN上找到了一篇8月底新发的搭建YOLOv5保姆级教程,https://blog.csdn.net/didiaopao/article/details/119787139。
参照教程,在一台系统为Server2012的服务器和一台WIN10的办公用机上同时搭建环境。由于这两台机器都没有显卡,所以跳过了安装显卡驱动的环节。安装好anaconda后,新建了pytorch和paddle的环境(都是基于python3.8的)。

__PS1:__事后找了一台有显卡(P106)的机器,不知为什么在安装pytorch环境时,选择清华源是显示报错,报错信息如下,大概意思是清华源上没有cuda11.1下pytorch的环境,无奈只能选择国外源。(但安装无显卡,仅仅是CPU的pytorch环境是可以选择清华源)
首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第2张图片
__PS2:__总结不推荐在Server2012上跑YOLOv5,若要用服务器跑,建议使用Server2019以上的版本。

在pycharm中新建工程,分别选择pytorch和paddle环境(CPU),参照教程里的验证代码,输出结果如下(安装成功)。
首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第3张图片

从Github下载YOLOv5程序+安装所需库

接下去,按如下教程(https://blog.csdn.net/didiaopao/article/details/119954291)从github上下载YOLOv5源码,解压后并在pycharm中以工程打开(选择pytorch环境)。在执行requestments文件的第一句语句 pip install -r requirements.txt后,发生如下错误。
首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第4张图片
首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第5张图片
打开test.py文件后,发现pycharm有如图错误提示,很明显是没有成功安装这两个库。
首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第6张图片

opencv_python库解决办法:

将opencv_python-4.5.1.18-cp38-cp38-win_amd64.whl复制到Anaconda中的pytorch环境的库安装目录(c:\Users\administrator.conda\envs\pytorch\Lib\site-package),打开Anaconda的命令提示符,激活pytorch环境,进入上述库安装目录,手动输入命令“pip install opencv_python-4.5.1.18-cp38-cp38-win_amd64.whl”,安装完成即可。

pycocotools库解决办法:

执行过pip install -r requirements.txt后,其实已安装了pycocotools库,但YOLOv5依旧说不满足所需,pycharm给出的报错信息是vc++,其实不需要安装相应的vc++。
参照以下方法即可解决:https://blog.csdn.net/Gao_qie/article/details/118391417

其实就是将高版本的库文件下载并解压后,直接复制替换原先安装的低版本的库文件。

这样就解决了opencv_python库和pycootools库不满足需求的问题。

XML转TXT:

接一下就可以跑训练了,但YOLOv5的数据集标签是TXT格式(矩形中心的坐标xy与wh的归一化值),若在ModelArts中标注后的格式为VOC的XML格式(如图),需要人工将XML的标签转换为TXT的格式,详细转换方法见链接https://blog.csdn.net/didiaopao/article/details/120022845
首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第7张图片
首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第8张图片

还需将数据集划分为训练集和验证集来进行YOLOv5模型的训练,一张图片的JPG文件名和标注TXT文件名必须一致。数据最好放在最外一级目录中,数据集的目录格式如下图所示。

首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第9张图片

配置自己的模型参数:

做好如上准备后,在正式跑YOLOv5之前还有一些准备工作。

第一、下载预训练权重文件
为了缩短网络的训练时间,并达到更好的精度,一般需加载预训练权重进行训练。而yolov5提供了几个预训练权重,可以对应不同的需求选择不同的版本的预训练权重。通过如下的图可以获得权重的名字和大小信息,可以预料的到,预训练权重越大,训练出来的精度就会相对来说越高,但是其检测的速度就会越慢。预训练权重可以通过这个网址 https://github.com/ultralytics/yolov5/releases 进行下载,如图,本文中以yolov5s.pt为预训练权重。
首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第10张图片
第二、修改数据配置文件
修改data目录下相应的yaml文件。找到data目录下的voc.yaml文件,将该文件复制一份,将复制的文件重命名,最好和项目相关,这样方便后面操作,这里我修改为csj52.yaml。
首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第11张图片
打开csj52.yaml文件修改其中的参数,首先将箭头1中的那一行代码注释掉,如果不注释则可能训练时候会报错;箭头2中需要将训练和测试的数据集的路径填上(绝对路径和相对路径都可以,绝对路径不可能出错);箭头3中需要检测的类别数,填写6,表明有6个类别;最后箭头4中填写需要识别的类别的名字(必须是英文,否则会乱码识别不出来)。
首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第12张图片
第三、修改模型配置文件
由于使用的是yolov5s.pt这个预训练权重,所以要使用models目录下的yolov5s.yaml文件中的相应参数(因为不同的预训练权重对应着不同的网络层数,所以用错预训练权重会报错)。同上修改data目录下的yaml文件一样,我们最好将yolov5s.yaml文件复制一份,然后将其重命名,我将其重命名为yolov5s_csj52.yaml。

首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第13张图片

打开yolov5s_csj52.yaml文件只需要修改如图中的nc后面的数字就好了,这里是识别六个类别。

首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第14张图片

其实下面两个参数depth_multiple和width_multiple就是模型的深度和层数的比例值,不同预训练模型的这两个值是不同的。
至此,相应的配置参数就修改好了。

跑YOLOv5训练:

找到train.py这个py文件,
首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第15张图片

然后找到主函数的入口,这里面有模型的主要参数。模型的主要参数解析如下所示。

if __name__ == '__main__':
"""
    opt模型主要参数解析:
    --weights:初始化的权重文件的路径地址
    --cfg:模型yaml文件的路径地址
    --data:数据yaml文件的路径地址
    --hyp:超参数文件路径地址
    --epochs:训练轮次
    --batch-size:喂入批次文件的多少
    --img-size:输入图片尺寸
    --rect:是否采用矩形训练,默认False
    --resume:接着打断训练上次的结果接着训练
    --nosave:不保存模型,默认False
    --notest:不进行test,默认False
    --noautoanchor:不自动调整anchor,默认False
    --evolve:是否进行超参数进化,默认False
    --bucket:谷歌云盘bucket,一般不会用到
    --cache-images:是否提前缓存图片到内存,以加快训练速度,默认False
    --image-weights:使用加权图像选择进行训练
    --device:训练的设备,cpu;0(表示一个gpu设备cuda:0);0,1,2,3(多个gpu设备)
    --multi-scale:是否进行多尺度训练,默认False
    --single-cls:数据集是否只有一个类别,默认False
    --adam:是否使用adam优化器
    --sync-bn:是否使用跨卡同步BN,在DDP模式使用
    --local_rank:DDP参数,请勿修改
    --workers:最大工作核心数
    --project:训练模型的保存位置
    --name:模型保存的目录名称
    --exist-ok:模型目录是否存在,不存在就创建
"""
    parser = argparse.ArgumentParser()
    parser.add_argument('--weights', type=str, default='yolov5s.pt', help='initial weights path')
    parser.add_argument('--cfg', type=str, default='', help='model.yaml path')
    parser.add_argument('--data', type=str, default='data/coco128.yaml', help='data.yaml path')
    parser.add_argument('--hyp', type=str, default='data/hyp.scratch.yaml', help='hyperparameters path')
    parser.add_argument('--epochs', type=int, default=300)
    parser.add_argument('--batch-size', type=int, default=16, help='total batch size for all GPUs')
    parser.add_argument('--img-size', nargs='+', type=int, default=[640, 640], help='[train, test] image sizes')
    parser.add_argument('--rect', action='store_true', help='rectangular training')
    parser.add_argument('--resume', nargs='?', const=True, default=False, help='resume most recent training')
    parser.add_argument('--nosave', action='store_true', help='only save final checkpoint')
    parser.add_argument('--notest', action='store_true', help='only test final epoch')
    parser.add_argument('--noautoanchor', action='store_true', help='disable autoanchor check')
    parser.add_argument('--evolve', action='store_true', help='evolve hyperparameters')
    parser.add_argument('--bucket', type=str, default='', help='gsutil bucket')
    parser.add_argument('--cache-images', action='store_true', help='cache images for faster training')
    parser.add_argument('--image-weights', action='store_true', help='use weighted image selection for training')
    parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
    parser.add_argument('--multi-scale', action='store_true', help='vary img-size +/- 50%%')
    parser.add_argument('--single-cls', action='store_true', help='train multi-class data as single-class')
    parser.add_argument('--adam', action='store_true', help='use torch.optim.Adam() optimizer')
    parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode')
    parser.add_argument('--local_rank', type=int, default=-1, help='DDP parameter, do not modify')
    parser.add_argument('--workers', type=int, default=8, help='maximum number of dataloader workers')
    parser.add_argument('--project', default='runs/train', help='save to project/name')
    parser.add_argument('--entity', default=None, help='W&B entity')
    parser.add_argument('--name', default='exp', help='save to project/name')
    parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
    parser.add_argument('--quad', action='store_true', help='quad dataloader')
    parser.add_argument('--linear-lr', action='store_true', help='linear LR')
    parser.add_argument('--label-smoothing', type=float, default=0.0, help='Label smoothing epsilon')
    parser.add_argument('--upload_dataset', action='store_true', help='Upload dataset as W&B artifact table')
    parser.add_argument('--bbox_interval', type=int, default=-1, help='Set bounding-box image logging interval for W&B')
    parser.add_argument('--save_period', type=int, default=-1, help='Log model after every "save_period" epoch')
    parser.add_argument('--artifact_alias', type=str, default="latest", help='version of dataset artifact to be used')
    opt = parser.parse_args()

训练自己的模型时需要修改如下几个参数。首先将weights权重yolov5s.pt的路径填写到对应的参数里面,然后将修好的models模型的yolov5s_csj52.yaml文件路径填写到相应的参数里面,最后将data数据的csj52.yaml文件路径填写到相对于的参数里面。这几个参数是必须要修改的参数。

    parser.add_argument('--weights', type=str, default='weights/yolov5s.pt', help='initial weights path')
    parser.add_argument('--cfg', type=str, default='models/yolov5s_csj52.yaml', help='model.yaml path')
    parser.add_argument('--data', type=str, default='data/csj52.yaml', help='data.yaml path')

还有几个参数需根据自己的需求来更改:

首先是模型的训练(迭代)轮次,这里默认是训练的300轮,但事实上150轮后,mAP值的变化是不大了,除非x6的预训练模型。

parser.add_argument('--epochs', type=int, default=100)

其次是输入图片的数量(与显存的大小有关)和工作的核心数,每台电脑的硬件配置不一样,所以需要根据电脑硬件性能来。
如出现如下报错信息,则是显存不够,需把batch-size和workers调小一些(默认都是4)。
在这里插入图片描述

parser.add_argument('--batch-size', type=int, default=4, help='total batch size for all GPUs')
parser.add_argument('--workers', type=int, default=4, help='maximum number of dataloader workers')

至此,就可以运行train.py函数训练自己的模型了。

推理测试:

等到数据训练好了以后,就会在主目录下产生一个run文件夹,在run/train/exp/weights目录下会产生两个权重文件,一个是最后一轮的权重文件,一个是最好的权重文件,就要利用这个最好的权重文件来做推理测试。除此以外还会产生一些验证文件的图片等一些文件。
首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第16张图片
打开主目录下的detect.py文件。
首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第17张图片
然后找到主函数的入口,这里面有模型的主要参数,解析如下所示。

if __name__ == '__main__':
"""
 --weights:权重的路径地址
 --source:测试数据,可以是图片/视频路径,也可以是'0'(电脑自带摄像头),也可以是rtsp等视频流
 --output:网络预测之后的图片/视频的保存路径
 --img-size:网络输入图片大小
 --conf-thres:置信度阈值
 --iou-thres:做nms的iou阈值
 --device:是用GPU还是CPU做推理
 --view-img:是否展示预测之后的图片/视频,默认False
 --save-txt:是否将预测的框坐标以txt文件形式保存,默认False
 --classes:设置只保留某一部分类别,形如0或者0 2 3
 --agnostic-nms:进行nms是否也去除不同类别之间的框,默认False
 --augment:推理的时候进行多尺度,翻转等操作(TTA)推理
 --update:如果为True,则对所有模型进行strip_optimizer操作,去除pt文件中的优化器等信息,默认为False
 --project:推理的结果保存在runs/detect目录下
 --name:结果保存的文件夹名称
"""
    parser = argparse.ArgumentParser()
    parser.add_argument('--weights', nargs='+', type=str, default='yolov5s.pt', help='model.pt path(s)')
    parser.add_argument('--source', type=str, default='data/images', help='source')  # file/folder, 0 for webcam
    parser.add_argument('--img-size', type=int, default=640, help='inference size (pixels)')
    parser.add_argument('--conf-thres', type=float, default=0.25, help='object confidence threshold')
    parser.add_argument('--iou-thres', type=float, default=0.45, help='IOU threshold for NMS')
    parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
    parser.add_argument('--view-img', action='store_true', help='display results')
    parser.add_argument('--save-txt', action='store_true', help='save results to *.txt')
    parser.add_argument('--save-conf', action='store_true', help='save confidences in --save-txt labels')
    parser.add_argument('--nosave', action='store_true', help='do not save images/videos')
    parser.add_argument('--classes', nargs='+', type=int, help='filter by class: --class 0, or --class 0 2 3')
    parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS')
    parser.add_argument('--augment', action='store_true', help='augmented inference')
    parser.add_argument('--update', action='store_true', help='update all models')
    parser.add_argument('--project', default='runs/detect', help='save results to project/name')
    parser.add_argument('--name', default='exp', help='save results to project/name')
    parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
    opt = parser.parse_args()

将刚刚训练好的最好的权重传入到推理函数中去。然后就可以对测试图像进行推理了。

parser.add_argument('--weights', nargs='+', type=str, default='runs/train/exp2/weights/best.pt', help='model.pt path(s)')

对图片进行测试推理,将如下参数修改成图片的路径,然后运行detect.py就可以进行测试了。

parser.add_argument('--source', type=str, default='VOCdevkit/yanzheng/', help='source')  # file/folder, 0 for webcam

首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第18张图片
推理测试结束以后,在run下面会生成一个detect目录,推理结果会保存在exp2目录下。如图所示。首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第19张图片
图片的推理结果如下所示。效果还是很不错的。
首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第20张图片

上传ModelArts打榜:

接下去需要将本地训练的YOLOv5模型上传至ModelArts中进行打榜。
现在需要解决的问题是:需要将哪些文件导入至ModelArts的模型中,导入时的文件目录结构是又怎样的,

我们查阅了华为ModelArts的官方说明文档,了解上传自己模型时需要的注意点。由于水平有限,实现弄得有点吃力。
后来我们想到了如下的方法:
1、先用ModelArts内置的YOLOv5算法训练一次,生成的模型文件在OBS桶中,我们将OBS桶中模型文件(一个目录)导出至本地,尝试寻找其中需要替换成我们本地训练的YOLOv5模型的文件。
2、通过对比后,发现有5个文件需要替换。
3、替换后,将模型文件(一个目录)从OBS桶中导入至ModelArts,再打榜,是不是就解决问题了?
尝试后,的确是这样,打榜成功了,如下图所示。
首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第21张图片

精益求精:

如上的方法,我们第一次的打榜成绩为:0.5958。事后用了YOLOv5的x+300轮的迭代,取得了我们打榜的最高分0.6771,排在高中组的第一名。
后来我们尝试了其他的一些算法,如内置的Fast-RCNN,结果不甚理想。
首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第22张图片
高手的确很多,都是深藏不漏,在临近截止时间前,有许多高分出现,绝大多数都是初中组的,真是惭愧啊。
最后我们的成绩依旧在0.6771,高中组第四,全体排名的第13名。
首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第23张图片
首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第24张图片
说明:SH-HI 表示高中组;SH-MID表示初中组;图片中的第9名sh-mid-019不是官方的参赛队,不计入排名。

9月25日我们组的三位同学,还参加了在线的答辩。无论结果是什么,更重要的是过程,我们在这次的比赛中真的学到了很多很多。首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第25张图片

最后附上我们的模型在ModelArts中在“部署上线”后的“在线服务”的测试截图。
首届长三角青少年人工智能擂台赛全记录(YOLOv5+Win10+Anaconda+Pycharm+ModelArts)_第26张图片

你可能感兴趣的:(人工智能,pycharm,深度学习)