PyTorch深度学习实战(22)——从零开始实现YOLO目标检测

PyTorch深度学习实战(22)——从零开始实现YOLO目标检测

    • 0. 前言
    • 1. YOLO 架构
      • 1.1 R-CNN 目标检测模型的局限性
      • 1.2 YOLO 目标检测模型原理
    • 2. 实现 YOLO 目标检测
      • 2.1 编译 DarkNet
      • 2.2 设置数据集格式
      • 2.3 配置网络架构
      • 2.4 模型训练和测试
    • 小结
    • 系列链接

0. 前言

YOLO (You Only Look Once) 是一种实时目标检测算法,它以其高效性和准确性而闻名。相比于传统的目标检测方法,YOLO 的主要特点是在单个前向传递中同时完成目标检测和分类,因此称为 You Only Look Once。由于整个检测过程只需要一次前向传递,因此非常高效,可以实现实时目标检测。此外,YOLO 通过全局感受野捕捉了整个图像中的上下文信息,对小尺寸物体的检测效果较好。在本节中,将介绍 YOLO 的工作原理,然后在自定义数据集上训练 YOLO 目标检测模型。

1. YOLO 架构

YOLO 目标检测模型与 Faster R-CNN 模型相比,YOLO 无需使用区域提议算法 (Region Proposal Network, RPN),其在单个神经网络中预测边界框和类别概率,因此推理效率更高。

1.1 R-CNN 目标检测模型的局限性

首先,我们了解基于 R-CNN 的目标检测算法的局限性。在 Faster R-CNN 中,使用锚框在图像上滑动并识别可能包含对象的区域,然后执行边界框校正。然而,在全连接层中,仅将检测到的区域的 RoI 池化输出作为输入传递,对于不完全包含对象的区域(即对象超出区域提议的边界框),网络只能猜测对象的边界框,因为网络仅仅看到了区域提议,并没有看到完整的图像。
YOLO 能够克服这一问题,它能够在预测目标对象边界框时看到整个图像。此外,由于 Faster R-CNN 有两个网络 (RPN 和预测对象类别及其边界框的分类-回归网络),因此,Faster R-CNN 的推理速度依然很慢。

1.2 YOLO 目标检测模型原理

接下来,我们将介绍 YOLO 如何克服 Faster R-CNN 的局限性,可以在一次前向传递过程中查看整个图像并进行预测。

(1) 为给定图像创建标签信息训练模型。

考虑以下带有真实边界框(红色边界框)的带标签图像:

示例图像

将图像划分为 N x N 个网格单元,假设 N=3

网格单元
识别包含至少一个真实边界框中心的网格单元,在示例中,为 3 x 3 网格图像的单元格 a1b3。真实边界框的中心点所在的单元负责预测对象的边界框,接下来,创建与每个单元格对应的标签信息。

每个单元格对应的输出标签信息格式如下:

y=pc
bx
by
bw
bh
c1
c2
c3

其中,pc (objectness score) 是单元格包含对象的概率。接下来,我们介绍如何计算 bxbybwbh
首先,我们将网格单元(考虑 a1 网格单元)视为独立图像,并将其尺寸归一化为 01 之间,如下所示:

网格单元
bxby 是真实边界框的中点相对于图像(网格单元)的位置,在示例中,bx = 0.8,因为真实边界框的中点距离原点(网格单元左上角) 0.8 个单位,同理,by = 0.25,而 bw 是边界框的宽度与网格单元格宽度的比值;bh 是边界框高度与网格单元格高度的比值:

网格单元
接下来,预测与网格单元对应的类别。如果有三个类别 (c1 – 气球、c2 – 玩具、c3 – 花篮),c1,c2,c3分别表示该单元格包含这三个类别的概率。这里我们不需要背景类别,因为 pc 对应于网格单元格是否包含对象。
我们已经了解如何表示每个单元格的输出,接下来,介绍如何构建以上 3 x 3 网格单元格的输出。
首先,考虑网格单元 a3 的输出:

y=0
?
?
?
?
?
?
?

单元格 a3 的输出如上图所示。由于网格单元不包含对象,因此第一个输出 pc0,其余值则无关紧要,因为该单元不包含任何目标对象的真实边界框中心。
接下来,考虑对应于网格单元 a1 的输出:

y=1
0.75
0.25
0.5
0.4
1
0
0

网格单元包含具有 bxbybwbh 值的对象,类别是气球,因此 c11,而 c2c30
对于每个单元格,均有 8 个输出。因此,对于 3 x 3 的单元格网格,将得到形状为 3 x 3 x 8 的输出。

(2) 定义模型,其中输入为图像,输出与上一步中定义的真实值相符,输出尺寸为 3 x 3 x 8

输出尺寸
(3) 通过使用锚框定义真实标签值。
在以上示例中,我们一直假设在一个网格单元格中只有一个对象。而在现实中,可能存在同一个网格单元内有多个对象的情况。如果仍按照一个对象构建训练数据,将导致创建的真实标签值并不正确。如下图所示,花篮和气球的真实边界框的中点落在同一个单元格(单元格 a1 中):

单元格
为了避免这种情况,一种方法是使用具有更多行和列的网格,例如,19 x 19 网格。但是,增加网格单元数量仍然可能无济于事。为了解决这一问题,需要再次使用锚框,假设我们有两个锚框,一个高大于宽,另一个宽大于高。通常,锚框的中心设定为网格单元格的中心。当存在两个锚框时,每个单元格的输出表示为两个锚框预期输出的连接:

y=pc
bx
by
bw
bh
c1
c2
c3
pc
bx
by
bw
bh
c1
c2
c3

此时,因为使用了两个锚框,模型输出尺寸为 3 x 3 x 16YOLO 模型预测输出的形状为 N x N x (num_classes + 1) x (num_anchor_boxes ),其中 N x N 是网格单元数,num_classes 是数据集中的类别数,num_anchor_boxes 是每个单元格的锚框数。

(3) 定义损失函数训练模型。

在计算与模型相关的损失时,需要确保在对象置信度得分小于某个阈值(表示单元格不包含目标对象)时不计算回归损失和分类损失。如果单元格包含一个对象,我们需要确保目标对象分类尽可能准确。
如果单元格包含对象,则边界框偏移量应尽可能接近真实边界框。但是,由于宽度和高度的偏移量比中心的偏移量高得多(因为中心的偏移量范围在 01 之间,而宽度和高度的偏移量并无此限制),因此通过获取平方根值来给予宽度和高度偏移较低的权重。
计算定位和分类的损失:
L l o c = λ c o o r d ∑ i = 0 S 2 ∑ j = 0 B 1 i j o b j [ ( x i − x ^ i ) 2 + ( y i − y ^ i ) 2 + ( w i − w ^ i ) 2 + ( h i − h ^ i ) 2 ] L c l s = ∑ i = 0 S 2 ∑ j = 0 B ( 1 i j o b j + λ ( 1 − 1 i j o b j ) ) ( C i j − C ^ i j ) 2 + ∑ i = 0 S 2 ∑ c ∈ C 1 i j o b j ( p i ( c ) − p ^ i ( c ) ) 2 L = L l o c + L c l s L_{loc}=\lambda_{coord}\sum_{i=0}^{S^2}\sum_{j=0}^{B}1_{ij}^{obj}[(x_i-\hat x_i)^2+(y_i-\hat y_i)^2+(\sqrt {w_i}-\sqrt{\hat w_i})^2+(\sqrt {h_i}-\sqrt{\hat h_i})^2] \\ L_{cls}=\sum_{i=0}^{S^2}\sum_{j=0}^{B}(1_{ij}^{obj}+\lambda(1-1_{ij}^{obj}))(C_{ij}-\hat C_{ij})^2+\sum_{i=0}^{S^2}\sum_{c∈C}1_{ij}^{obj}(p_i(c)-\hat p_i(c))^2 \\ L=L_{loc}+L_{cls} Lloc=λcoordi=0S2j=0B1ijobj[(xix^i)2+(yiy^i)2+(wi w^i )2+(hi h^i )2]Lcls=i=0S2j=0B(1ijobj+λ(11ijobj))(CijC^ij)2+i=0S2cC1ijobj(pi(c)p^i(c))2L=Lloc+Lcls

其中, λ c o o r d \lambda_{coord} λcoord 是与回归损失相关的权重, 1 i j o b j 1_{ij}^{obj} 1ijobj 表示单元格是否包含对象, p ^ i ( c ) \hat p_i(c) p^i(c) 对应于预测的类别概率, C i j C_{ij} Cij 表示对象置信度得分,总损失是分类和回归损失值的之和。

2. 实现 YOLO 目标检测

为了实现 YOLO 目标检测模型,我们使用官方的 YOLO-v4 实现来识别图像中公共汽车和卡车的位置,继续使用与 R-CNN 一节中相同的数据集,并根据我们的需要对其进行修改。

2.1 编译 DarkNet

首先,从 GitHub 获取 DarkNet 存储库并进行编译,官方 YOLOv4 模型基于 C 语言编写的,为了在 PyTorch 中使用需要进行编译。

(1) 下载 DarkNet 存储库后,重新配置 Makefile 文件,在shell中执行以下命令:

darknet-master$ sed -i 's/OPENCV=0/OPENCV=1/' Makefile
darknet-master$ sed -i 's/GPU=0/GPU=1/' Makefile
darknet-master$ sed -i 's/CUDNN=0/CUDNN=1/' Makefile
darknet-master$ sed -i 's/CUDNN_HALF=0/CUDNN_HALF=1/' Makefile

Makefile 是编译 DarkNet 所需的配置文件,使用以下标志编译 DarkNetOPENCVGPUCUDNNCUDNN_HALF,使用这些优化标志能够使模型训练速度更快。sed 函数表示流编辑器,它是一个强大的 Linux 命令,可以直接从命令提示符修改文本文件中的信息,语法为 sed 's/<search-string>/<replace-with>/' path/to/text/file,例如,使用 sed -i 's/OPENCV=0/OPENCV=1/' Makefile 能够将 OPENCV=0 替换为 OPENCV=1

(2) 编译 darknet 源码:

darknet-master$ make

(3) 下载并解压数据集,使用与 R-CNN 一节中相同的数据集。

(4) 下载预训练权重 yolov4.weights 进行样本预测。

(5) 运行以下命令测试是否安装成功:

darknet-master$ ./darknet detector test cfg/coco.data cfg/yolov4.cfg yolov4.weights data/test.jpeg

以上代码使用由神经网络配置 cfg/yolov4.cfg 和预训练权重 yolov4.weights 构建的神经网络对 data/test.jpeg 进行预测。此外,从 cfg/coco.data 文件中获取类别,文件中包含了预训练权重的训练对象类别,示例图像 (data/test.jpeg) 预测结果如下:

预测结果

我们已经安装了 darknet,在下一节中,我们将学习如何使用自定义数据集准备训练数据以满足 YOLOv4 输入、输出需求。

2.2 设置数据集格式

YOLO 使用固定格式进行训练,利用所需格式存储图像和标签后,就可以使用自定义数据集训练 YOLO 模型。接下来,我们介绍 YOLO 训练所需的文件和文件夹结构。

(1) 使用 vim 命令在 data 文件夹中创建 obj.names

darknet-master$ vim data/obj.names

data/obj.names 文件中添加以下内容:

bus
truck

obj.names
以上代码可以创建名为 obj.names 的文件,并将 “bus” 和 “truck” 写入其中,每个类别占一行。

(2) 创建文本文件 data/obj.data

darknet-master$ vim data/obj.data

data/obj.data 文件中添加以下内容,描述数据集中的参数以及包含训练和测试图像路径的文本文件位置,以及包含对象名称的文件的位置以及要保存训练模型的文件夹:

classes = 2
train = data/train.txt
valid = data/val.txt
names = data/obj.names
backup = backup/

data/obj.data
上述文本文件的扩展名并非 .txtYOLO 使用硬编码的名称和文件夹来识别数据的位置。

(3) 将所有图像和标签数据文本文件移动到 data/obj 文件夹中:

darknet-master$ mkdir -p data/obj
darknet-master$ cp -r open-images-bus-trucks/images/* data/obj/
darknet-master$ cp -r open-images-bus-trucks/yolo_labels/all/{train,val}.txt data/
darknet-master$ cp -r open-images-bus-trucks/yolo_labels/all/labels/*.txt data/obj/

所有训练和验证图像都位于 data/obj 文件夹中,且将所需文本文件移动到同一个文件夹中。每个包含图像标签数据的文件都与图像共享相同的名称,例如,该文件夹可能包含 1001.jpg1001.txt,文本文件包含该图像中目标对象的类别标签和边界框,如果 data/train.txt 包含 1001.jpg,则它为训练图像;如果它出现在 data/val.txt 中,表示它是验证图像。
文本文件本身包含如下信息:clsxcycwh,其中 cls(xc, yc) 处宽度为 w、高度为 h 的边界框中对象的类别索引,每行都存储图像中的一个目标对象。
例如,如果宽度为 800、高度为 600 的图像包含一个卡车和一个公交车,中心点分别位于 (500,300)(100,400),且它们的宽度和高度分别为 (200,100)(300,50),那么文本文件内容如下所示:

1 0.62 0.50 0.25 0.12
0 0.12 0.67 0.38 0.08

2.3 配置网络架构

YOLO 有多种大小不同的架构配置,适用于规模大小不同的训练数据集。架构配置可以使用不同的主干网络,使用 .cfg 文件定义网络架构配置,预定义的配置文件位于存储库的 cfgs 文件夹中,每个文本文件都包含一个不同的网络架构以及网络所用的超参数,例如批大小和学习率。本节中,使用最小的可用架构 (cfg/yolov4-tiny-custom.cfg) 并根据自定义数据集配置网络架构:

# 创建现有配置的副本
darknet-master$ cp cfg/yolov4-tiny-custom.cfg cfg/yolov4-tiny-bus-trucks.cfg
# 将最大批大小修改为4000
darknet-master$ sed -i 's/max_batches = 500200/max_batches=4000/' cfg/yolov4-tiny-bus-trucks.cfg
# 每个批数据的子批数据大小
darknet-master$ sed -i 's/subdivisions=1/subdivisions=16/' cfg/yolov4-tiny-bus-trucks.cfg
# 学习率衰减
darknet-master$ sed -i 's/steps=400000,450000/steps=3200,3600/' cfg/yolov4-tiny-bus-trucks.cfg 
# 类别数修改为2
darknet-master$ sed -i 's/classes=80/classes=2/g' cfg/yolov4-tiny-bus-trucks.cfg 
# 在分类和回归头中,修改输出卷积滤波器的数量255->21、57->33
darknet-master$ sed -i 's/filters=255/filters=21/g' cfg/yolov4-tiny-bus-trucks.cfg 
darknet-master$ sed -i 's/filters=57/filters=33/g' cfg/yolov4-tiny-bus-trucks.cfg

重新调整 yolov4-tiny 架构,使其可以自定义数据集上进行训练,接下来,就可以加载预训练的权重并微调模型参数。

2.4 模型训练和测试

GitHub 中下载预训练模型权重并存储在 build/darknet/x64 中:

darknet-master$ cp yolov4-tiny.conv.29 build/darknet/x64/

训练模型:

darknet-master$ ./darknet detector train data/obj.data cfg/yolov4-tiny-bus-trucks.cfg yolov4-tiny.conv.29 -dont_show -mapLastAt

在以上代码中,使用 -dont_show 标志跳过显示中间预测图像,-mapLastAt 将定期打印验证数据的平均平均精度,权重会定期存储在备份文件夹中,并且可以在训练后用于预测。
对新图像进行预测:

darknet-master$ ./darknet detector test data/obj.data cfg/yolov4-tiny-bus-trucks.cfg backup/yolov4-tiny-bus-trucks_4000.weights open-images-bus-trucks/images/0d39f132cdf7c027.jpg

测试结果

小结

YOLO 在目标检测任务中具有显著的优势,由于整个检测过程只需要一次前向传递,因此非常高效,并且可以实现实时目标检测。此外,YOLO 通过全局感受野捕捉了整个图像中的上下文信息,对小尺寸物体的检测效果较好。在本节中,使用 darknet 实现了 YOLO 目标检测模型,并了解了如何根据需要对模型进行修改。

系列链接

PyTorch深度学习实战(1)——神经网络与模型训练过程详解
PyTorch深度学习实战(2)——PyTorch基础
PyTorch深度学习实战(3)——使用PyTorch构建神经网络
PyTorch深度学习实战(4)——常用激活函数和损失函数详解
PyTorch深度学习实战(5)——计算机视觉基础
PyTorch深度学习实战(6)——神经网络性能优化技术
PyTorch深度学习实战(7)——批大小对神经网络训练的影响
PyTorch深度学习实战(8)——批归一化
PyTorch深度学习实战(9)——学习率优化
PyTorch深度学习实战(10)——过拟合及其解决方法
PyTorch深度学习实战(11)——卷积神经网络
PyTorch深度学习实战(12)——数据增强
PyTorch深度学习实战(13)——可视化神经网络中间层输出
PyTorch深度学习实战(14)——类激活图
PyTorch深度学习实战(15)——迁移学习
PyTorch深度学习实战(16)——面部关键点检测
PyTorch深度学习实战(17)——多任务学习
PyTorch深度学习实战(18)——目标检测基础
PyTorch深度学习实战(19)——从零开始实现R-CNN目标检测
PyTorch深度学习实战(20)——从零开始实现Fast R-CNN目标检测
PyTorch深度学习实战(21)——从零开始实现Faster R-CNN目标检测

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/140305.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

服务器中了mkp勒索病毒怎么处理,mkp勒索病毒解密,数据恢复

10月份以来&#xff0c;云天数据恢复中心陆续接到很多企业的求助&#xff0c;企业的服务器遭到了mkp勒索病毒攻击&#xff0c;导致企业的服务器数据库被加密&#xff0c;严重影响了企业工作&#xff0c;通过这一波mkp勒索病毒的攻击&#xff0c;云天数据恢复工程师为大家总结了…

jQuery的使用,下载以及一些小案例

24.jQuery的使用 1.官网地址 https://jquery.com/ 版本&#xff1a; ●1X:兼容E678等低版本浏览器&#xff0c;官网不再更新 ●2x:不兼容IE678等低版本浏览器&#xff0c;官网不再更新 ●3x:不兼容E678等低版本浏览器&#xff0c;是官方主要更新维护的版本 2 jQuery的使用步…

如何处理前端响应式图片?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

正方形(Squares, ACM/ICPC World Finals 1990, UVa201)rust解法

有n行n列&#xff08;2≤n≤9&#xff09;的小黑点&#xff0c;还有m条线段连接其中的一些黑点。统计这些线段连成了多少个正方形&#xff08;每种边长分别统计&#xff09;。 行从上到下编号为1&#xff5e;n&#xff0c;列从左到右编号为1&#xff5e;n。边用H i j和V i j表示…

基于PHP的创意设计分享系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

jenkins整合gerrit

背景 公司项目之前使用jenkins整合了gitlab&#xff0c;后面代码迁移到gerrit&#xff0c;所以需要修改jenkins配置。下面就简单的介绍一下jenkins如何整合gerrit。 环境 服务器&#xff1a;linux 环境&#xff1a;docker、jenkins 代码仓库&#xff1a;gerrit 前提 docke…

链表 oj2 (7.31)

206. 反转链表 - 力扣&#xff08;LeetCode&#xff09; 我们通过头插来实现 将链表上的节点取下来&#xff08;取的时候需要记录下一个节点&#xff09;&#xff0c;形成新的链表&#xff0c;对新的链表进行头插。 /*** Definition for singly-linked list.* struct ListNode…

STL库——Vector常见使用接口

一、介绍 1. vector是表示可变大小数组的序列容器&#xff0c;就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素 进行访问&#xff0c;和数组一样高效。但是又不像数组&#xff0c;它的大小是可以动态改变的&#xff0…

基于 Triple 实现 Web 移动端后端全面打通

*作者&#xff1a;陈有为&#xff0c;陌陌研发工程师、Apache Dubbo PMC RPC 协议开发微服务 在我们正常开发微服务的时候&#xff0c;传统 RPC 服务可能在最底层。上层可能是浏览器、移动端、外界的服务器、自己的测试、curl 等等。我们可能会通过 Tomcat 这种外部服务器去组…

​蔚来 V2G:带你重新了解如何参与构建新型电力系统

8 月 23 号&#xff0c;蔚来低调的在官方社区社区内发布了一条推文&#xff0c;推文为 「蔚来参与全国最大规模 V2G 需求响应」。 而车网互动验证中心(简称 e-Park)的 V2G 试验&#xff0c;在江苏无锡正式启动。 本次响应时间为 30 分钟&#xff0c;50 台电动车送电近 2000kW…

手术麻醉临床信息管理系统源码,客户端可以接入监护仪、麻醉机、呼吸机

一、手术麻醉临床信息管理系统介绍 1、手术麻醉临床信息管理系统是数字化手段应用于手术过程中的重要组成部分&#xff0c;用数字形式获取并存储手术相关信息&#xff0c;既便捷又高效。既然是管理系统&#xff0c;那就是一整套流程&#xff0c;管理患者手术、麻醉的申请、审批…

传输层协议(TCP/UDP协议)

全文目录 端口号端口号范围划分 传输层UDP协议特点基于UDP的应用层协议 TCP协议确认应答机制&#xff08;可靠性&#xff09;延迟应答机制超时重传机制流量控制连接管理机制TIME_WAIT 状态CLOSE_WAIT 状态拥塞控制滑动窗口 TCP、UDP对比TCP的listen第二个参数 端口号 在套接字…