后知后觉的我,终于明白了之前师哥说的简简单单的几句话。
由于用的公司电脑,没有GPU,没有办法搭建yolo环境,故没法训练模型。
借助服务器,获取所需的GPU。通过vs code连接服务器,剩余操作其实和本地差不多。(如果还是不懂,可以了解linux的基本结构)
搭环境!!简单几个字其实一直不太明白,知道看到上述虚拟环境的博文,才算有了一点点清晰的认识,每个算法模型都在自己的“生存条件”,即环境
在该环境下算法才能正常运行。那访问服务器,满足GPU的条件后,就开始正式搭建环境,而该服务器下,其实师姐师哥们已经搭建好了一个yolov5的虚拟环境
我只需要激活该环境,在该环境下运行yolov5算法模型即可!!!
而为了不破坏师姐师哥们的环境,我可以自己创建一个新的虚拟环境,在里面下载安装包,搭建环境也可以!!!
#服务器
由于电脑没有独立显卡,所以无法安装cuda等相关软件以搭建yolo环境,故需要利用公司的服务器。
- 服务器和电脑的差别
https://zhuanlan.zhihu.com/p/162938209
https://zhuanlan.zhihu.com/p/166335427
从用途来看;服务器是主机通过安装各种程序,长期稳定接受互联网访问,提供各式各样服务的工具,长期、稳定、开放是它显著的特点。
从安装系统来看;服务器有着专门的系统,比如Windows系统有Windows2003/2008/2012/2016/2019各种版本,Linux系统也有Ubuntu、centos、redhat等版本,还有专门用来虚拟化的VMware、Virutozzo等,这些系统强化了主机作为服务器的性能,能够更快更稳定运行,节约系统资源。
- 如何通过vs code连接服务器
从vs code连接服务器的教程如下:
https://jingyan.baidu.com/article/ca41422ff94e1c5faf99ed7e.html
其中有一步比较疑惑,即输入ssh连接命令接口,格式为ssh user@hostname -p port,对应配置是
可以通过两种方式方式连接:
- ssh user@hostname -p port
- ssh 别名
连接成功后,直接选择第一个配置,成功连接后,输入密码即可。
- 连接服务器以后如何使用
(1)了解linux系统的基础结构
https://www.cnblogs.com/zx125/p/11557483.html
补充知识点:
①root账户和name账户
root用户是系统中唯一的超级管理员,它具有等同于操作系统的权限。一些需要root权限的应用,譬如广告阻挡,是需要root权限的。
root比windows的系统管理员的能力更大,足以把整个系统的大部分文件删掉,导致系统完全毁坏,不能再次使用。用root进行不当的操作是相当危险的,轻微的可以死机,严重的甚至不能开机。
在Unix、Linux及Android中,除非确实需要,一般情况下都不推荐使用root,最好单独建立一个普通的用户,作为日常之用。
~是什么?
其实就是根目录下的个人文件夹
如果以root账号登陆 ,~ 是 /root/
如果以 name 登陆 ,~ 是 /home/name/
可知对应的是/home/name/data/lbb 其中name是个人文件夹,是一个用户
②镜像(Mirroring)
镜像是一种文件存储形式,是冗余的一种类型,一个磁盘上的数据在另一个磁盘上存在一个完全相同的副本即为镜像。
(2)了解conda的指令
https://www.jianshu.com/p/f0602213f400
(3)连接服务以后如何操作?
①成功连接
②点开文件夹,新建py文件,编写代码
③输入命令 nvidia-smi 查看英伟达显卡信息以及显卡驱动和cuda信息
④如何将本地的文件上传到服务器中
不用复杂的代码,直接拖拽就行
#搭建yolo的环境
明白服务器为何物后,我们需要新建虚拟环境yolov5,在其中配置好yolov5环境需要的包
师姐已经在服务器中把环境搭好了,所以我就省事了,只需要将她搭建好的环境复制到我的虚拟环境中
搭建yolo环境,明白何为搭建环境和虚拟环境
虚拟环境:https://www.cnblogs.com/yuehouse/p/10239195.html
了解conda,在虚拟环境中运行
由于通过了服务器,故需要掌握虚拟环境的使用。
使用conda创建虚拟环境:https://blog.csdn.net/qq_45154565/article/details/109326095
用到的指令:
查看虚拟环境:conda info --envs
删除虚拟环境:conda remove -n env --all (env为虚拟环境的名字)
复制虚拟环境:conda create -n env2 --clone env1 (env1是要复制的环境,env2是创建的环境)
查看复制后的虚拟环境安装包:conda list
对比虚拟环境安装包和requirement.txt的内容,看是否需要更新或添加
ps:复制yolov5的环境至lbb虚拟环境中,检查lbb虚拟环境是否配置完整,然后开始用正式训练
#正题:用yolov5训练自己的数据集
以下三个链接是同一个博主,可以快速了解全过程,并且非常详细
https://blog.csdn.net/CSDN1621564706/article/details/115295208?spm=1001.2014.3001.5501 (搭建yolo环境)
https://blog.csdn.net/CSDN1621564706/article/details/114152179?spm=1001.2014.3001.5501
https://blog.csdn.net/CSDN1621564706/article/details/115311347?spm=1001.2014.3001.550
以下三个链接是觉得非常完整,可以相互对比看的内容,我的代码也是参考以下三个链接中的。
https://blog.csdn.net/weixin_48994268/article/details/115282688
https://blog.csdn.net/a_cheng_/article/details/111401500
https://blog.csdn.net/qq_36756866/article/details/109111065?spm=1001.2014.3001.5501
- 制作数据集
coco文件夹是数据集制作,yolov5是源代码,接下来讲述如何制作数据集
在coco下新建images和labels两个文件夹,分别放置图片和标注文件
然后同级目录下新建两个py文件
import os
import random
trainval_percent = 0.1
train_percent = 0.9
xmlfilepath = 'coco/images'
txtsavepath = 'coco/ImageSets'
total_xml = os.listdir(xmlfilepath)
num = len(total_xml)
list = range(num)
tv = int(num * trainval_percent)
tr = int(tv * train_percent)
trainval = random.sample(list, tv) #从所有list中返回tv个数量的项目
train = random.sample(trainval, tr)
if not os.path.exists('coco/ImageSets/'):
os.makedirs('coco/ImageSets/')
ftrainval = open('coco/ImageSets/trainval.txt', 'w')
ftest = open('coco/ImageSets/test.txt', 'w')
ftrain = open('coco/ImageSets/train.txt', 'w')
fval = open('coco/ImageSets/val.txt', 'w')
for i in list:
name = total_xml[i][:-4] + '\n'
if i in trainval:
ftrainval.write(name)
if i in train:
ftest.write(name)
else:
fval.write(name)
else:
ftrain.write(name)
ftrainval.close()
ftrain.close()
fval.close()
ftest.close()
该代码会生成以下文件夹
另一个py文件
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
sets = ['train', 'test','val']
classes = ['person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light',
'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow',
'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee',
'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard',
'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',
'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch',
'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone',
'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear',
'hair drier', 'toothbrush']
def convert(size, box):
dw = 1. / size[0]
dh = 1. / size[1]
x = (box[0] + box[1]) / 2.0
y = (box[2] + box[3]) / 2.0
w = box[1] - box[0]
h = box[3] - box[2]
x = x * dw
w = w * dw
y = y * dh
h = h * dh
return (x, y, w, h)
#若目前标注文件已经是txt,不是xml,可直接讲以下两处地方注释掉
#第一处代码
'''
def convert_annotation(image_id):
in_file = open('coco/all_annotations/%s.xml' % (image_id))
out_file = open('coco/all_labels/%s.txt' % (image_id), 'w')
tree = ET.parse(in_file)
root = tree.getroot()
size = root.find('size')
w = int(size.find('width').text)
h = int(size.find('height').text)
for obj in root.iter('object'):
difficult = obj.find('difficult').text
cls = obj.find('name').text
if cls not in classes or int(difficult) == 1:
continue
cls_id = classes.index(cls)
xmlbox = obj.find('bndbox')
b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
float(xmlbox.find('ymax').text))
bb = convert((w, h), b)
out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
'''
wd = getcwd()
print(wd)
for image_set in sets:
if not os.path.exists('coco/labels/'):
os.makedirs('coco/labels/')
image_ids = open('coco/ImageSets/%s.txt' % (image_set)).read().strip().split()
list_file = open('coco/%s.txt' % (image_set), 'w')
for image_id in image_ids:
list_file.write('/home/cv/data/lbb/coco/images/%s.jpg\n' % (image_id))
#convert_annotation(image_id) 第二处注释代码
list_file.close()
该代码会生成以下文件(没有 .cache文件,这两个文件是后来生成的)
此时数据集变成如下所示(没有 .cache文件,这两个文件是后来生成的)
到此为止,数据集制作完毕,在这里强调一点:检查一下train.txt里的图片路径是否是绝对路径,这样不易出错。
- 训练数据集
训练数据集的操作跟以上分享的三个网址保持一致。
修改data里的yaml文件,models的种类数量,train.py的对应参数
需要注意的点:提前下载好yolov5s.pt放置在weights的文件夹下,缩短训练时长(下载地址以上分享的三个网址中有)
然后输入指令:python mytest.py --img 640 --batch 12 --epochs 100 --data data/mytest.yaml --cfg models/yolov5s.yaml --weights weights/yolov5s.pt
- 测试detect.py
训练完以后可以看到在runs/train/exp/weights下生成了训练好的权重文件best.pt和last.pt,接着我们用训练好的权重文件进行测试,打开detect.py文件,修改对应两个变量(操作跟以上分享的三个网址保持一致)
输入指令:python detect.py --weights runs/train/exp3/weights/best.pt --source data/images/ --device 0 --save-txt
需要注意的点:测试的图片不要和训练图片重复
- 查看结果
结果图片会在run/detect下的exp文件夹中生成
#在该过程中的遇到的小问题
(1)代码出现红色波浪线:语法错误(不小心空格)或代码不严谨,一般很难检查出来,我都是重新复制粘贴
(2)正式训练数据集之前,需要先制作自己的数据集,先对数据进行分类工作。
(3)yolov5的代码放在跟数据集同级目录下
注意:修改yolov5代码的data下的文件时,路径用绝对路径,以防出错,制作数据集时,代码里的路径也最好是绝对路径
(4)可以先下载权重模型,放置weights文件夹下,减少训练时长
(5)用指令执行train.py文件
python mytest.py --img 640 --batch 12 --epochs 100 --data data/mytest.yaml --cfg models/yolov5s.yaml --weights weights/yolov5s.pt
(6)在运行过程中出现问题,于是pip install wandb
下载后又出现问题,如下:
输入:3。
(7)测试时不要用训练的图片
(8)用该地址下载的工具解析coco数据集:
https://blog.csdn.net/flyfish1986/article/details/115485209