YOLOV8逐步分解(2)_DetectionTrainer类初始化过程

 接上篇文章yolov8逐步分解(1)--默认参数&超参配置文件加载继续讲解。

 1. 默认配置文件加载完成后,创建对象trainer时,需要从默认配置中获取类DetectionTrainer初始化所需的参数args,如下所示

def train(cfg=DEFAULT_CFG, use_python=False):"""Train and optimize YOLO model given training data and device."""model = cfg.model or 'yolov8n.pt'data = cfg.data or 'coco128.yaml'  # or yolo.ClassificationDataset("mnist")device = cfg.device if cfg.device is not None else ''args = dict(model=model, data=data, device=device)if use_python:from ultralytics import YOLOYOLO(model).train(**args)else:trainer = DetectionTrainer(overrides=args)  #初始化训练器trainer.train()

        通过debug可以看到,如下所示,args值为指定模型和数据集

 2. 使用上一步中获取的参数args,创建并初始化一个目标检测训练器trainer

trainer = DetectionTrainer(overrides=args)

3. DetectionTrainer类的初始化代码如下,下面我们将逐步讲解。

def __init__(self, cfg=DEFAULT_CFG, overrides=None, _callbacks=None):"""Initializes the BaseTrainer class.Args:cfg (str, optional): Path to a configuration file. Defaults to DEFAULT_CFG.overrides (dict, optional): Configuration overrides. Defaults to None.对配置文件/训练数据文件参数进行加载,关键信息判断处理解析,保证文件存在,不存在则下载等合法性检测,及值的初始化化操作"""self.args = get_cfg(cfg, overrides)  #将overrides中的配置与cfg中的配置融合,返回SimpleNameSpace类型self.device = select_device(self.args.device, self.args.batch) #选择运行在CPU/GPU还是苹果推出的MPS库上self.check_resume() #判断是否基于之前的断点继续训练,如果是,则加载之前保存的数据参数self.validator = Noneself.model = Noneself.metrics = Noneself.plots = {}init_seeds(self.args.seed + 1 + RANK, deterministic=self.args.deterministic) #初始化随机数# Dirs 创建运行结果保存额目录及文件:创建本次训练的目录/ weights保存目录 /保存运行参数project = self.args.project or Path(SETTINGS['runs_dir']) / self.args.task #project: runs/detectname = self.args.name or f'{self.args.mode}'  #name: 'train'if hasattr(self.args, 'save_dir'):  #判断是否设置保存路径 ,如果没有则根据项目和任务名穿件保存目录self.save_dir = Path(self.args.save_dir)else:self.save_dir = Path(increment_path(Path(project) / name, exist_ok=self.args.exist_ok if RANK in (-1, 0) else True))self.wdir = self.save_dir / 'weights'  # weights dir #runs/detect/train72/weighhtsif RANK in (-1, 0):self.wdir.mkdir(parents=True, exist_ok=True)  # make dirself.args.save_dir = str(self.save_dir)yaml_save(self.save_dir / 'args.yaml', vars(self.args))  # save run args  #保存运行参数self.last, self.best = self.wdir / 'last.pt', self.wdir / 'best.pt'  # checkpoint pathsself.save_period = self.args.save_period   #保存周期#设置 epoch次数 和 batch的大小self.batch_size = self.args.batchself.epochs = self.args.epochsself.start_epoch = 0if RANK == -1:print_args(vars(self.args))# Deviceif self.device.type == 'cpu':self.args.workers = 0  # faster CPU training as time dominated by inference, not dataloading# Model and Dataset 初始化模型文件 和数据集self.model = self.args.model  #yolov8n.pttry:if self.args.task == 'classify':   #分类任务self.data = check_cls_dataset(self.args.data)elif self.args.data.endswith('.yaml') or self.args.task in ('detect', 'segment'):  #检测和分割任务self.data = check_det_dataset(self.args.data) #加载数据yaml文件,进行关键属性值检测,并进行路径转换,确保数据集文件存在,不存在则下载if 'yaml_file' in self.data:self.args.data = self.data['yaml_file']  # for validating 'yolo train data=url.zip' usageexcept Exception as e:raise RuntimeError(emojis(f"Dataset '{clean_url(self.args.data)}' error ❌ {e}")) from eself.trainset, self.testset = self.get_dataset(self.data) #初始化训练集测试集参数 获取路径self.ema = None# Optimization utils initself.lf = None   #损失函数self.scheduler = None  #学习率调整策略# Epoch level metrics 指标self.best_fitness = Noneself.fitness = Noneself.loss = None   #当前损失值self.tloss = None  #总损失值self.loss_names = ['Loss']self.csv = self.save_dir / 'results.csv'self.plot_idx = [0, 1, 2]# Callbacksself.callbacks = _callbacks or callbacks.get_default_callbacks()if RANK in (-1, 0):callbacks.add_integration_callbacks(self)

3.1  self.args = get_cfg(cfg, overrides) 该行主要实现功能为:

        将默认配置参数从Simplenamespace转为字典后与overrides中的参数合并更新,进行一些参数的合法性检测后,再转换为Simplenamespace格式输出。

        overrides该参数主要是用于更新默认加载的配置文件中model和data的值,默认配置中上述值均为None,如下图所示:

更新后的配置如下图所示:

3.2 self.device = select_device(self.args.device, self.args.batch) 功能为:

        选择算法运行在CPU还是GPU上,参数batch用于检测设置的batch数值是否是GPU个数的整数倍,若不是整数倍则报错。

3.3  self.check_resume() :判断是否基于之前的断点继续训练,如果是,则加载之前保存的数据参数,本次默认配置参数该值为False.

3.4 接下来创建运行时的文件保存目录,包括本次训练的权重文件保存目录,并保存训练使用的参数以及checkPoint路径等。

# Dirs 创建运行结果保存目录及文件:创建本次训练的目录/ weights保存目录 /保存运行参数project = self.args.project or Path(SETTINGS['runs_dir']) / self.args.task #project: runs/detectname = self.args.name or f'{self.args.mode}'  #name: 'train'if hasattr(self.args, 'save_dir'):  #判断是否设置保存路径 ,如果没有则根据项目和任务名创建保存目录self.save_dir = Path(self.args.save_dir)else:self.save_dir = Path(increment_path(Path(project) / name, exist_ok=self.args.exist_ok if RANK in (-1, 0) else True))self.wdir = self.save_dir / 'weights'  # weights dir #runs/detect/train72/weighhtsif RANK in (-1, 0):self.wdir.mkdir(parents=True, exist_ok=True)  # make dirself.args.save_dir = str(self.save_dir)yaml_save(self.save_dir / 'args.yaml', vars(self.args))  # save run args  #保存运行参数self.last, self.best = self.wdir / 'last.pt', self.wdir / 'best.pt'  # checkpoint pathsself.save_period = self.args.save_period   #保存周期

3.5 初始化batch/epoch等参数,这个一目了然,不在解释

3.6  初始化数据集(coco128.yaml),步骤如下: 

        3.6.1 检测传入的数据集参数’dataset’是否是yaml结尾文件

        3.6.2 若是路径并且是压缩格式,则下载数据集配置文件

        3.6.3  加载coco128.yaml,通过函数yaml_load()加载

def check_det_dataset(dataset, autodownload=True):"""Download, check and/or unzip dataset if not found locally."""data = check_file(dataset)  #dataset: coco128.yaml #判断文件是否合法,如果不存在在下载,或者从本地搜索# Download (optional)extract_dir = ''if isinstance(data, (str, Path)) and (zipfile.is_zipfile(data) or is_tarfile(data)): #判断数据集是否时zip or tar压缩格式 #new_dir = safe_download(data, dir=DATASETS_DIR, unzip=True, delete=False, curl=False)data = next((DATASETS_DIR / new_dir).rglob('*.yaml'))extract_dir, autodownload = data.parent, False# Read yaml (optional)if isinstance(data, (str, Path)):data = yaml_load(data, append_filename=True)  # dictionary #读取数据集yam文件 simplenamespace格式# Checks 必要参数检测for k in 'train', 'val':if k not in data: #如果数据中既不包含 train也不包含 val,则报错raise SyntaxError(emojis(f"{dataset} '{k}:' key missing ❌.\n'train' and 'val' are required in all data YAMLs."))if 'names' not in data and 'nc' not in data:raise SyntaxError(emojis(f"{dataset} key missing ❌.\n either 'names' or 'nc' are required in all data YAMLs."))if 'names' in data and 'nc' in data and len(data['names']) != data['nc']:raise SyntaxError(emojis(f"{dataset} 'names' length {len(data['names'])} and 'nc: {data['nc']}' must match."))if 'names' not in data: #如果没有names则,用数字代替data['names'] = [f'class_{i}' for i in range(data['nc'])]else:data['nc'] = len(data['names'])data['names'] = check_class_names(data['names']) #检测data['names']是否是dict,以及将key转换为数字# Resolve pathspath = Path(extract_dir or data.get('path') or Path(data.get('yaml_file', '')).parent)  # dataset rootif not path.is_absolute():path = (DATASETS_DIR / path).resolve() #转化为绝对路径data['path'] = path  # download scriptsfor k in 'train', 'val', 'test':  #全部转换为绝对路径if data.get(k):  # prepend pathif isinstance(data[k], str):x = (path / data[k]).resolve()if not x.exists() and data[k].startswith('../'):x = (path / data[k][3:]).resolve()data[k] = str(x)else:data[k] = [str((path / x).resolve()) for x in data[k]]# Parse yamltrain, val, test, s = (data.get(x) for x in ('train', 'val', 'test', 'download'))if val:val = [Path(x).resolve() for x in (val if isinstance(val, list) else [val])]  # val pathif not all(x.exists() for x in val):  #不存在则下载name = clean_url(dataset)  # dataset name with URL auth strippedm = f"\nDataset '{name}' images not found ⚠️, missing paths %s" % [str(x) for x in val if not x.exists()]if s and autodownload:LOGGER.warning(m)else:m += f"\nNote dataset download directory is '{DATASETS_DIR}'. You can update this in '{SETTINGS_YAML}'"raise FileNotFoundError(m)t = time.time()if s.startswith('http') and s.endswith('.zip'):  # URLsafe_download(url=s, dir=DATASETS_DIR, delete=True)r = None  # successelif s.startswith('bash '):  # bash scriptLOGGER.info(f'Running {s} ...')r = os.system(s)else:  # python scriptr = exec(s, {'yaml': data})  # return Nonedt = f'({round(time.time() - t, 1)}s)'s = f"success ✅ {dt}, saved to {colorstr('bold', DATASETS_DIR)}" if r in (0, None) else f'failure {dt} ❌'LOGGER.info(f'Dataset download {s}\n')check_font('Arial.ttf' if is_ascii(data['names']) else 'Arial.Unicode.ttf')  # download fontsreturn data  # dictionary

        其中,data = yaml_load(data, append_filename=True)加载完成后,data内容如下:

注意:’nc’:80 是通过 data['nc'] = len(data['names']) 后添加的。

   3.6.4 将data中的路径全部转换为绝对路径

 for k in 'train', 'val', 'test':  #全部转换为绝对路径if data.get(k):  # prepend pathif isinstance(data[k], str):x = (path / data[k]).resolve()if not x.exists() and data[k].startswith('../'):x = (path / data[k][3:]).resolve()data[k] = str(x)else:data[k] = [str((path / x).resolve()) for x in data[k]]

        转换完成并更新data后,data的内容如下,其中train,val,test等键的值变为了绝对路径:

        3.6.5 获取训练集、测试集、验证集、以及下载路径

train, val, test, s = (data.get(x) for x in ('train', 'val', 'test', 'download'))

        3.6.6 最終返回data,数据类型为字典,完成对coco128.yaml文件的加载解析及校验工作。

3.7  获取训练集和验证集的路径

self.trainset, self.testset = self.get_dataset(self.data) #初始化训练集测试集参数 获取路径

        其中,获取路径方法函数实现过程如下:

def get_dataset(data):"""Get train, val path from data dict if it exists. Returns None if data format is not recognized."""return data['train'], data.get('val') or data.get('test')

3.8 其他学习率、损失函数等都设置为None

        self.ema = None# Optimization utils initself.lf = None   #损失函数self.scheduler = None  #学习率调整策略# Epoch level metrics 指标self.best_fitness = Noneself.fitness = Noneself.loss = None   #当前损失值self.tloss = None  #总损失值self.loss_names = ['Loss']self.csv = self.save_dir / 'results.csv'self.plot_idx = [0, 1, 2]

3.9 设置用于结果展示获取的一些回调函数

        # Callbacksself.callbacks = _callbacks or callbacks.get_default_callbacks()if RANK in (-1, 0):callbacks.add_integration_callbacks(self)

        至此,trainer的初始化过程解析完成。

        总结,本章详细介绍了yolov8训练器trainer的初始化过程,讲解参数的加载替换过程,着重讲解了coco128数据集的加载解析及校验,最后介绍了损失函数学习率的初始化。

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

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

相关文章

python的神奇bug2

今天测试出一个很诡异的bug, 这个错误还真的很难发现 测试1 a [1,10,100] for i in a:print(i)if(i10):a[20,30,-1]一般来说我们在进行迭代时,a这个值时不能改动的,但是现在的问题时如果我不小心给改动了呢,结果如下 也就是说…

基于JSPM的美食推荐管理系统

背景 互联网的迅猛扩张彻底转变了全球各类组织的运营模式。自20世纪90年代起,中国各级政府和企事业单位便开始探索运用网络系统来处理管理事务。然而,早期的网络覆盖不广、用户接受度不高、相关网络法规不健全以及技术发展不成熟等因素,都曾…

达梦数据库新手上路排坑

数据库安装 这个没啥说的,按照官网教程操作,我使用的是docker进行安装 下载文件docker文件 官方下载地址- load -i dm8****.tar (注意修改为当前下载的文件)达梦官方文档注意修改为当前版本 docker run -d -p 5236:5236 --name dm8 --privilegedtrue -…

HarmonyOS 应用开发之PageAbility组件

PageAbility组件概述 PageAbility是包含UI、提供展示UI能力的应用组件,主要用于与用户交互。 开发者通过DevEco Studio开发平台创建PageAbility时,DevEco Studio会自动创建相关模板代码。PageAbility相关能力通过单独的featureAbility实现,…

STL —— vector(1)

博主首页: 有趣的中国人 专栏首页: C专栏 本篇文章主要讲解vector使用的相关内容 1. vector简介 vector 是 C 标准库中的一个容器类模板,它提供了动态数组的功能,可以方便地管理和操作元素的集合。下面是关于 vector 的一些基本信…

基于单片机智能家居控制系统设计

**单片机设计介绍,基于单片机智能家居控制系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的智能家居控制系统设计旨在实现家居设备的自动化控制和智能化管理,提高家庭生活的便利性和舒…

大数据做「AI大模型」数据清洗调优基础篇

关于本文 近期一直在协助做AI大模型数据清洗调优的工作,主要就是使用大数据计算引擎Spark做一些原始数据的清洗工作,整体数据量大约6PB-8PB之间,那么对于整个大数据量的处理性能将是一个重大的挑战,关于具体的调优参数配置项暂时不…

【论文阅读+复现】AniPortrait: Audio-Driven Synthesis of Photorealistic Portrait Animation

AniPortrait:音频驱动的逼真肖像动画合成。 code:Zejun-Yang/AniPortrait: AniPortrait: Audio-Driven Synthesis of Photorealistic Portrait Animation (github.com) paper:[2403.17694] AniPortrait: Audio-Driven Synthesis of Photoreal…

Soot入门学习笔记

Soot 适合参考的文档和教程如下: 北京大学软件分析技术 南京大学软件分析 Tutorials for soot McGill University 198:515 (vt.edu) 比较好的笔记资料: 南京大学《软件分析》课程笔记 比较好的入门作业或者案例: CSCE710 Assignmen…

产品说明书二维码生成的优势:数字化时代的智能选择

随着二维码技术的不断发展,越来越多的企业开始选择使用二维码来展示产品使用说明,以取代传统的纸质说明书。这一趋势不仅符合数字化时代的潮流,更为消费者提供了更便捷、更智能的产品使用体验。以下是产品说明书二维码生成的优势:…

C#_泛型_委托

文章目录 泛型泛型的使用泛型的约束委托委托的实例化多播委托委托的调用内置委托类型委托练习泛型委托Lambda表达式(进阶)上期习题答案本期习题 泛型 泛型(Generic) 是一种规范,它允许我们使用占位符来定义类和方法,编译器会在编…

Linux进程概念(下)

1. 进程的状态 为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在Linux内核里,进程有时候也叫做任务)。 下面的状态在kernel源代码里定义: /* * The task state array is…

数对 离散化BIT

先把公式变个形&#xff0c;然后直接BIT 枚举右端点查询左端点累加答案 离散化好题&#xff0c;注意BIT写的时候右端点的范围是离散化区间的大小 #include<bits/stdc.h> using namespace std; #define int long long using ll long long; using pii pair<int,int&…

国内好用的chatGPT和AI绘图工具

分享一个比较好用的AI 分享一个比较好用的AI&#xff0c;只是需要开通会员&#xff0c;目前官网的价格是&#xff1a;298&#xff0c;开通之后可以使用chatgpt4、AI绘画、图片融合等等&#xff01;不开通的话是可以免费使用15次的&#xff0c;下面是一些介绍图片&#xff01;链…

UE5数字孪生系列笔记(三)

C创建Pawn类玩家 创建一个GameMode蓝图用来加载我们自定义的游戏Mode新建一个Pawn的C&#xff0c;MyCharacter类作为玩家&#xff0c;新建一个相机组件与相机臂组件&#xff0c;box组件作为根组件 // Fill out your copyright notice in the Description page of Project Set…

Solidity Uniswap V2 Router swapTokensForExactTokens

最初的router合约实现了许多不同的交换方式。我们不会实现所有的方式&#xff0c;但我想向大家展示如何实现倒置交换&#xff1a;用未知量的输入Token交换精确量的输出代币。这是一个有趣的用例&#xff0c;可能并不常用&#xff0c;但仍有可能实现。 GitHub - XuHugo/solidit…

Golang实战:深入hash/crc64标准库的应用与技巧

Golang实战&#xff1a;深入hash/crc64标准库的应用与技巧 引言hash/crc64简介基本原理核心功能 环境准备安装Golang创建一个新的Golang项目引入hash/crc64包测试环境配置 hash/crc64的基本使用计算字符串的CRC64校验和计算文件的CRC64校验和 高级技巧与应用数据流和分块处理网…

Jmeter 配置说明之线程组

一、线程组介绍&#xff1a; 线程组元件是任何一个测试计划的开始点。在一个测试计划中的所有元件都必须在某个线程组下。所有的任务都是基于线程组&#xff1a; 通俗理解&#xff1a; 线程组&#xff1a;就是一个线程组&#xff0c;里面有若干个请求&#xff1b; 线程&am…

vue3.0 + ts + eslint报错:error Parsing error: ‘>‘ expected

eslint报错 这里加上对应的 eslint配置即可&#xff1a; parser: vue-eslint-parser, parserOptions: {parser: "typescript-eslint/parser",ecmaVersion: 2020,sourceType: module, }具体如下&#xff1a; module.exports {parser: vue-eslint-parser,parserOpti…

​马来语翻译中文去哪比较好?

据了解&#xff0c;马来语是马来西亚、文莱的官方语言&#xff0c;也是新加坡的官方语言之一&#xff0c;马来语跟印尼语是同一种语言&#xff0c;它在整个东南亚有着极大的影响力。如今在国内市场上&#xff0c;马来语翻译的需求也是供不应求&#xff0c;那么&#xff0c;如何…