PaddleClas icon indicating copy to clipboard operation
PaddleClas copied to clipboard

如何构造一个分布式加权采样器

Open xywlpo opened this issue 2 years ago • 12 comments

您好,请问如何构造一个分布式的加权采样器,就是采样基于样本的权重,例如使用WeightedRandomSampler的效果,然后数据要支持分布式的训练DistributedBatchSampler,请问应该如何构造?

非常感谢您的回复

xywlpo avatar May 31 '22 17:05 xywlpo

  1. 新建文件PaddleClas/ppcls/data/dataloader/WeightedRandomSampler.py
  2. 在该文件中写一个叫WeightedRandomSampler的类,并从paddle.io.DistributedBatchSampler继承过来。
  3. 重写__init____iter__方法,写成你需要的分布式加权采样。
  4. 写好后在PaddleClas/ppcls/data/__init__.py中import你写的类,就可以开始使用了

HydrogenSulfate avatar Jun 02 '22 07:06 HydrogenSulfate

好的,谢谢,请问您这边有写好的demo吗?

xywlpo avatar Jun 02 '22 10:06 xywlpo

好的,谢谢,请问您这边有写好的demo吗?

PaddleClas/ppcls/data/dataloader/pk_sampler.py

HydrogenSulfate avatar Jun 02 '22 10:06 HydrogenSulfate

好的,谢谢,请问您这边有写好的demo吗?

PaddleClas/ppcls/data/dataloader/pk_sampler.py

好的,多谢

xywlpo avatar Jun 02 '22 12:06 xywlpo

好的,谢谢,请问您这边有写好的demo吗?

PaddleClas/ppcls/data/dataloader/pk_sampler.py

您好,我已看过pk_sampler.py这个脚本,下面的地方有些不太明白,就是下图zhon中画红框的地方,为何要这么写?非常感谢您的帮助 image

xywlpo avatar Jun 04 '22 06:06 xywlpo

确保程序产生合法的batch_index后返回结果

HydrogenSulfate avatar Jun 05 '22 14:06 HydrogenSulfate

我自己写了一下,非分布式可以跑通,不确定是否能实现分布式的要求,麻烦帮我看下:

`class DistributedWeightBatchSampler(DistributedBatchSampler):

def __init__(self,
             dataset,
             batch_size,
             shuffle=True,
             drop_last=True):
    super().__init__(\
        dataset, batch_size, shuffle=shuffle, drop_last=drop_last)

    assert hasattr(self.dataset, "labels"), \
        "Dataset must have labels attribute."
    
    self.label_dict = {}
    categories = len(set(self.dataset.labels))
    for i in range(categories):
        self.label_dict[i] = 0

    for label in self.dataset.labels:
        self.label_dict[label] += 1
    self.label_index = [i for i in range(len(self.dataset.labels))]

    sample_nums = len(self.dataset.labels)
    self.weights = [1.0 / (1.0 * self.label_dict[label] / sample_nums) for label in self.dataset.labels]
    logging.info('head categories is {}, weights is {}'.format(\
        categories, self.weights))

    self.weights = self.weights / np.array(self.weights).sum(axis=-1)

def __iter__(self):
    batch_index = []
    batch_index = np.random.choice(
        self.label_index,
        size=self.batch_size,
        replace=False,
        p=self.weights)
    if not self.drop_last or len(batch_index) == self.batch_size:
        yield batch_index`

然后我想问下,paddle的数据分布式大概是如何实现的?

xywlpo avatar Jun 06 '22 08:06 xywlpo

然后我想问下,paddle的数据分布式大概是如何实现的?

你好,这个问题麻烦在paddle的主repo下提issue: https://github.com/PaddlePaddle/Paddle

weisy11 avatar Jun 06 '22 09:06 weisy11

我自己写了一下,非分布式可以跑通,不确定是否能实现分布式的要求,麻烦帮我看下:

请问是否有运行分布式的环境呢?理论上来说,只要单机多卡可以跑通,分布式就没问题。

weisy11 avatar Jun 06 '22 09:06 weisy11

然后我想问下,paddle的数据分布式大概是如何实现的?

你好,这个问题麻烦在paddle的主repo下提issue: https://github.com/PaddlePaddle/Paddle

好的,谢谢

xywlpo avatar Jun 06 '22 12:06 xywlpo

我自己写了一下,非分布式可以跑通,不确定是否能实现分布式的要求,麻烦帮我看下:

请问是否有运行分布式的环境呢?理论上来说,只要单机多卡可以跑通,分布式就没问题。

好的,明白了,我确认下:在 iter 的实现里,是不是不需要考虑分布式的问题,只要保证能正常产生batch的数据索引就行是吧?

xywlpo avatar Jun 06 '22 12:06 xywlpo

我自己写了一下,非分布式可以跑通,不确定是否能实现分布式的要求,麻烦帮我看下:

请问是否有运行分布式的环境呢?理论上来说,只要单机多卡可以跑通,分布式就没问题。

好的,明白了,我确认下:在 iter 的实现里,是不是不需要考虑分布式的问题,只要保证能正常产生batch的数据索引就行是吧?

看具体采样器的功能,如果是最普通的distributedsampler,那可能需要考虑每张卡上的数据差异,如果是PKSampler,由于是按照ID采样,因此不需要考虑每张卡上的数据差异

HydrogenSulfate avatar Jul 04 '22 07:07 HydrogenSulfate