网站源码安装,推广营销软件,济南商城网站制作,简单公司网站1 问题 探索DataLoader的属性#xff0c;方法 Vscode中图标含意 list 与 iterator 的区别#xff0c;尤其yield的用法 2 方法 知乎搜索DataLoader的属性#xff0c;方法 pytorch基础的dataloader类是 from torch.utils.data.dataloader import Dataloader 其主要的参数如下方法 Vscode中图标含意 list 与 iterator 的区别尤其yield的用法 2 方法 知乎搜索DataLoader的属性方法 pytorch基础的dataloader类是 from torch.utils.data.dataloader import Dataloader 其主要的参数如下 datasets、batch size、shuffle、sampler、batch_sampler、num_workers、collate_fn、pin_memory、drop_last ... 1datasets 这可以算是dataloader最重要的参数从本质上讲这是一个数据集映射器DatasetMapper这里借用了d2的概念所谓数据集映射器就是将数据集dataset以及其标注文件annotations从原始的数据文件中进行提取并转换为网络所需要的输入数据的格式。这一步重要且繁琐但是定义数据集dataset整体的结构还是固定的。 定义数据集dataset类的基本结构如下 class mydataset(Dataset):# 这里可以继承torch的数据集类进行覆写也可以不继承直接自己去定义 def __init__(): #定义映射数据集所需要的一些基本的属性例如数据样本的文件目录数据的格式等等 #如果是映射coco格式的数据集则会使用pycocotools的COCO类进行数据提取的预定义 ... def __len__():#这里一般返回的是数据集的长度就是数据集样本的数量 ... def __getitem__(): #这里就是数据集映射功能的核心函数dataloader就是通过它来对数据集的样本进行提取映射为所需要的格式 #当然在进行数据映射的时候也可以在这个方法中添加一些数据增强的功能这都是无限制的。 ... # 在功能上 __getitem__ __iter__ __next__ 所以定义的dataset数据集通常其实例对象本身也是一个迭代器 #这里注意区分 迭代器、可迭代对象、生成器3者之间的联系与区别 #可迭代对象任何一个实现了__iter__方法的对象都是可迭代对象 #迭代器任何一个同时实现了__iter__ 与 __next__ 方法的对象都是一个迭代器 #生成器任何一个同时实现了__iter__ 与 __next__ 方法的对象并且在迭代过程中本身能够自动改变迭代值则这种对象都是一个生成器 生成器是一种特殊的迭代器生成器的例子建议参看torch.utils.data.samplers 中的BatchSampler -- 任何具有yield关键字的函数都可以视为一种生成器调用函数返回的是一个生成器对象对该对象采用next()方法才会调用该生成器函数 关于dataset类定义的例子很多建议大家可以看看yolox中关于dataset的定义进行参考在很多情况下我们需要针对特定任务进行数据预处理而这项工作大部分都是在dataset中定义完成的有时因为涉及到的数据预处理任务比较多可能会将dataset的定义分为两个部分使得整个程序看上去不会那么的臃肿一个是Mapper 一个是augmentation这两个部分对数据处理进行了明确的分工一个用于格式转换映射一个用于数据预处理增强。 2batch_size 这个很好理解了就是用于提取数据的批量大小。 3shuffle 这个也很好理解提取数据的过程设置是随机还是按顺序提取若是随机则为T否则为F。实际上shuffle参数的设置是调用了torch中固有sampler如果设置为T则dataloader会自动调用RandomSampler。 4sampler / BatchSampler ---- 采样器 / 批量采样器 采样器是数据处理中的一个比较特别的部分在目前大部分的情况下我们都是使用的是torch内部固定的采样器来实现对数据的采样但是也有少数的情况下由于一些数据本身的一些原因我们需要对对采样器进行继承覆写--就是自定义如果采样器是自定义的话则shuffle必须为F --- 都自定义了就不要与框架实现的采样器冲突了。关于采样器自定义的格式如下以BatchSampler为例 class sampler(torch.utils.data.sampler):----- 一般这里要继承 torch 采样器类 并对相关的方法进行自定义重写 def __init__(self, data_source): super().__init__(): ... def __iter__(self)- iterator[int] 或者是 Iterator[list[int]] :用于返回所采样数据 在数据集中的索引idx ... # 这里的__iter__方法一般实现的是一个生成器用yield关键字进行返回值 #实现在迭代过程中动态改变采样数据的索引idx---就是改变返回数据的索引idx def __len__(self)- int: 实现的是采样器 在整个数据集的采样次数 这里的采样次数都是跟batch_size有关 总采样次数len 数据集总样本数 / 采样的batch_size if self.drop_last: return len(self.sampler) // self.batch_size # type: ignore[arg-type] else: return (len(self.sampler) self.batch_size - 1) // self.batch_size # type: ignore[arg-type] ... def xxx():----- 一般这里是对上述的3个基本的方法 进行补充说明 写一些补充上述3个基本的方法的一些功能或者扩展 ... # 比如可以添加一些多尺度训练的功能或者是其他对与采集样本的一些功能这个就比较随机了自己定义即可。 实现采样器必须得有__init__, __iter__, __len__方法。 由于BatchSampler中对数据采样的方式以及batch的大小drop_last的规定已经作了一些说明和定义因此如果自定义了一个BatchSampler就不需要batch size、shuffle、sampler、drop_last等参数了 ---- 原则就是自定义的功能不要与dataloader中调用的框架的固有功能冲突。 5num_workers ---- 子进程数量这个在分布式的训练中要特别注意进程的数量以及GPU数量word—size的把控和分配。一般而言。子进程数量越多dataloader的执行的效率就越高但是也越耗cpu。 6pin_memory -- 锁页内存主机的内存分为 锁页 和 不锁页 两种内存因为cuda只接受 锁页内存 的传入因此在创建DataLoader时设置pin_memoryTrue则意味着生成的Tensor数据最开始就是属于内存中的锁页内存这样将内存的Tensor转义到GPU的显存就会更快一些----但是缺点是对于服务器内存的要求比较高。 7drop_last --- 这个主要用于设置在批量提取数据时是否要将“不能整除的”最后一部分达不到小批量数目的数据扔掉--不参加训练默认为F你也可以设置为T。 (8) collate_fn ---- 封装器。 dataloader通过其定义的sampler返回采样的批量的数据样本索引idx对定义的dataset根据这些索引idx进行采样并预处理数据。这样的话dataloader批量迭代数据的结果可能就会包含一个批量batch-size中所有样本的结果例如batchsize设置为4则dataloader就会返回数据集dataset中采样的4个样本的结果而collate_fn 的作用就是要对这些一个batch的迭代结果进行封装使其整合为神经网络所需要的输入形式-----举个例子就是从batchsize个c,h,w转化为大家最熟悉的b,c,h,w----- 因此很明显collate_fn的作用就是为了对dataloader处理的批量输出进行封装整合转化为网络所需要的输入形式。这项功能既可以自定义也可以使用默认的框架功能。不过对于不同的框架不同的环境和任务很多情况下这个都是自定义的定义的方法就是一个function也不需要专门搞一个类的形式来定义它除非是大型的工程需要用到很多种封装形式其基本的定义的格式如下 def collate_fn(batch): # 输入为dataloader在迭代过程中产生的 批量处理后的 数据样本 --- 例如batchsize个 list / tuple / dict # 每个list/tuple/dict 都是dataloader处理后的一个batch中的单个样本的结果 ... # 返回为经处理整合之后的批量的数据样本并作为dataloader最终的迭代输出结果 -- 例如一个 list / tuple / dict 当然如果不用这个封装功能直接忽略该参数也是可以的最后dataloader会使用其默认的collate_fn并返回一个batchsize的结果 ---- 返回的结果来源于dataset中的__getitem__返回的结果。 百度Vscode中图标含意 橙色树状结构类 紫色立方体方法 长方体变量 局部变量 成员变量 命名空间。 属性 。事件 百度list 与 iterator 的区别 1、返回的类型不同list()返回Listiterate()返回Iterator 2、获取方式不同list会一次性将数据库中的信息全部查询出iterate会先把所有数据的id查询出来然后真正要遍历某个对象的时候先到缓存中查找如果找不到以id为条件再发送一条sql到数据库这样如果缓存中没有数据则查询数据库的次数为n1 3、iterate会查询2级缓存list只会查询一级缓存 4、list中返回的List中每个对象都是原本的对象iterate中返回的对象是代理对象。debug可以发现 百度yield的用法 1 什么是yield函数 Python中yield函数是一个生成器(generator),可用于迭代在函数中yield类似于return不同的是yield返回一个return的值并且记住这个返回值的位置下次迭代就从记住的这个位置开始并且下一次迭代时从上一次迭代遇到的yield后面的代码开始执行。 2 yield函数的特点及用法。 yield函数的优点在于它可迭代但又不直接生成返回值如果采用return来返回值就会直接生成返回值如果返回的值或者迭代的数据太大都会使得内存消耗过大yield函数就会很好的减少内存的消耗但是它只可读取一次。带有yield的函数不仅仅可以用于for循环还可以用于函数的参数例如 #用于for循环def yields(n): print(yield用法:) while n10: n1 yield n return passcyields(0)print(next(c))print(next(c))print(next(c))输出123#用于函数的参数def a(): print(aaa) p yield 123 print(bbb) k yield 234r a()print(next(r))输出aaa123 思考一下如果将用于函数参数的yield再增加一个输出next()会发生什么情况呢 def a(): print(aaa) p yield 123 print(bbb) k yield 234r a()print(next(r))print(next(r))输出aaa123bbb234 由以上代码以及运行结果不难发现每一个next返回值都会在执行到yield函数后暂停生成下一次next返回值则会继续从上一个暂停的位置执行这也是yield函数的特点与用法。 3 send()与next()用法的异同。 next()函数可以不断打印yield生成器的值 send()函数特别之处在于它可以携带参数并修改上一个表达式的值同时用法也与next()有很多相同之处 3.1相同点 相同点在于当send()所携带的参数为None(即未携带任何参数)时用法与next()一模一样都仅仅是来打印yield生成器的值。 3.2 不同点 不同点在于当send()所携带的参数时就会将所带参数赋值给上一个表达式实例 def a(): print(send():) i yield 123 print(i) if i234: print(send传入的参数为234) k yield 345 print(k)ra()next(r)r.send(234)输出send()234Send传入的参数为234 分析首先执行next(r)当第一次遇见yield跳出输出send()然后执行r.send(234)send()直接将234参数传给i中并从yield位置继续执行输出i值为234然后输出if条件语句当执行到下一个yield时也就是kyield 345时跳出。 注意yield的第一次执行一定为next(r)或者r.send(None)。 3 结语 了解了Dataloader 其主要的参数有助于我更好地理解和使用这个类从而解决图像基本信息问题。 Vscode中图标含意有助与我在日后的写代码的过程中快速的选择自己想要的函数。 list 与 iterator 的区别yield的用法。有助于在今后代码的迭代选择时应需求选择。