yolo 训练
这里写目录标题
- 分配训练集&Validation数量
- 数据集读取
- 读取全部文件夹
- 替换路径
- loss weight
- NMS
- BBox_IOU
- EIou
- Optimizer
分配训练集&Validation数量
validation_size = training_size * validation_ratio / (1 - validation_ratio)
training_size = 219
validation_ratio = 0.2
validation_size = 219*0.2/(1-0.2)
如果你有 346 张验证图像,使用 k=5 的交叉验证方法,你可以将这些图像分成 5 个不同的折叠(fold),每个折叠包含 69 或 70 张图像。
平均分配图像的方法:
num_images_per_fold = len(val_images) // num_folds
from sklearn.model_selection import KFold# 假设你有 291 个训练图像和 55 个验证图像
train_images = range(291)
valid_images = range(291, 291+55)# 将训练图像分成五个部分
kf = KFold(n_splits=5, shuffle=True)
for fold, (train_idx, valid_idx) in enumerate(kf.split(train_images)):# 选择一个部分作为验证集,其余部分作为训练集train_images_fold = [train_images[i] for i in train_idx]valid_images_fold = [train_images[i] for i in valid_idx]# 在每次交叉验证中,使用训练集进行训练,并使用验证集进行验证# TODO: 训练和验证模型# 记录模型的性能指标# TODO: 记录模型性能指标# 将五个结果的平均值作为模型的性能指标
# TODO: 计算模
数据集读取
读取全部文件夹
p = Path(p) # p = WindowsPath('E:/data/helmet_head/train')
glob.glob(str(p / '**' / '*.*'), recursive=True)
这行 Python 代码使用了 pathlib 模块中的 WindowsPath 类来创建一个 Windows 路径对象 p,表示了一个名为 train 的目录,该目录位于 E:/data/helmet_head/ 目录下。接下来,使用 glob 函数来获取该目录及其所有子目录中的所有文件(包括子目录中的文件)。
p / '**' / '*.*'
表示将 p 对象的路径添加上 '**'
(表示所有子目录),然后再添加上 '*.*'
(表示所有类型的文件)路径,得到一个包含通配符的字符串路径。这个字符串路径会被转换为一个 WindowsPath 对象并传递给 glob 函数。
glob(str(p / '**' / '*.*'
), recursive=True) 表示使用 glob 函数获取符合给定路径模式的文件列表。recursive=True 表示要递归地查找子目录中的文件。
替换路径
x = 'E:\\data\\helmet_head\\train\\collect20120420\\JPEGImages\\000000.jpg'
sa = '\\JPEGImages\\'
sb = '\\Annotations\\'
sb.join(x.rsplit(sa, 1))
将指定路径 x 中的子目录名称 ‘JPEGImages’ 替换为 ‘Annotations’
x.rsplit(sa, 1)
使用 rsplit
函数将路径 x 按照指定的子目录名称 ‘JPEGImages’ 进行分割,并将分割结果作为一个列表返回。其中,sa
是分割字符串,1
表示只分割一次,即只分割最后一次出现的位置。
x.rsplit(sa, 1) 的结果为:
[‘E:\data\helmet_head\train\collect20120420’, ‘000000.jpg’]。
'\\Annotations\\'.join(x.rsplit(sa, 1))
使用 ‘\Annotations\’ 字符串将分割后的列表中的元素连接起来,得到一个新的路径。这个路径将原路径中的子目录名称 ‘JPEGImages’ 替换为 ‘Annotations’。
‘\Annotations\’.join(x.rsplit(sa, 1)) 的结果为:
'E:\data\helmet_head\train\collect20120420\\Annotations\\
000000.jpg’
loss weight
Pytorch: BCEWithLogitsLoss
YOLO v5 中的loss weight 在data/hyp/scratch.yaml 中的cls_pw
,同时 obj_pw
也可以使用同样的vector
通过train.py 中:
model.class_weights = labels_to_class_weights(dataset.labels, nc).to(device) * nc # attach class weights
weights = np.bincount(classes, minlength=nc)
weights[weights == 0] = 1 # replace empty bins with 1
weights = 1 / weights # number of targets per class
weights /= weights.sum()
- 得到3个种类在数量上应该受到的提高为: tensor([0.12096, 2.43440, 0.44464])
- 其中数字越大的代表数据量越少
target = torch.ones([4,3,8,8], dtype=torch.float32)
output = torch.full([4,3,8,8], 1.5)
pos_weight = torch.ones([3,8,8])
criterion = torch.nn.BCEWithLogitsLoss(pos_weight=pos_weight)
criterion(output, target)
这里的pos_weight = torch.ones([3,8,8]) 一定确保倒数的维度和output/target 相同
初始的cls_pw
是一个scalar, 如下:
target = torch.ones([4,3,8,8], dtype=torch.float32)
output = torch.full([4,3,8,8], 1.5)
pos_weight = torch.ones([1])
criterion = torch.nn.BCEWithLogitsLoss(pos_weight=pos_weight)
criterion(output, target)
NMS
以下是torch 版的 NMS, 代替了torchvision.ops.nms(boxes, scores, iou_thres)
def nms(bboxes, scores, iou_thresh=0.5):_, order = scores.sort(0, descending=True)keep = []while order.numel() > 0:if order.numel() == 1: # 保留框只剩一个i = order.item()keep.append(i)breakelse:i = order[0].item() # 保留scores最大的那个框box[i]keep.append(i)iou = bbox_iou_new(bboxes[i], bboxes[order[1:]]).squeeze()idx = (iou <= iou_thresh).nonzero().squeeze() # 注意此时idx为[N-1,] 而order为[N,]if idx.numel() == 0:breakorder = order[idx + 1] # 修补索引之间的差值return keep
以下是计算bbox的,这个function 被用于替换 NMS中计算IOU。这样做可以帮助做些关于IOU相关的ablation 分析
def bbox_iou_new(box1, box2, GIoU=False, DIoU=False, CIoU=False, SIoU=False, EIoU=False, Focal=True, eps=1e-7):# Returns Intersection over Union (IoU) of box1(1,4) to box2(n,4)b1_x1, b1_y1, b1_x2, b1_y2 = box1.chunk(4, -1)b2_x1, b2_y1, b2_x2, b2_y2 = box2.chunk(4, -1)w1, h1 = b1_x2 - b1_x1, (b1_y2 - b1_y1).clamp(eps)w2, h2 = b2_x2 - b2_x1, (b2_y2 - b2_y1).clamp(eps)# Intersection areainter = (b1_x2.minimum(b2_x2) - b1_x1.maximum(b2_x1)).clamp(0) * \(b1_y2.minimum(b2_y2) - b1_y1.maximum(b2_y1)).clamp(0)# Union Areaunion = w1 * h1 + w2 * h2 - inter + eps# IoUiou = inter / unionif CIoU or DIoU or GIoU or EIoU:cw = b1_x2.maximum(b2_x2) - b1_x1.minimum(b2_x1) # convex (smallest enclosing box) widthch = b1_y2.maximum(b2_y2) - b1_y1.minimum(b2_y1) # convex heightif CIoU or DIoU or EIoU: # Distance or Complete IoU https://arxiv.org/abs/1911.08287v1c2 = cw ** 2 + ch ** 2 + eps # convex diagonal squaredrho2 = ((b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2 + (b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2) / 4 # center dist ** 2if CIoU: # https://github.com/Zzh-tju/DIoU-SSD-pytorch/blob/master/utils/box/box_utils.py#L47v = (4 / math.pi ** 2) * (torch.atan(w2 / h2) - torch.atan(w1 / h1)).pow(2)with torch.no_grad():alpha = v / (v - iou + (1 + eps))return iou - (rho2 / c2 + v * alpha) # CIoUelif EIoU:rho_w2 = ((b2_x2 - b2_x1) - (b1_x2 - b1_x1)) ** 2rho_h2 = ((b2_y2 - b2_y1) - (b1_y2 - b1_y1)) ** 2cw2 = cw ** 2 + epsch2 = ch ** 2 + epsif Focal:gamma = 0.5return (iou - (rho2 / c2 + rho_w2 / cw2 + rho_h2 / ch2)) * torch.pow(inter / (union + eps), gamma).mean() # Focal_EIoureturn iou - (rho2 / c2 + rho_w2 / cw2 + rho_h2 / ch2)return iou - rho2 / c2 # DIoUc_area = cw * ch + eps # convex areareturn iou - (c_area - union) / c_area # GIoU https://arxiv.org/pdf/1902.09630.pdfelif SIoU:# SIoU Loss https://arxiv.org/pdf/2205.12740.pdfs_cw = (b2_x1 + b2_x2 - b1_x1 - b1_x2) * 0.5 + epss_ch = (b2_y1 + b2_y2 - b1_y1 - b1_y2) * 0.5 + epssigma = torch.pow(s_cw ** 2 + s_ch ** 2, 0.5)sin_alpha_1 = torch.abs(s_cw) / sigmasin_alpha_2 = torch.abs(s_ch) / sigmathreshold = pow(2, 0.5) / 2sin_alpha = torch.where(sin_alpha_1 > threshold, sin_alpha_2, sin_alpha_1)angle_cost = torch.cos(torch.arcsin(sin_alpha) * 2 - math.pi / 2)rho_x = (s_cw / cw) ** 2rho_y = (s_ch / ch) ** 2gamma = angle_cost - 2distance_cost = 2 - torch.exp(gamma * rho_x) - torch.exp(gamma * rho_y)omiga_w = torch.abs(w1 - w2) / torch.max(w1, w2)omiga_h = torch.abs(h1 - h2) / torch.max(h1, h2)shape_cost = torch.pow(1 - torch.exp(-1 * omiga_w), 4) + torch.pow(1 - torch.exp(-1 * omiga_h), 4)return iou - 0.5 * (distance_cost + shape_cost)return iou # IoU
BBox_IOU
CIOU 弥补了 GIOU 只考虑重合不考虑临近但也可用的框。但是CIOU中的那几个criteria 依然还有缺点:
-
v 不太靠谱
- 如果 w, h 的量级为 ground-truth 的整倍数,那么v 为 0 (无效,一样大才是想要的,但不是倍数大) 比如 K倍:
- w = k w g t , h = k w g t w= kw^{gt}, h = kw^{gt} w=kwgt,h=kwgt v = 4 π 2 ( a r c t a n w g t h g t − a r c t a n k w g t k h g t ) 2 = 0 v = \frac{4}{\pi ^2}(arctan \frac{w^{gt}}{h^{gt}}-arctan\frac{kw^{gt}}{kh^{gt}})^2 = 0 v=π24(arctanhgtwgt−arctankhgtkwgt)2=0
-
还是 v 的这一步在gradient 这里引起的不靠谱
- w, h 会有相反的符号, 当 w 和 h 都比 ground truth 大/小 时,两个量按理也应该同时扩大/缩小。
- 符号导致对w,h 处理不公。
- 细节原因:
做partial gradient 后,w, h 会因为 V中 原本用来算宽高比之差的地方,导致各自在gradient 时,遭遇不公
这里的v 如果不放进训练过程,倒也还是make sense, 可以看作是宽高比的 norm-2 的计算。但放进训练,就要搞gradient,也就是搞partial gradient,就从🆗到不太行了。
EIou
Optimizer
Adam 与 AdamW 都是用于Yolo v5 中的optimiser. 他们在小数据集上可以很快降低loss, 但随着训练增加,他们不如SGD 会 平稳,反而会 oscillation.
Adam 可以看作是extend 自 L2 regularisation 的 optimiser. (Pytorch) (Paper)
AdamW 可以看作是extend自 weight decay 的 optimiser. (Pytorch) (Paper)
论文给 SGD和 Adam 都试了 weight decay 和 L2 regularization.红色的是传统使用 L2 regularization 做法, 绿色是使用weight decay的做法。
L2 regulrisation 都是针对Gradient做。
而 Weight decay 是在对 parameters 做 update时做。
相关文章:

yolo 训练
这里写目录标题 分配训练集&Validation数量数据集读取读取全部文件夹替换路径 loss weightNMSBBox_IOUEIou Optimizer 分配训练集&Validation数量 validation_size training_size * validation_ratio / (1 - validation_ratio)training_size 219 validation_ratio …...

谷歌chrome浏览器升级新版后字体显示不清楚解决方案
谷歌chrome浏览器升级新版后字体显示不清楚解决方案 参考图片: Chrome更新至版本Chrome 109.0.5414.120 字体看不清 浏览器症状与表现 Chrome更新至版本Chrome 109.0.5414.120 字体看不清;会很细,在设置中选择自定义的字体,仍无法…...

在外包干了三年,我废了……不吹不黑!
没错,我也干过外包,一干就是三年,三年后,我废了…… 虽说废的不是很彻底,但那三年我几乎是出差了三年、玩了三年、荒废了三年,那三年,我的技术能力几乎是零成长的。 说起这段三年的外包经历&a…...

【Vue】学习笔记-消息的订阅与发布
消息的订阅与发布(基本不用) 消息订阅与发布(pubsub)消息订阅与发布是一种组件间的通信的方式,适用于任意组件间通信 消息订阅与发布 1.订阅消息∶消息名 2.发布消息︰消息内容 消息订阅与发布的工作流程: (A是订阅者,B是发布…...
大疆无人机 MobileSDK(遥控器/手机端)开发 v5版<1>
文章目录 概要整体架构流程技术细节SDK 架构体系概述层级架构智能任务空白项目集成 MSDK新建空白项目新建 MyApplication.kt 文件修改 build.gradle(Module) 文件修改 AndroidManifest.xml 文件修改 MainActivity.kt 文件导入 UXSDK 开源框架4.X 和 5.X 版本差异说明DJIKey差异…...

azkaban介绍
目录 为什么需要工作流调度系统 什么是azkaban azkaban适用场景 azkaban特点 常见的工作流调度系统 azkaban和Ooize特性对比 azkaban的架构 azkaban调度的任务有可能有那些类型 总结 为什么需要工作流调度系统 一个完整的大数据分析系统,必然由很多任务单…...

自学黑客(网络安全)必学内容
随着时代的发展,经济、社会、生产、生活越来越依赖网络。而随着万物互联的物联网技术的兴起,线上线下已经打通,虚拟世界和现实世界的边界正变得模糊。这使得来自网络空间的攻击能够穿透虚拟世界的边界,直接影响现实世界的安全。 …...

Java每日一练(20230518) 移除元素、跳跃游戏II、复原IP地址
目录 1. 移除链表元素 🌟 2. 跳跃游戏 II 🌟🌟 3. 复原 IP 地址 🌟🌟 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 移…...

diff命令和vimdiff命令
文章目录 diff命令基本用法选项示例 vimdiff命令命令格式选项说明常用操作 diff命令 diff命令是一个文本比较工具,用于比较两个文件的内容,它会逐行比较两个文件的内容并输出它们之间的差异。下面是diff命令的常用选项和用法: 基本用法 比…...
AcWing 797.差分(C++)
目录 1.题目描述 2.AC 1.题目描述 797.差分 输入一个长度为 nn 的整数序列。 接下来输入 mm 个操作,每个操作包含三个整数 l,r,cl,r,c,表示将序列中 [l,r][l,r] 之间的每个数加上 cc。 请你输出进行完所有操作后的序列。 输入格式 第一行包含两…...

Python每日一练(20230515) 只出现一次的数字 I\II\III
目录 1. 只出现一次的数字 Single Number 2. 只出现一次的数字 II Single Number II 3. 只出现一次的数字 III Single Number III 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 leetcod…...

基于【EasyDL】【图像分类】实现农作物病害识别小程序
内容、数据集来源:基于飞桨的农作物病害智能识别系统 - 飞桨AI Studio 项目背景 联合国粮食及农业组织的一份报告表明,每年农业生产的自然损失中有三分之一以上是由农业病虫害造成的,使这些成为当前影响农业生产和农业生产的最重要因素。需要考虑的农业…...

元宇宙又“死”了!Epic老板:你当6亿用户是摆设?
“扎克伯格花了数年时间试图让Metaverse成为现实,但现在它已被AI取代,并走向科技创意的坟墓。”一篇表达“元宇宙已死”的文章近期在推特上引发热议,而游戏制作公司Epic Games CEO Tim Sweeney的还击更是让这个话题热上加热。 “搞一次在线守…...
阶段小结2022
工作马上一年,对于一年工作能力提升可能逐步在提升,业务能力也在慢慢提升,虽然没有一年前想象的飞起状态,但是刚接触这一行,希望越来越好。 之前每次的遇到的问题其实都会在笔记或者博客中记录,但是没有整体…...

linux0.12-8-11-vsprintf.c
[383页] 1、 这一小节可以不看代码如何实现,因为标准的C库函数; 2、 等自己看完的这本书,有兴趣过来研究研究也是可以的。 8-11 vsprintf.c程序 8-11-1 功能描述 该程序主要包括vsprintf(),用于对参数产生格式化的输出。由于该函数是C函数…...

Node.js 与 WebAssembly
目录 1、简介 2、关键概念 3、生成WebAssembly模块 4、如何使用它 5、与操作系统交互 1、简介 首先,让我们了解为什么WebAssembly是一个很棒的工具,并学会自己使用它。 WebAssembly是一种类似汇编的高性能语言,可以从各种语言编译&…...

OpenCL编程指南-4.4矢量操作符
矢量操作符 如下描述了可用于矢量数据类型或矢量和标量数据类型组合的各类操作符。 算术操作符 算术操作符(加()、减(–)、乘(*)和除(/)),可以作用于内置整数、浮点标量和矢量数…...

索洛模型(二)
索洛模型(二) 文章目录 索洛模型(二)[toc]1 事实2 假设2.1 对生产函数的假设2.2对投入要素的假设 3 索洛模型的动态学3.1 k k k的动态学3.2 平衡增长路径 4 储蓄率变化的影响4.1 对产出的影响4.2 对消费的影响 索罗经济增长模型(Solow growth model)&am…...

【多微电网】基于粒子群优化算法的面向配电网的多微电网协调运行与优化(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

使用Atmel Studio开发Arduino的ATmega328P单片机
摘要:我们知道Arduino开发板常用的芯片是Atmel公司生产的AVR微控制器系列。最常见的是ATmega328P,被广泛用于Arduino Uno开发板。其他常用的AVR芯片包括ATmega2560和ATmega32U4。使用Arduino平台开发AVR的单片机非常方便。Arduino IDE提供了一个非常简洁…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...

学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...

(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...