YOLOv5训练过程
YOLOv5训练过程
1. 数据格式转为YOLOv5需要的格式
YOLOv5
需要图像标注的数据格式
大家都知道,用于训练的图片都是有对应的标注信息的,主要来标注图片中的待识别物体(用边界框和类别表示)
在yolov5
中每一个图片对应的标注信息(边界框和类别)是存放在txt
文件中的,内容如下所示:
每一行5个值,含义依次是类别,真实边界框中心点x坐标,y坐标,宽,高
如果你的数据没有对应的标注文件,那么可以用标注工具进行标注:(可以用labelme
或者labelimg
,或者yolov5
提供的一个网址数据集制作)
如果你有标注文件,但是格式不对的画,比如你是json
格式,就需要自己手动编写脚本去转换,或者去网上找别人写好的脚本
这里以一个我的json
文件为例,如果有和这个json格式相同的,可能大多数都与这个不同,可以用下面代码进行转换:
{"info": {"image_name": "5191_1642654681678.jpg"}, "annotations": [{"bbox": [99, 517, 8, 18], "color": "other"}, {"bbox": [113, 519, 9, 17], "color": "other"}, {"bbox": [223, 531, 9, 29], "color": "other"}, {"bbox": [237, 555, 7, 14], "color": "other"}, {"bbox": [382, 564, 6, 12], "color": "red"}, {"bbox": [325, 484, 10, 28], "color": "other"}, {"bbox": [388, 480, 12, 22], "color": "other"}, {"bbox": [453, 481, 13, 29], "color": "other"}, {"bbox": [721, 555, 7, 17], "color": "other"}, {"bbox": [710, 555, 7, 15], "color": "other"}, {"bbox": [944, 533, 7, 18], "color": "red"}, {"bbox": [992, 533, 6, 18], "color": "red"}, {"bbox": [1261, 566, 6, 15], "color": "red"}, {"bbox": [801, 565, 6, 15], "color": "other"}, {"bbox": [792, 565, 7, 15], "color": "other"}, {"bbox": [772, 575, 8, 18], "color": "red"}, {"bbox": [389, 564, 6, 14], "color": "other"}]}
import os from PIL import Image import json import numpy as np import pandas as pd # 读取原始的json数据 ant_root_dir = "./traffic_light_data/annotations" # 存放json文件的文件夹 img_root_dir = "./traffic_light_data/images" # 存放图像的文件夹 output_root = "./traffic_light_data/ant_txt" # 存放输出结果的文件夹 json_list = os.listdir(ant_root_dir) json_dir_list = [os.path.join(ant_root_dir, json_dir) for json_dir in json_list] def cls_merger_bbox(cls, bbox, size): """ 这个函数需要你修改一下下面的类别映射,如果类别多的话,用下面的代码则很不好,可以自己改一下 """ # 转换颜色字符串为类别数字 if cls == 'red': cls = 0 elif cls == 'green': cls = 1 elif cls == 'yellow': cls = 2 else: cls = 3 # 转换bbox到0-1之间(除以图像宽和高) # 传入的bbox格式为(边界框中心x,中心y,宽,高) bbox [0], bbox[2] = bbox[0] / size[0], bbox[2] / size[0] bbox[1], bbox[3] = bbox[1] / size[1], bbox[3] / size[1] bbox.insert(0, cls) bbox = np.around(bbox, decimals=4) return bbox for i, json_dir in enumerate(json_dir_list): # 将json数据转为python字典格式,并读取标注信息 data = json.load(open(json_dir)) ant_list = data['annotations'] image_name = data['info']['image_name'] # 读取json文件对应的图像宽高 image_dir = os.path.join(img_root_dir, image_name) img = Image.open(image_dir) size = img.size # 用数组存取我们的标注信息 ant_yolo_np = np.zeros((len(ant_list), 5)) for i, ant in enumerate(ant_list): bbox = ant['bbox'] # list cls = ant['color'] # str # 将bbox缩放到0-1之间,并把cls转成对应的数字,将两者放在一个列表中 cls_bbox = cls_merger_bbox(cls, bbox, size) # 放入数组中 ant_yolo_np[i, :] = cls_bbox output = pd.DataFrame(ant_yolo_np) output.iloc[:, 0] = output.iloc[:, 0].astype(int) output_name = os.path.join(output_root, os.path.splitext(image_name)[0]+'.txt') # np.savetxt(output_name, ant_yolo_np, delimiter=' ', fmt='%.04f') output.to_csv(output_name, sep=' ', index=False, header=False) print("转换完毕")
import random import shutil """ 下面代码用于划分训练集和验证集 """ image_list = os.listdir(img_root_dir) output_list = os.listdir(output_root) index_list = random.sample(range(len(image_list)), 80) for i in index_list: image_name = os.path.join(img_root_dir, image_list[i]) txt_name = os.path.join(output_root, output_list[i]) shutil.move(image_name, './valid_image') shutil.move(txt_name, './valid_txt')
yolov5需要的数据在文件夹中的位置
你的图像和标注数据应该按照下面的形式放在文件夹中:
datasets
- traffic_light
- images
- train 存放训练图像
- val 存放验证集图像
- labels
- train 存放训练图像对应的标注txt文件
- val 同上
- images
然后将datasets
文件夹放到与你下载到的yolov5
项目的同级目录下
2.训练时必须修改的文件
创建自己的.yaml
文件,里面主要用来配置你的数据的信息,创建位置如下图所示:
里面的内容如下所示:
主要是把我们刚才放到datasets
下的数据集的路径还有训练集合验证集的路径填一下
修改models
文件夹下的yolov5*.yaml
文件,这个是你后面用于训练的模型配置文件(下图改的是yolov5x.yaml
),修改一下类别就行,其他的有能力也可以改:
将数据集配置好,并修改以上两个文件后就可以训练啦!
进入yolov5
项目文件夹,打开终端,输入下面命令:
python train.py --img 640 --batch 4 --epochs 30 --data ./data/traffic_light.yaml --weights ./weights/yolov5x.pt --cfg ./models/yolov5x.yaml
--img
:指的是输入网络的图像尺寸,有两个选择,640
和1280
--batch
:是1
个epoch
内,一次性喂入网络的数据中包含的图像个数,也就是卷积网络输入数据的第一个纬度(比如[4,3, 640,640]
);可以根据你的显存大小进行调整,显存越大可以设置更大,我的就6G,且网络模型很大,所以就设置小一些,不然会报显存不足或者其他错误--epochs
:训练网络的次数,一个epoch
有图像总数/batch
次更新模型的机会,一个epoch
进行完之后,说明你的训练数据集已将全部被网路训练一遍了,接下来网络会在验证集上验证目前的网络参数效果如何--data
:你的数据集对应的.yaml
文件--weights
:官方提供的预训练权重,weights
文件夹是我自己建的;下载地址:权重下载,进去之后找到Assets字样,如果你的网络比较卡,可以在百度网盘中下载:链接:https://pan.baidu.com/s/1CCmJmx4wCIJcmDahIye2Hw ,权重后面的6
表示的是输入图像尺寸为1280分辨率的图像,--cfg
也要改成相应的带6
的
提取码:iltr--cfg
:网络模型对应的文件
正常来说就可以训练了,如果有什么问题可以留言,看到了会回复
训练好之后,会提示你本次训练结果存放在run/train/exp*
文件夹下,在该文件夹下的weights
文件夹中可以看到本次训练的最好参数和最后一个epoch
训练完之后的权重
用你训练好的权重进行测试
执行下面代码:
python detect.py --weights ./runs/train/exp6/weights/best.pt --source ./test.jpg
执行完之后会提示你结果保存在***
中
- 下面是
--source
参数的值
--weights
:是你训练好的权重
3.其他
可视化时,更改边界框的粗细
修改学习率等超参数
data
文件夹下的hyps
文件夹中可以修改各种超参数,-low
好像是图像尺寸为640
时生效
4.训练结果记录
第一次: 本次用的图像尺寸是640,也就是说会把你输入的图像,进行缩放与随机裁剪等变化,最终用于训练的大小是640;直接用的最大的模型yolov5x,批次刚开始小一些30个,发现mAP一直在上升,因此可以加大批次数,增大一些学习率python train.py --img 640 --batch 4 --epochs 30 --data ./data/traffic_light.yaml --weights ./weights/yolov5x.pt --cfg ./models/yolov5x.yaml |
---|
![]() |
测试结果:python detect.py --weights ./runs/train/exp6/weights/best.pt --source ./test.jpg |
第二次: 与第一次相比,只是把初始学习率改为了0.03 ,然后训练次数增大到100 ;感觉mAP 还有上升空间,下面继续增加训练次数和学习率python train.py --img 640 --batch 4 --epochs 100 --data ./data/traffic_light.yaml --weights ./weights/yolov5x.pt --cfg ./models/yolov5x.yaml |
![]() |
python detect.py --weights ./runs/train/exp6/weights/best.pt --source ./detect # 将detect 文件夹下的图片都进行测试 |
下面是跑了300个epochs 的情况,感觉两次结果很接近 |
![]() |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!