sampler采样器记录

深度学习数据标注完成后,需要构建dataset并送入dataloader整合好以后送入模型去学习,而数据在进入dataloader后会有一个采样器sampler进行数据的index的筛选,本文主要记录常见的几种sampler:

  • mmdetection中的Groupsampler
  • 数据不均衡–Imbalanced Dataset Sampler
  • 数据不均衡–Weighted Random Sampler
  • Random Sampler
  • Sequential Sampler
  • Subset Random Sampler

1、sampler

sampler是torch中的基础函数,只有定义没有实现,是实现其他不同采样器需要继承的基类,该基类只有一个初始化函数、一个迭代器__iter__函数以及一个统计数据长度的__len__函数,在实现其他采样器的时候,必须要实现的是iter函数以及len函数,其中iter不断的返回数据的index,以获取相应的样本。

class Sampler(Generic[T_co]):
    def __init__(self, data_source: Optional[Sized]) -> None:
        pass
        
    def __iter__(self) -> Iterator[T_co]:
        raise NotImplementedError
        
    def __len__(self) -> int:
    	pass

2、Groupsampler

mmdetection实现很多数据预处理方式,并最终在collate将不同size的图片通过pad统一到相同大小。减少pad面积,可以节约算力,因此商汤实现了自己采样器Groupsampler,将未处理的图片根据ratio(长和宽的比例)分为两组,ratio大于1的分为一组,ratio小于1的分为另一组。要求每次dataloader迭代一次,返回的batch都为同一组!这样相似ratio图片的输入可以有效减少pad面积。
其实现的源码如下:

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)  
        # flag标志由dataset在初始化时确定,详见customdataset
        # flag只有两个取值,根据ratio是否大于1,分为两组

        self.group_sizes = np.bincount(self.flag)  # 对每组的数量进行计数,详见bincount的使用方法
        self.num_samples = 0 # 作为__len__的返回值
        
        for i, size in enumerate(self.group_sizes):
            self.num_samples += int(np.ceil(size / self.samples_per_gpu)) * self.samples_per_gpu
        # group_size不一定能确保被samples_per_gpu整除,因此需要向上取整
        # 比如分组0的数量是100个,分组1的数量是200个,samples_per_gpu为3
        # 那么num_samples = 102+201 = 303

    def __iter__(self): # 返回迭代器,每次迭代返回一个整数索引
        indices = []
        for i, size in enumerate(self.group_sizes):
            if size == 0:
                continue
            indice = np.where(self.flag == i)[0] # 获得同组的图片下标
            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)
        # 还是以"分组0的数量是100个,分组1的数量是200个,samples_per_gpu为3"举例,num_samples = 102+201 = 303        
        # 102大于100,201大于200,所以我们需要还额外增加下标
        # 最后得到303个下标,其中前102个是分组0,后201个是分组1,确保每samples_per_gpu都是同一ratio

        indices = np.concatenate(indices)
       
        indices = [
            indices[i 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI小花猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值