当前位置:   article > 正文

YOLOv5训练个人数据集总结_yolov5训练总结

yolov5训练总结

已记录一下自己的代码在GPU服务器端跑的时候流程和遇到的问题以及解决方法。

需要具备部分基础知识。

声明

国际惯例,写在前面

-----------------------------------------------------------------------------------------------

声明:本文章仅供个人学习之用,由于作者能力有限,相关观点和信息仅供参考。

如有侵权请联系。

欢迎各位读者老爷提问和交流。

我们的目标是星辰大海!

1. 准备情况

因为公司原因,通知xshell和xftp没有版权,不让用了。如何解决远程登录到服务器上成为了第一个问题。

01. 通过vscode实现远程连接服务器

(1)安装remote插件。

安装 Remote Development插件,会自动安装这么多个。

 (2)连接到服务器

 

点击这里的加号,被水印挡住了,或者按按下shift+ctrl+p,输入Remote-SSH: Connect to Host。

输入你要远程访问的IP地址

 你可以每次都输入密码,或者自行配置

Host代表连接的名称(自定义)

HostName是服务器的地址

IdentityFile是免密登录需要的 是本地id_rsa文件的路径

User是登录服务器的用户名

Port是端口号

IdentitiesOnly也是免密登录值为yes 

 

02. 通过安装anaconda来安装虚拟环境

(1)下载anaconda

  1. # 切换root用户,输入密码
  2. su root
  3. # 进入root目录,安装脚本存放路径
  4. cd /root
  5. # 下载anaconda安装脚本(本教程采用清华源)
  6. wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2020.07-Linux-x86_64.sh
  7. # 安装anaconda
  8. bash Anaconda3-2020.07-Linux-x86_64.sh
  9. # Please, press ENTER to continue -> 回车继续
  10. # 阅读协议,同意按回车(跳过ctrl+c)
  11. # Do you accept the license terms? [yes|no] -> 同意协议输入yes回车
  12. # Anaconda3 will now be installed into this location -> 选择安装路径(本文安装/usr/local/anaconda3),等待安装
  13. # by running conda init? [yes|no] -> 是否添加系统环境,输入yes回车
  14. # 待安装结束
  15. # 刷新当前用户环境(激活环境)
  16. source ~/.bashrc
  17. #添加国内源
  18. conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
  19. conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
  20. conda config --set show_channel_urls yes
  21. ## 新建虚拟环境
  22. conda create -n python36 python=3.6.5
  23. # 删除虚拟环境
  24. conda remove -n python36 --all
  25. # 查看所有环境
  26. conda env list
  27. # 激活虚拟环境
  28. conda activate python36
  29. # 退出当前虚拟环境
  30. conda deactivate python36

一定要记得最后一句,刷新

(2)使用conda安装requirement.txt,pip报错

  1. $ git clone https://github.com/ultralytics/yolov5
  2. $ cd yolov5
  3. $ pip3 install -r requirements.txt
  4. while read requirement; do conda install --yes $requirement || pip install $requirement; done < requirements.txt

03.训练自己数据集过程

(1)自己的数据集有几类,要和yaml文件中对应起来,我这里使用的是yolov5s,2类

(2) 照抄一个yaml文件,修改一下,需要按照自己的数据类型具体修改。

在data路径下,新建一个自己的xxx.yaml

需要修改的东西非常少,就是训练集,测试集,测试类别,类别名称。

但是需要注意的是,train:后面有个空格,跟的是你的数据的路径,注意,这里知道文件夹,当时看csdn看到一个写到train.txt的我一度以为我有问题

 在这里我产生了问题,

我获取到的数据比较干净,在Annotations中是已经标注好的v5.txt格式 ,JPEGImages里面是原图片。

注意细节:

  1. ├── data
  2. │ ├── Annotations 进行 detection 任务时的标签文件,xml 形式,文件名与图片名一一对应
  3. │ ├── images 存放 .jpg 格式的图片文件
  4. │ ├── ImageSets 存放的是分类和检测的数据集分割文件,包含train.txt, val.txt,trainval.txt,test.txt
  5. │ ├── labels 存放label标注信息的txt文件,与图片一一对应
  6. ├── ImageSets(train,val,test建议按照811比例划分)
  7. │ ├── train.txt 写着用于训练的图片名称
  8. │ ├── val.txt 写着用于验证的图片名称
  9. │ ├── trainval.txt train与val的合集
  10. │ ├── test.txt 写着用于测试的图片名称

 

yolov5使用的是txt格式,每个图像对应一个txt文件,文件每一行为一个目标的信息,包括class,x_center,y_center,width,height格式。

格式如下:

那么问题来了。

很多朋友的数据都是标准的xml格式。

第一步,我们需要把xml转换成txt

xml2txt.py

  1. # -*- coding: utf-8 -*-
  2. import xml.etree.ElementTree as ET
  3. import pickle
  4. import os
  5. from os import listdir, getcwd
  6. from os.path import join
  7. #import shutil
  8. sets = ['train', 'test', 'val']
  9. #classes = ['1', '2', '3', '4', '5']
  10. '''
  11. classes = ['asamu', 'baishikele', 'baokuangli', 'aoliao', 'bingqilinniunai', 'chapai', 'fenda', 'guolicheng',
  12. 'haoliyou', 'heweidao', 'hongniu', 'hongniu2', 'hongshaoniurou', 'kafei', 'kaomo_gali', 'kaomo_jiaoyan',
  13. 'kaomo_shaokao', 'kaomo_xiangcon', 'kele', 'laotansuancai', 'liaomian', 'lingdukele', 'maidong', 'mangguoxiaolao',
  14. 'moliqingcha', 'niunai', 'qinningshui', 'quchenshixiangcao', 'rousongbing', 'suanlafen', 'tangdaren', 'wangzainiunai',
  15. 'weic', 'weitanai', 'weitaningmeng', 'wulongcha', 'xuebi', 'xuebi2', 'yingyangkuaixian', 'yuanqishui', 'xuebi-b', 'kebike',
  16. 'tangdaren3', 'chacui', 'heweidao2', 'youyanggudong', 'baishikele-2', 'heweidao3', 'yibao', 'kele-b', 'AD', 'jianjiao', 'yezhi',
  17. 'libaojian', 'nongfushanquan', 'weitanaiditang', 'ufo', 'zihaiguo', 'nfc', 'yitengyuan', 'xianglaniurou', 'gudasao', 'buding',
  18. 'ufo2', 'damaicha', 'chapai2', 'tangdaren2', 'suanlaniurou', 'bingtangxueli', 'weitaningmeng-bottle', 'liziyuan', 'yousuanru',
  19. 'rancha-1', 'rancha-2', 'wanglaoji', 'weitanai2', 'qingdaowangzi-1', 'qingdaowangzi-2', 'binghongcha', 'aerbeisi', 'lujikafei',
  20. 'kele-b-2', 'anmuxi', 'xianguolao', 'haitai', 'youlemei', 'weiweidounai', 'jindian', '3jia2', 'meiniye', 'rusuanjunqishui',
  21. 'taipingshuda', 'yida', 'haochidian', 'wuhounaicha', 'baicha', 'lingdukele-b', 'jianlibao', 'lujiaoxiang', '3+2-2',
  22. 'luxiangniurou', 'dongpeng', 'dongpeng-b', 'xianxiayuban', 'niudufen', 'zaocanmofang', 'wanglaoji-c', 'mengniu',
  23. 'mengniuzaocan', 'guolicheng2', 'daofandian1', 'daofandian2', 'daofandian3', 'daofandian4', 'yingyingquqi', 'lefuqiu']
  24. '''
  25. def convert(size, box):
  26. dw = 1. / size[0]
  27. dh = 1. / size[1]
  28. x = (box[0] + box[1]) / 2.0
  29. y = (box[2] + box[3]) / 2.0
  30. w = box[1] - box[0]
  31. h = box[3] - box[2]
  32. x = x * dw
  33. w = w * dw
  34. y = y * dh
  35. h = h * dh
  36. return (x, y, w, h)
  37. path = 'your path'# /a/Annotations 这里就是路径到a
  38. def convert_annotation(image_id):
  39. in_file = open(path+'Annotations/%s.xml' % (image_id))
  40. #print(111,in_file)
  41. out_file = open(path+'labels/%s.txt' % (image_id), 'w')
  42. tree = ET.parse(in_file)
  43. root = tree.getroot()
  44. size = root.find('size')
  45. w = int(size.find('width').text)
  46. h = int(size.find('height').text)
  47. for obj in root.iter('object'):
  48. #try:
  49. #difficult = obj.find('difficult').text
  50. #except AttributeError:
  51. # difficult = obj.find('Difficult').text
  52. cls = obj.find('name').text
  53. if cls not in classes:# or int(difficult) == 1:
  54. continue
  55. cls_id = classes.index(cls)
  56. xmlbox = obj.find('bndbox')
  57. b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
  58. float(xmlbox.find('ymax').text))
  59. bb = convert((w, h), b)
  60. out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
  61. wd = getcwd()
  62. print(wd)
  63. for image_set in sets:
  64. if not os.path.exists(path+'labels/'):
  65. os.makedirs(path+'labels/')
  66. image_ids = open(path+'ImageSets/Main/%s.txt' % (image_set)).read().strip().split()
  67. #print(111,image_ids)
  68. list_file = open(path+'%s.txt' % (image_set), 'w')
  69. for image_id in image_ids:
  70. list_file.write(path+'images/%s.jpg\n' % (image_id))
  71. convert_annotation(image_id)
  72. list_file.close()

 第二步,把一个整个的数据集进行切割,比如你有100张数据,80张用来训练,20张用来测试。

  1. # -*- coding: utf-8 -*-
  2. import os
  3. import random
  4. trainval_percent = 0.2
  5. train_percent = 0.8
  6. xmlfilepath = 'hat_data/Annotations'
  7. txtsavepath = 'hat_data/ImageSets/Main/'
  8. total_xml = os.listdir(xmlfilepath)
  9. num = len(total_xml)
  10. list = range(num)
  11. tv = int(num * trainval_percent)
  12. tr = int(tv * train_percent)
  13. trainval = random.sample(list, tv)
  14. train = random.sample(trainval, tr)
  15. ftrainval = open(txtsavepath+'trainval.txt', 'w')
  16. ftest = open(txtsavepath+'test.txt', 'w')
  17. ftrain = open(txtsavepath+'train.txt', 'w')
  18. fval = open(txtsavepath+'val.txt', 'w')
  19. for i in list:
  20. name = total_xml[i][:-4] + '\n'
  21. if i in trainval:
  22. ftrainval.write(name)
  23. if i in train:
  24. ftest.write(name)
  25. else:
  26. fval.write(name)
  27. else:
  28. ftrain.write(name)
  29. ftrainval.close()
  30. ftrain.close()
  31. fval.close()
  32. ftest.close()

 这样会生成几个文件

 第三步,按照文件把文件进行划分,

在yolov5中标准对应的是images和labels,你可以修改成自己的文件名字,但是那样子你得在/data/dataset.py中进行修改代码,反正都可以,

  1. # -*- coding: utf-8 -*-
  2. import os
  3. import shutil
  4. def locate(path):
  5. temp = []
  6. with open(path+'val.txt','rb') as f:
  7. #r = f.readlines()
  8. for line in f.readlines():
  9. #print(str(line.strip()).split("'")[1])
  10. temp.append(str(line.strip()).split("'")[1])
  11. return temp
  12. def object_save(path,pic,pic_save):
  13. temp = locate(path)
  14. #print(temp)
  15. if not os.path.exists(pic_save+'val'):
  16. os.makedirs(pic_save+'val')
  17. if not os.path.exists(pic_save+'train'):
  18. os.makedirs(pic_save+'train')
  19. for i in os.listdir(pic):
  20. if i[:-4] in temp:
  21. print(i)
  22. shutil.copyfile(pic+i,pic_save+'val/'+i)
  23. else:
  24. shutil.copyfile(pic+i,pic_save+'train/'+i)
  25. if __name__ == '__main__':
  26. ImageSets_path = './ImageSets/Main/'
  27. pic_path = './JPEGImages/'
  28. pic_save_path = './images/'
  29. object_save(ImageSets_path,pic_path,pic_save_path)
  30. labels_path = './Annotations/'
  31. labels_save_path = './labels/'
  32. object_save(ImageSets_path,labels_path,labels_save_path)

(3)修改train.py

 (4)python train.py

各种BUG

1.AssertionError: train: No labels in images/train.cache. Can not train without labels. See https://github.com/ultralytics/yolov5/wiki/Train-Custom-Data

查了网上很多资料,出现这个问题都在数据格式转换上面,我再三检查,我没什么问题。

改来改去,把yaml中路径换成了绝对路径,可以了。

老人,地铁,手机

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/680113
推荐阅读
相关标签
  

闽ICP备14008679号