mmdetection之dataloader构建


前言

 本篇将介绍mmdetection如何构建dataloader类的。dataloader主要控制数据集的迭代读取。与之配套的是首先实现dataset类。关于dataset类的实现请转mmdetection之dataset类构建


1、总体流程

 在pytorch中,Dataloader实例构建需要以下重要参数(截取dataloader源码)。

    Arguments:
        dataset (Dataset): dataset from which to load the data.
        batch_size (int, optional): how many samples per batch to load
            (default: ``1``).
        shuffle (bool, optional): set to ``True`` to have the data reshuffled
            at every epoch (default: ``False``).
        sampler (Sampler or Iterable, optional): defines the strategy to draw
            samples from the dataset. Can be any ``Iterable`` with ``__len__``
            implemented. If specified, :attr:`shuffle` must not be specified.
        batch_sampler (Sampler or Iterable, optional): like :attr:`sampler`, but
            returns a batch of indices at a time. Mutually exclusive with
            :attr:`batch_size`, :attr:`shuffle`, :attr:`sampler`,
            and :attr:`drop_last`.
        num_workers (int, optional): how many subprocesses to use for data
            loading. ``0`` means that the data will be loaded in the main process.
            (default: ``0``)
        collate_fn (callable, optional): merges a list of samples to form a
            mini-batch of Tensor(s).  Used when using batched loading from a
            map-style dataset.

 简单介绍下各个参数含义:

dataset:就是继承Dataset类的实例;
batch_size: 批次大小
shuffle: True.在开始新的一轮epoch时,是否会重新打乱数据
sampler:迭代器:里面存储着数据集的下标(可能被打乱/顺序)。是迭代器。
batch_samper: 迭代sampler中下标,然后根据下标去dataset中取出batch_size个数据。
collate_fn:将batch个数据整合进一个list,调整宽和高。

 可能上面几个参数定义有点而蒙。没关系,只需记住dataset,sampler,batch_sampler,dataloader均是迭代器即可。至于迭代器:理解为可以被 for … in dataset:使用即可。
 既然Dataloader主要参数有了,那么现在看下mmdetection中如何build_dataloader的。接下来我打算分两部分进行讲解:
 (1)如何实例化一个dataloader对象。如下图所示:mmdetection中主要实现下边四个参数。GroupSamper继承自torch的sampler类。shuffle大多数都是True。而batch_sampler参数mmdetection使用是pytorch中已实现的BatchSampler类。
在这里插入图片描述

 (2)读取一个batch数据流程。

2、实例化dataloader

2.1. GroupSampler类实现

 dataset的实现请转dataset类构建。这里我贴下GroupSampler源码:

class GroupSampler(Sampler):

    def __init__(self, dataset, samples_per_gpu=1):
        assert hasattr(dataset, 'flag')
        self.dataset = dataset
        self.samples_per_gpu = samples_per_gpu
        self.flag = dataset.flag.astype(np.int64)  #
        self.group_sizes = np.bincount(self.flag)  # np.bincount()函数统计 下标01出现的次数。
        self.num_samples = 0
        for i, size in enumerate(self.group_sizes):
            self.num_samples += int(np.ceil(
                size / self.samples_per_gpu)) * self.samples_per_gpu

    def __iter__(self):
        indices = []
        for i, size in enumerate(self.group_sizes):      # self.group_sizes = [942,4096] ;其中942代表长度比例<1的图像数量;
            if size == 0:
                continue
            indice = np.where(self.flag == i)[0]         # 提取出self.flag中等于当前i的下标。 self.flag顺序存储着训练集中所有图像的aspect-ratio
            assert len(indice) == size
            np.random.shuffle(indice)                    # 这里将下标打乱了
            num_extra = int(np.ceil(size / self.samples_per_gpu)
                            ) * self.samples_per_gpu - len(indice)
            indice = np.concatenate(
                [indice, np.random.choice(indice, num_extra)])
            indices.append(indice)
        indices = np.concatenate(indices)                # 合并陈一个list,长度为5011的
        indices = [                                      # 按照batch将list划分:若batch=1,则将列表划分成长度为5011的数组。
            indices[i * self.samples_per_gpu:(i + 1) * self.samples_per_gpu]
            for i in np.random.permutation(
                range(len(indices) // self.samples_per_gpu))
        ]
        indices = np.concatenate(indices)
        indices = indices.astype(np.int64).tolist()
        assert len(indices) == self.num_samples
        return iter(indices)

    def __len__(self):
        return self.num_samples

 其实主要实现了__iter__方法使其成为一个迭代器。而大致思路就是:假如我有一个5000张图像的数据集。那么数据集下标是0~4999.通过np.random.shuffle打乱5000个下标。假如batch是2,则共得到2500对。将这2500对以数组形式存于indices这个list中。最终通过iter(indices)迭代

2.2. BatchSampler类

 这部分mmdetection使用的是pytorch源码。我贴下源码:

class BatchSampler(Sampler[List[int]]):

    def __init__(self, sampler: Sampler[int], batch_size: int, drop_last: bool) -> None:

        self.sampler = sampler
        self.batch_size = batch_size
        self.drop_last = drop_last

    def __iter__(self):
        batch = []
        for idx in self.sampler:
            batch.append(idx)
            if len(batch) == self.batch_size:
                yield batch
                batch = []
        if len(batch) > 0 and not self.drop_last:
            yield batch

    def __len__(self):
        # Can only be called if self.sampler has __len__ implemented
        # We cannot enforce this condition, so we turn off typechecking for the
        # implementation below.
        # Somewhat related: see NOTE [ Lack of Default `__len__` in Python Abstract Base Classes ]
        if self.drop_last:
            return len(self.sampler) // self.batch_size  # type: ignore
        else:
            return (len(self.sampler) + self.batch_size - 1) // self.batch_size  # type: ignore

 从源码可以看出:BatchSampler以sampler初始化的。同时也实现了__iter__方法,每迭代够一个batch,则借助生成器yield batch,即返回一个batch数据。

3、读取一个batch数据流程

 这里我想用张图说明下:文字不易描述:
在这里插入图片描述

总结

 本文主要介绍mmdetection如何通过实现dataset,sampler来构造一个Dataloader,另外,展示了dataloader内部是如何迭代每个批次数据的。

<think>好的,我现在需要帮用户解决关于如何在mmdetection框架中构建dataloader的问题。用户还提到了站内引用,需要结合这些引用来组织回答。首先,我得回忆一下mmdetection的数据加载流程。 根据引用[1],mmdetection通过dataset和sampler来构造Dataloader。我应该先解释这两个组件的角色。然后,引用[2]提到数据加载器可能在实际使用时被构建,特别是在执行器内部。这可能涉及到配置文件和build_dataloader函数的使用。 接下来,用户需要教程和示例代码。我应该分步骤说明,比如配置数据集、定义数据加载器参数、使用build_dataloader函数。示例代码部分要展示如何导入必要的模块,并正确调用函数。 同时,要注意用户提到的LaTeX格式要求,确保行内公式用$...$,独立公式用$$...$$。不过这个问题可能涉及代码较多,数学公式可能较少,但如果有性能分析之类的可能需要数学表达式。 另外,用户要求生成相关问题。我需要考虑用户可能进一步想知道的内容,比如自定义数据集的处理、多GPU训练配置、性能优化方法等。 最后,确保回答结构清晰,分步骤说明,并引用正确的来源。检查是否有遗漏的步骤,比如配置文件的具体参数,或者常见的错误处理。还要验证示例代码的正确性,确保与mmdetection的最新版本兼容。</think>### mmdetection 构建 DataLoader 教程 在mmdetection构建DataLoader主要涉及**数据集配置、采样器定义和数据加载参数设置**三个核心步骤[^1][^2]。以下是具体实现方法: #### 一、配置数据集(Dataset) ```python from mmdet.datasets import build_dataset from mmdet.datasets import CocoDataset # COCO格式数据集配置 dataset_cfg = dict( type='CocoDataset', ann_file='data/coco/annotations/instances_train2017.json', img_prefix='data/coco/train2017/', pipeline=[ dict(type='LoadImageFromFile'), dict(type='LoadAnnotations', with_bbox=True) ] ) dataset = build_dataset(dataset_cfg) ``` #### 二、定义数据加载器参数 ```python dataloader_cfg = dict( batch_size=2, num_workers=4, persistent_workers=True, # 避免重复初始化工作进程 sampler=dict( type='DefaultSampler', # 默认采样器 shuffle=True), # 训练时启用shuffle[^2] dataset=dataset) ``` #### 三、构建DataLoader ```python from mmdet.datasets import build_dataloader dataloader = build_dataloader(dataloader_cfg) ``` #### 四、数据迭代示例 ```python for i, data_batch in enumerate(dataloader): images = data_batch['img'] gt_bboxes = data_batch['gt_bboxes'] # 训练代码... ``` ### 关键组件说明 1. **Pipeline配置**:定义数据增强流程,如`Resize`、`RandomFlip`等操作 2. **Sampler选择**: - `DefaultSampler`:基础采样器 - `GroupSampler`:保证同一批次的图像宽高比相似 - `InfiniteSampler`:支持无限迭代 3. **多GPU配置**:通过设置`samples_per_gpu`和`workers_per_gpu`实现分布式训练 ### 性能优化建议 - 设置`persistent_workers=True`可减少进程重复创建开销 - 使用`pin_memory=True`加速CPU到GPU的数据传输 - 调整`num_workers`数量(建议为GPU数量的4倍)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值