YOLOX源码之【数据缓存】

这里首先需要了解下装饰器 - 廖雪峰的官方网站的用法,后面会用到。

如果cache=True,在launch前就调用get_dataset,否则launch后再调用get_dataset。

函数get_dataset调用COCODataset类,并赋给self.dataset。COCODataset继承自CacheDataset,CacheDataset继承自Dataset,Dataset继承自torch.utils.data.data.Dataset。

COCODataset在__init__中super().__init__()初始化父类CacheDataset,CacheDataset在__init__中调用self.cache_images进行缓存图片操作,代码如下。

def cache_images(self,num_imgs=None,data_dir=None,cache_dir_name=None,path_filename=None,
):assert num_imgs is not None, "num_imgs must be specified as the size of the dataset"if self.cache_type == "disk":assert (data_dir and cache_dir_name and path_filename) is not None, \"data_dir, cache_name and path_filename must be specified if cache_type is disk"self.path_filename = path_filenamemem = psutil.virtual_memory()  # 获取系统虚拟内存信息mem_required = self.cal_cache_occupy(num_imgs)gb = 1 << 30  # 1 << 30 == 2^30 == (2^10)^3 == 1024^3# 1 << 30将二进制数1左移30位,其余位都为0。2^30的二进制表示是在最高位为1,其余位都为0的二进制数,即10后面跟着30个0。因此1 << 30 == 2^30if self.cache_type == "ram":if mem_required > mem.available:self.cache = Falseelse:logger.info(f"{mem_required / gb:.1f}GB RAM required, "f"{mem.available / gb:.1f}/{mem.total / gb:.1f}GB RAM available, "f"Since the first thing we do is cache, "f"there is no guarantee that the remaining memory space is sufficient")if self.cache and self.imgs is None:if self.cache_type == 'ram':self.imgs = [None] * num_imgslogger.info("You are using cached images in RAM to accelerate training!")else:   # 'disk'if not os.path.exists(self.cache_dir):os.mkdir(self.cache_dir)logger.warning(f"\n*******************************************************************\n"f"You are using cached images in DISK to accelerate training.\n"f"This requires large DISK space.\n"f"Make sure you have {mem_required / gb:.1f} "f"available DISK space for training your dataset.\n"f"*******************************************************************\\n")else:logger.info(f"Found disk cache at {self.cache_dir}")returnlogger.info("Caching images...\n""This might take some time for your dataset")num_threads = min(8, max(1, os.cpu_count() - 1))b = 0load_imgs = ThreadPool(num_threads).imap(partial(self.read_img, use_cache=False),  # 偏函数,固定参数use_cache=False# 这里是partial的一个神奇用法,修改装饰器的参数range(num_imgs))  # 这里load_imgs是一个迭代器pbar = tqdm(enumerate(load_imgs), total=num_imgs)for i, x in pbar:   # x = self.read_img(self, i, use_cache=False)if self.cache_type == 'ram':self.imgs[i] = xelse:   # 'disk'cache_filename = f'{self.path_filename[i].split(".")[0]}.npy'cache_path_filename = os.path.join(self.cache_dir, cache_filename)os.makedirs(os.path.dirname(cache_path_filename), exist_ok=True)np.save(cache_path_filename, x)b += x.nbytespbar.desc = \f'Caching images ({b / gb:.1f}/{mem_required / gb:.1f}GB {self.cache_type})'pbar.close()

缓存有ram和disk两种类型,ram是一次性将训练集中所有图片读取完放到一个列表中赋给self.imgs,disk是读取每张图片并以.npy格式保存到硬盘中。首先通过psutil.virtual_memory()获取系统虚拟内存信息,然后调用self.cal_cache_occupy()计算训练集中所有图片占用内存大小。然后用多线程的方式读取图片。

这里需要特别介绍一下读取图片的操作。首先functools.partial的作用是在原始函数的基础上固定某些参数创建一个新的可调用对象,这个新的可调用对象可以像原始函数一样被调用,但是某些参数已经被预先设置好了。下面是一个例子,在这个例子中,partial(add, 5)创建了一个新的函数add_five,它实际上是add函数的一个版本,只不过把第一个参数固定为5。这样当我们调用add_five(3)时,实际上是调用add(5, 3),所以结果是8。

from functools import partialdef add(x, y):return x + y# 使用partial固定第一个参数
add_five = partial(add, 5)print(add_five(3))  # 输出 8

partial(self.read_img, use_cache=False)调用的self.read_img在COCODataset中实现,并且将参数use_cache固定为False,但是我们看到函数read_img并没有入参use_cache,而装饰器@cache_read_img有入参use_cache,这里是partial的一个特别的用法,即可以改变装饰器的自身的参数。

@cache_read_img(use_cache=True)
# 实际调用的是cache_read_img(use_cache=True)(read_img)(self, index)
def read_img(self, index):return self.load_resized_img(index)

装饰器cache_read_img的实现如下,可以看到当use_cache=True时根据缓存类型从ram或disk中读取图片,当use_cache=False时调用被装饰函数read_img读取图片。这里本身就是在进行缓存图片的操作,图片还没缓存呢当然就不能从缓存中读取图片了。 

def cache_read_img(use_cache=True):def decorator(read_img_fn):"""Decorate the read_img function to cache the imageArgs:read_img_fn: read_img functionuse_cache (bool, optional): For the decorated read_img function,whether to read the image from cache.Defaults to True."""@wraps(read_img_fn)  # 保持被装饰函数read_img_fn的__name__属性不变def wrapper(self, index, use_cache=use_cache):cache = self.cache and use_cacheif cache:if self.cache_type == "ram":img = self.imgs[index]img = copy.deepcopy(img)elif self.cache_type == "disk":img = np.load(os.path.join(self.cache_dir, f"{self.path_filename[index].split('.')[0]}.npy"))else:raise ValueError(f"Unknown cache type: {self.cache_type}")else:img = read_img_fn(self, index)return imgreturn wrapperreturn decorator

至此就完成了缓存图片的操作。

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

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

相关文章

amfori BSCI提供一种公认的方法来识别和补救全球供应链中的风险

amfori BSCI简介 采用共同的行为准则 amfori BSCI提供了一套行为准则&#xff0c;其中包含一系列价值观和原则&#xff0c;可帮助 amfori成员改进自己的政策和实践&#xff0c;例如更新采购合同以负责任地开展业务。这些原则适用于全球所有行业&#xff0c;并符合国际法规&am…

学习1:java 校验注解之 @NotNull、@NotBlank、@NotEmpty学习

NotBlank 这个注解确保字段的值不是null&#xff0c;也不是一个只包含空白字符&#xff08;如空格、制表符、换行符等&#xff09;的字符串。换句话说&#xff0c;它必须至少包含一个非空白字符。 NotEmpty 会检查字段是否不是null且不是空集合、空数组或空字符串。但在字符串…

解决Linux中特殊文件名删除难题

最近在使用rz上传文件时出现中断&#xff0c;导致生成了乱码文件&#xff0c;尝试删除这些文件时遇到各种报错。 在Linux操作系统中&#xff0c;当尝试删除以特殊字符&#xff08;如-&#xff09;开头的文件时&#xff0c;可能会遇到错误信息&#xff0c;提示“invalid option”…

深入理解 Java 泛型工厂方法:类型安全与灵活性的结合

深入理解 Java 泛型工厂方法&#xff1a;类型安全与灵活性的结合 泛型工厂方法是指使用泛型参数来创建对象的静态方法。它可以返回与传入类型参数一致的实例&#xff0c;从而确保类型安全并提高代码的灵活性和重用性。 1. 基本实现 泛型工厂方法通常接受一个 Class 对象作为…

【excel】设置二级可变联动菜单

文章目录 【需求】在一级菜单选定后&#xff0c;二级菜单联动显示一级菜单下的可选项【步骤】step1 制作辅助列1.列转行2.在辅助列中匹配班级成员 step2 名称管理器step3 制作二级下拉菜单step4 消除二级菜单中的空白 【总结】 之前做完了 【excel】设置可变下拉菜单&#xff…

为什么一线大厂都在高薪抢 AI 产品经理?

前言 不知道你是否听过“移动互联网产品经理”这个说法&#xff0c;当移动互联网成为整个互联网行业的基础建设&#xff0c;深入到各行各业&#xff0c;所有产品经理&#xff0c;其实都是移动互联网产品经理。 而近些年&#xff0c;随着 AI 技术逐渐落地和市场认可度的不断提…

公安视频图像信息数据库及GA/T 1400视图库视频监控系统的使用场景

随着科技的快速发展&#xff0c;大数据、人工智能等新技术不断融入各行各业&#xff0c;为各行各业带来了前所未有的变革。在公安领域&#xff0c;GA/T 1400协议公安视频图像信息数据库的应用为视频监控场景提供了强有力的支持&#xff0c;极大地提升了公安工作的效率和准确性。…

C++ XML文件和解析

XML&#xff08;可扩展标记语言&#xff09;是一种用于存储和传输数据的标记语言。它具有自描述性和平台无关性的特点。XML 文档的格式主要由一组嵌套的元素和属性构成&#xff0c;结构清晰&#xff0c;易于理解和解析。 XML 文档的基本格式 一个 XML 文档通常包括以下部分&a…

大模型狂奔不息的300天

大模型行业正如火如荼地发展着&#xff0c;那么&#xff0c;如何解读当前国内大模型行业的发展&#xff1f;谁又可能是大模型时代的超级应用&#xff1f;或许后一个问题的答案&#xff0c;现在还未能揭晓。一起来看看本文关于大模型行业发展的解读和分析。 2023年&#xff0c;没…

一个小时搞定JAVA面向对象(6)——多态

文章目录 多态多态条件下成员的访问特点成员变量成员方法 多态的好处多态的缺点多态中的转型向上转型向下转型类型转换异常 多态 多态必须要子父类继承或者接口实现关系,必须有方法的重写. 定义格式: ​ new对象:父类引用指向子类对象 Fu fu new Zi( )理解为大类型接收了一…

持续总结中!2024年面试必问 20 道 Kafka面试题(六)

上一篇地址&#xff1a;持续总结中&#xff01;2024年面试必问 20 道 Kafka面试题&#xff08;五&#xff09;-CSDN博客 十一、Zookeeper 对于 Kafka 的作用是什么&#xff1f; Apache ZooKeeper是一个开源的分布式协调服务&#xff0c;它为分布式应用提供一致性服务&#xf…

Linux线程 -- 互斥锁 和 条件变量

在多线程编程中&#xff0c;互斥量&#xff08;mutex&#xff09;是用于保护共享资源的同步机制&#xff0c;确保在任一时刻只有一个线程能够访问共享资源。互斥量用于防止竞态条件&#xff08;race conditions&#xff09;&#xff0c;确保数据一致性。 基本概念 互斥量&…

python学习笔记-04

高级数据类型 一组按照顺序排列的值称为序列&#xff0c;python中存在三种内置的序列类型&#xff1a;字符串、列表和元组。序列可以支持索引和切片的操作&#xff0c;第一个索引值为0表示从左向右找&#xff0c;第一个索引值为负数表示从右找。 1.字符串操作 1.1 切片 切片…

不同平台账号究竟要如何运营?新媒体矩阵这样做,不怕没结果!

干货分享 越来越多企业要求做矩阵化运营&#xff0c;众多平台一把抓&#xff0c;那么对于新媒体人来说&#xff0c;可能会有些困惑&#xff0c;都是新媒体平台&#xff0c;他们各有什么特质&#xff1f;今天冲鸭老师就对目前新媒体4大热榜平台进行分析。 抖音 用户特点 年轻…

Flutter 中的 ErrorWidget 小部件:全面指南

Flutter 中的 ErrorWidget 小部件&#xff1a;全面指南 Flutter 是一个由 Google 开发的跨平台 UI 框架&#xff0c;它允许开发者使用 Dart 语言构建高性能、美观的应用。在 Flutter 的丰富组件库中&#xff0c;ErrorWidget 是一个特殊的组件&#xff0c;用于在渲染过程中捕获…

Unity 编辑器扩展 一键替换指定物体下的所有材质球

先看效果 实现方案 1&#xff1a;创建几个用于测试的Cube 2&#xff1a;创建一个脚本 3:编写脚本内容 主要是这部分的逻辑 附上完整代码 using System.Collections; using System.Collections.Generic; using UnityEditor; using UnityEngine;public class Tool {[MenuItem(…

json文件操作和异常处理

目录 按行读取文件readline() 读取大文件: json文件: json文件介绍: json的语法&#xff1a; 读取json文件: json文件写入: 异常&#xff1a; 捕获异常: 捕获指定类型的异常: 捕获未知类型的异常(使用最多): 异常捕获的完整结构: 异常传递: ​编辑抛出异常: 按行…

[HDCTF 2023]Normal_Rsa(e,phi不互素)

题目&#xff1a; from Crypto.Util.number import * mbytes_to_long(bxxxxxx) pgetPrime(256) qgetPrime(256) e74 np*q cpow(m,e,n) print("p",p) print("q",q) print("c",c) #p 8605358291738634342256717476404047103323438810696848883487…

如何评价GPT-4o?【模板】

如何评价GPT-4o? 简介&#xff1a;最近&#xff0c;GPT-4o横空出世。对GPT-4o这一人工智能技术进行评价&#xff0c;包括版本间的对比分析、GPT-4o的技术能力以及个人感受等。 提醒&#xff1a;在发布作品前&#xff0c;请把不需要的内容删掉。 方向一&#xff1a;对比分析 提…

C++字符串转base64编码

上一篇博客中分享的案例里面base64编码的工具函数单独拿出来分享一下&#xff0c;为不想自己写的大佬提供快捷的CV路径 const std::string base64_chars "ABCDEFGHIJKLMNOPQRSTUVWXYZ""abcdefghijklmnopqrstuvwxyz""0123456789/";std::string ba…