《南溪的目标检测学习笔记》——数据载入篇(torch)

1 介绍

在这里插入图片描述

在PyTorch中定义自己的数据集类,需要继承父类Dataset
自定义的Dataset类需要实现以下三个函数:
init():用来实现初始化的操作;
__len__():用来返回数据集的样本数目;
__getitem__(): to support the indexing such that dataset[i] can be used to get i-th sample;

1.1 设计理念

一、使用GPU进行数据预处理:gpu
二、原生Torch数据预处理:torchvision.transforms
三、使用torch.utils.data.Dataset避免使用 list | dict 类型作为成员变量

2 读取图像(read images)

我们使用turbojpeg来读取图像,

jpeg = TurboJPEG()
with open(image_path, 'rb') as in_file:
    image = jpeg.decode(in_file.read())

2.1 使用TurboJPEG读取图像出现“OSError: Not a JPEG file: starts with 0x89 0x50”错误

网上资料认为:“‘OSError: Not a JPEG file: starts with 0x89 0x50’错误可能是因为不正确的转换格式更改了后缀名导致的”

为了解决这个问题,我们需要使用turbojpeg来遍历读取一遍COCO数据集的图像文件,找出这种异常的图像文件;

3 数据载入(data loading)

Number of workers

Note
将num_workers设成CPU的核心数可以极大地提高训练速度,(我在学习DeepLabV3+试了一下,加速比大概在4倍左右!)

获得CPU的物理核心数:

import psutil
psutil.cpu_count(False)

这里我们就设置为psutil.cpu_count(False)-2,(为系统进程和UI进程留出2个CPU核心)。

Torch loading

data_loader = torch.utils.data.DataLoader(
	self.train_set,
    batch_size=batch_size,
    shuffle=True,
    # shuffle the samples, to prevent training order pattern
    num_workers=num_workers,
    collate_fn=self.train_set.collate_fn,
    pin_memory=True,  
    # 将数据固定在内存中,可以跟`.cuda(non_blocking=True)`联合使用来并行传输数据
    drop_last=True)

Note
pin_memory设置为True可以加快多进程方式的数据读取;
在实现时,可以参考[torch-MemoryPinning]判断读取的tensor是否处于pinned状态;

Dali loading

我们使用nvidia.dali来直接将数据载入GPU,载入操作的写作参考《COCO Reader — NVIDIA DALI》
数据集载入代码:

pipe = Pipeline(batch_size=batch_size, num_threads=4, device_id=0)
with pipe:
    jpegs, bboxes, labels, polygons, vertices = fn.readers.coco(
        file_root=file_root,  # folder of COCO `*.jpg` images
        annotations_file=annotations_file,
        polygon_masks=True,
        ratio=True)
    images = fn.decoders.image(jpegs, device="mixed", output_type=types.RGB)
    pipe.set_outputs(images, bboxes, labels, polygons, vertices)

4 数据预处理(image preprocess)

数据预处理也是数据读取中很重要的内容,对于目标检测来说,十分重要的就是图像预处理,比如:可以使用resize方法对图像下采样来降低输入尺寸,从而减小模型的显存占用,提高batch-size;
写作时,image和label的变换要写在一起,因为两者的变换相伴相生的,请想象一下检测框在图像上显示的效果图就可以知道;

4.0 Philosophy

  • 使用仿射矩阵来计算坐标变换

关于函数常见变换的示意图

在这里插入图片描述(图片来自阿-岳同学_bilibili

4.1 Normalize Image

Demo: ffcv_image_pipeline_NormalizeImage

5 样本增广(data augmentation)

我们需要在dali中实现样本增广,dali在API也是可以支持 conditionally augment images ,请参考《Conditional-Like Execution and Masking — NVIDIA DALI documentation》
我感觉dali在实现内部的增广计算时可能时使用了一种类似于静态图(graph)的构建形式,所以无法直接支持条件操作( DALI does not support conditional or partial execution),这里我们会参考文档来实现类似于if语句的样本增广;

6 样本增广(data augmentation)

关于如何 debug dali,请参考dali文档《Pipeline Debug Mode — NVIDIA DALI documentation》
示例代码:

7 学习笔记

7.1 FFCV: 预加载文件十分庞大(二次测试)

安装ffcv:

conda install cupy pkg-config compilers libjpeg-turbo opencv -c conda-forge
# 注意:一定要先安装上面的依赖库,然后安装ffcv,否则ffcv因为缺少依赖则无法正常安装
pip install ffcv

参数说明:
-c: CHANNELNAME, 指定安装的conda-channel。
安装过于麻烦,使用体验较差!
FFCV的加速主要是针对数据加载和数据增广;
对于target的数据预加载,ffcv要求target的数据类型是固定的,这对于目标检测任务简直是不可能的,目标检测任务的实例数量是不确定的,怎么可能让数据类型是固定形状的呢?!

生成数据集字节文件:writer.from_indexed_dataset(data_set)

使用ffcv第一步需要生成数据集字节文件,

writer = DatasetWriter(f'/***/***/tmp/coco_{name}.beton', {
        # Tune options to optimize dataset size, throughput at train-time
        'image': RGBImageField(max_resolution=max_resolution),
        'label': IntField()
    })
writer.from_indexed_dataset(train_set)

参数说明:
max_resolution:用来设置读取的最大尺寸,which will resize images to have maximum side length equal to this value.

问题备忘

安装时出现“ffcv 0.0.* depends on webdataset”的问题

【提示信息如下】:

ERROR: Cannot install ffcv0.0.1, ffcv0.0.2 and ffcv==0.0.3 because these package versions have conflicting dependencies.

The conflict is caused by:
ffcv 0.0.3 depends on webdataset
ffcv 0.0.2 depends on webdataset
ffcv 0.0.1 depends on webdataset

To fix this you could try to:

  1. loosen the range of package versions you’ve specified
  2. remove package versions to allow pip attempt to solve the dependency conflict

ERROR: ResolutionImpossible: for help visit https://pip.pypa.io/en/latest/user_guide/#fixing-conflicting-dependencies

这是因为ffcv依赖于webdataset,于是进行安装

conda install webdataset
FFCV使用torchvision的标准格式(eg.torchvision.datasets.CIFAR10)作为输入

对于torchvision.datasets.CIFAR10,其数据格式为

(<PIL.Image.Image>, int)
RGBImageField.max_resolution的采样操作是否会保持图像的长宽比?Yes

RGBImageField.max_resolution的采样操作会保持图像的长宽比,采样器resizer()的代码如下:
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值