【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

04-08 1742阅读

目录

一、简介

配置

环境准备

二、环境配置

1.安装anaconda

2.安装TensorFlow

3.安装pytorch

4.pyqt5安装

 5.安装labelimg

6.下载yolov5

7.pycharm安装

三、使用labelimg标记图片

1.准备工作

2.标记图片

四、 划分数据集以及配置文件修改

1. 划分训练集、验证集、测试集

2.XML格式转yolo_txt格式

3.配置文件

4.聚类获得先验框

五、使用CPU训练

六、训练结果可视化


一、简介

   最近为了应付毕业论文,学习了目标检测,目的是检测车辆和行人,使用了yolov5,想到了是否可以在mac 上跑yolov5 ,因为是m1芯片,以及系统的更新,踩了不少坑,总结了几个博主的经验,顺利的在mac上实现了yolov5的训练和检测。

踩坑点:pyqt5安装、labelimg安装(需前置pyqt5)、yolov5训练时隐藏文件文件.DS_store无法识别

配置

电脑型号:2021 mbp  m1 pro

系统版本:ventura 13.0 (22A380)

环境准备

anaconda individual 最新版

python 3.9.13

pytorch 2.0 (后面有教程)

TensorFlow 2.11.0(后面有教程)

Pyqt5 5.15.7(后面有教程)

labelimg 1.8.6

pycharm 2022.3

yolov5 

二、环境配置

1.安装anaconda

(1)进入官网

官网链接:Anaconda | The World's Most Popular Data Science Platform

直接在这里下载并安装anaconda就可以

(2)点击安装包进行安装

直接无脑点下一步

在这一步时选择仅为我安装。【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

安装好之后再应用程序里就可以看见。

(3)打开终端之后

发现前面有个(base)就是安装成功了。

2.安装TensorFlow

(1)创建一个新的anaconda环境

conda create -n tf python=3.9.13

(2)切换到tf环境(再打开终端时要记得切到这个环境)

conda activate tf

【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

前面有(tf)则是转换成功 

(3)安装macos版本的TensorFlow。

如果显示404等错误,可以尝试挂个梯子。

conda install -c apple tensorflow-deps

python3 -m pip install tensorflow-macos

(如果不确定使用python3还是python,可以使用which python查看路径,使用虚拟环境下的python才有效)

python3 -m pip install tensorflow-metal 

(4)然后在终端输入

python3

import tensorflow 

如果出现

则是成功

exit()

可以退出python命令行

报错——>提示numpy版本不兼容(numpy版本过低要重新装)

conda uninstall numpy

pip install numpy

再次尝试导入tensorflow重复(4)中

成功

3.安装pytorch

进入pytorch官网

官网链接:PyTorch

【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

点击install 出现

【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

 选择相应的配置

在终端运行

pip3 install torch torchvision torchaudio

 等待安装完成即可。

4.pyqt5安装

因为labelimg需要Pyqt5,但高版本macos 的pyqt安装会出错。

可以先运行一下

pip install pyqt5

如果成功则这步省略

出错则需要进行安装homebrew 再用brew去安装pyqt5

(1)安装homebrew

Homebrew — The Missing Package Manager for macOS (or Linux)

首页就是安装方法

终端运行

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

安装完成之后 使用brew 安装pyqt5

brew install pyqt5

如果你的brew 长时间没更新

会报404找不到资源的错误,那就先要更新brew,csdn搜索即可。

安装完成之后进入homebrew的cellar文件夹

我的在

/opt/homebrew/Cellar

找到pyqt@5文件夹点进去

目录如下所示

/opt/homebrew/Cellar/pyqt@5/5.15.7_2/lib/python3.9/site-packages

把下列文件全部放到anaconda环境中

【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

 首先找到conda的环境

conda env list

【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

我的tf环境在

/Users/qishuocheng/anaconda3/envs/tf

使用前往文件夹就可以

【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

点进去找到lib文件夹

/Users/qishuocheng/anaconda3/envs/tf/lib/python3.9/site-packages

【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

 把上面pyqt5的文件放进来

python 

import PyQt5

不报错就算成功【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

 5.安装labelimg

上述完成后进行

pip install labelimg

安装完成之后

输入

labelimg

【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

 出现这个即可。

6.下载yolov5

GitHub - ultralytics/yolov5 at v6.1

直接下载zip

或者git clone到本地

git clone https://github.com/ultralytics/yolov5.git (加本地文件地址)

没有git 的要先

pip install git

7.pycharm安装

PyCharm: the Python IDE for Professional Developers by JetBrains

进入官网

下载之后配置

切到你的conda环境

【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

如果没有就添加本地解释器

【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

选择你的环境点击确定就可以切换环境啦。 

三、使用labelimg标记图片

1.准备工作

在yolov5目录下新建一个名为VOCData的文件夹【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

在VOCData文件夹下创建 Annotations 和 images 文件夹

images放要训练的图片

(【🎯易错】:images的文件名不建议修改,否则之后训练时容易出现No labels found的错误,原因见下)【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

[说明]:

Annotations 文件夹用于存放使用labelimg标记后的图片(XML格式)

images 文件夹用于存放用于标记的图片

(【🎯易错】:images 文件夹下直接放图片,内部不要嵌套有文件夹,否则之后训练可能会出现 No label found 的错误,具体原因见下文中 xml_to_yolo.py文件的第67行)

2.标记图片

在cmd窗口下输入 labelimg 或者运行 labelimg.py 文件进入labelimg的可执行程序(注:如果是在虚拟环境下安装的labelimg,记得先激活虚拟环境)

conda activate tf(你自己的虚拟环境名)

分别设置需要标注图片的文件夹和存放标记结果的文件夹的地址

图像放在之前设置好的images里

更改存放目录改为Annotions文件夹里

【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

推荐设置自动保存

 【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

 

标记图片快捷键:w:标记   a:上一张图片   d:下一张图片

标注的时候尽可能贴近物体轮廓

【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

四、 划分数据集以及配置文件修改

1. 划分训练集、验证集、测试集

 在VOCData目录下创建程序 split_train_val.py 并运行以下代码。代码可以不做任何修改

 注意注意:在macos下,文件夹内会生成.Ds_store隐藏文件要先删除 不然会读取错误

打开images文件夹(之前创建的文件)

这是我的文件夹 根据自己路径找

 cd /Users/qishuocheng/Desktop/yolov5/VOCData/images 

ls -a

【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

删除这个文件后

rm .DS_Store

运行下面的代码(images下存放你的图片)

# coding:utf-8
import os
import random
import argparse
parser = argparse.ArgumentParser()
#xml文件的地址,根据自己的数据进行修改 xml一般存放在Annotations下
parser.add_argument('--xml_path', default='Annotations', type=str, help='input xml label path')
#数据集的划分,地址选择自己数据下的ImageSets/Main
parser.add_argument('--txt_path', default='ImageSets/Main', type=str, help='output txt label path')
opt = parser.parse_args()
trainval_percent = 1.0  # 训练集和验证集所占比例。 这里没有划分测试集
train_percent = 0.9     # 训练集所占比例,可自己进行调整
xmlfilepath = opt.xml_path
txtsavepath = opt.txt_path
total_xml = os.listdir(xmlfilepath)
if not os.path.exists(txtsavepath):
    os.makedirs(txtsavepath)
num = len(total_xml)
list_index = range(num)
tv = int(num * trainval_percent)
tr = int(tv * train_percent)
trainval = random.sample(list_index, tv)
train = random.sample(trainval, tr)
file_trainval = open(txtsavepath + '/trainval.txt', 'w')
file_test = open(txtsavepath + '/test.txt', 'w')
file_train = open(txtsavepath + '/train.txt', 'w')
file_val = open(txtsavepath + '/val.txt', 'w')
for i in list_index:
    name = total_xml[i][:-4] + '\n'
    if i in trainval:
        file_trainval.write(name)
        if i in train:
            file_train.write(name)
        else:
            file_val.write(name)
    else:
        file_test.write(name)
file_trainval.close()
file_train.close()
file_val.close()
file_test.close()


运行结束后会在生成一个名为 ImageSets 的文件夹:

 测试集里的内容为空,因为在划分数据的时候,将90%的数据划分到训练集,将10%的数据划分到训练集。如果要分配,则调整上面14,15行代码中trainval和train的所占的比例

[说明]:

训练集是用来训练模型的,通过尝试不同的方法和思路使用训练集来训练不同的模型

验证集使用交叉验证来挑选最优的模型,通过不断的迭代来改善模型在验证集上的性能

测试集用来评估模型的性能

2.XML格式转yolo_txt格式

在VOCData目录下创建程序 xml_to_yolo.py 并运行以下代码,注意:

将classes改为自己标注时设置的类名(我这里叫"car")

将各个绝对路径修改为自己的

# -*- coding: utf-8 -*-
import xml.etree.ElementTree as ET
import os
from os import getcwd
sets = ['train', 'val', 'test']
classes = ["car"]  # 改成自己的类别
abs_path = os.getcwd()
print(abs_path)
def convert(size, box):
    dw = 1. / (size[0])
    dh = 1. / (size[1])
    x = (box[0] + box[1]) / 2.0 - 1
    y = (box[2] + box[3]) / 2.0 - 1
    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
def convert_annotation(image):
    in_file = open('/Users/qishuocheng/Desktop/yolov5/VOCData/Annotations/%s.xml' % image,encoding='utf-8')
    out_file = open('/Users/qishuocheng/Desktop/yolov5/VOCData/labels/%s.txt' % image, '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
        # 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))
        b1, b2, b3, b4 = b
        # 标注越界修正
        if b2 > w:
            b2 = w
        if b4 > h:
            b4 = h
        b = (b1, b2, b3, b4)
        bb = convert((w, h), b)
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
wd = getcwd()
for image_set in sets:
    if not os.path.exists('/Users/qishuocheng/Desktop/yolov5/VOCData/labels/'):
        os.makedirs('/Users/qishuocheng/Desktop/yolov5/VOCData/labels/')
    image_ids = open(
        '/Users/qishuocheng/Desktop/yolov5/VOCData/ImageSets/Main/%s.txt' % image_set).read().strip().split()
    if not os.path.exists('/Users/qishuocheng/Desktop/yolov5/VOCData/dataSet_path/'):
        os.makedirs('/Users/qishuocheng/Desktop/yolov5/VOCData/dataSet_path/')
    list_file = open('dataSet_path/%s.txt' % image_set, 'w')
    # 这行路径不需更改,这是相对路径
    for image_id in image_ids:
        list_file.write('/Users/qishuocheng/Desktop/yolov5/VOCData/images/%s.jpeg\n' % image_id)
        convert_annotation(image_id)
    list_file.close()

 运行后会生成如下图所示的 dataSet_path 和 labels 文件夹。dataSet_path下会有三个数据集的txt文件,labels下存放各个图像的标注文件

3.配置文件

 在 yolov5 的 data 文件夹下创建一个名为 myvoc.yaml,模板如下,改成自己的路径,根据自己实际情况填写:

(【🎯易错】:注意冒号后面是有空格的)

train: /Users/qishuocheng/Desktop/yolov5/VOCData/dataSet_path/train.txt

val: /Users/qishuocheng/Desktop/yolov5/VOCData/dataSet_path/val.txt

# number of classes

nc: 1

# class names

names: ["car"]

4.聚类获得先验框

在 models 文件夹下找到 yolov5s.yaml(如果使用这个权重模型训练的话),将其中的 nc 改为实际上标注类的数量,和 myvoc.yaml 一样(记得保存)。

# YOLOv5 🚀 by Ultralytics, GPL-3.0 license
# Parameters
nc: 1  # 只改这里 改成自己的类的数量
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # layer channel multiple
anchors:
  - [10,13, 16,30, 33,23]  # P3/8
  - [30,61, 62,45, 59,119]  # P4/16
  - [116,90, 156,198, 373,326]  # P5/32
# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, C3, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, C3, [1024]],
   [-1, 1, SPPF, [1024, 5]],  # 9
  ]
# YOLOv5 v6.0 head
head:
  [[-1, 1, Conv, [512, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  # cat backbone P4
   [-1, 3, C3, [512, False]],  # 13
   [-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 4], 1, Concat, [1]],  # cat backbone P3
   [-1, 3, C3, [256, False]],  # 17 (P3/8-small)
   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 14], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 20 (P4/16-medium)
   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 10], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 23 (P5/32-large)
   [[17, 20, 23], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

五、使用CPU训练

 在cmd窗口下激活相应虚拟环境后 cd 到 yolov5 文件夹后,输入下列指令即可开始训练

mac也可以调用mps加速,听说有bug 不如用cpu训练的快,所以建议用cpu

python train.py --weights yolov5s.pt  --cfg models/yolov5s.yaml  --data data/myvoc.yaml --epoch 200 --batch-size 8 --img 640   --device cpu

[参数说明]:

--weights :权重文件所在的相对路径

--cfg:存储模型结构配置文件的相对路径

--data:存储训练、测试数据的文件的相对路径

--epoch:训练过程中整个数据集将被迭代(训练)了多少次

--batch-size:训练完多少张图片才进行权重更新

--img:img-size

--device:选择用CPU或者GPU训练

(开始训练)

【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

训练完成!

六、训练结果可视化

训练结果将保存在/yolov5/runs/train/exp 文件夹下,部分文件意义如下:

【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

weights:训练生成权重。包含 best.pt (最好的权重,detect时用到它),和 last.pt(最近生成的权重模型)

confusion:混淆矩阵。混淆矩阵让我们了解分类模型所犯的错误,更重要的是可以了解哪些错误类型正在发生。

F1_curve:置信度和F1分数的关系图

P_curve:准确率和置信度的关系图

R_curve:召回率和置信度之间的关系

PR_curve:PR曲线中的P代表的是precision(精准率),R代表的是recall(召回率),其代表的是精准率与召回率的关系

labels:左上图表示个类别的数据量;右上图表示标签;左下图表示 center 的 xy 坐标;右下图表示各个标签的长和宽

 训练时或者训练后,输入tensorboard --logdir=runs,即可利用 tensorboard 实现训练结果可视化

 tensorboard --logdir=runs

在高版本的tensorboard中 有个很恶心的点需要更改 = 为 "" 不然识别不出来。

 tensorboard --logdir "runs"

 访问网页 http://localhost:6006/即可看到各种训练结果(注:localhost指的是你所在的计算机本身)【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

使用刚刚训练好的 best.pt模型来检测:

python detect.py --weights runs/train/exp/weights/best.pt --source ../source/test.png

[说明]:

--weights:表示我们选择的权重模型

--source:表示待检测的图片的路径 (…/表示上级路径)

成功实现了恶劣环境下的DM码的定位

识别成功

【yolov5 教程】(避免踩雷保姆级教程 在m1芯片下 使用yolov5本地训练自己的数据集 ——mac m1

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]