Neural network Pytork-如何使用weightedrandomsampler进行欠采样

Neural network Pytork-如何使用weightedrandomsampler进行欠采样,neural-network,pytorch,conv-neural-network,imbalanced-data,cnn,Neural Network,Pytorch,Conv Neural Network,Imbalanced Data,Cnn,我有一个不平衡的数据集,希望对代表性过高的类进行采样不足。我该怎么做呢。我想使用加权随机抽样器,但我也愿意接受其他建议 到目前为止,我假设我的代码必须像下面这样结构化。但是我不知道怎么做 列车组=数据集。ImageFolderpath\u列车,变换=变换 ... sampler=data.WeightedRandomSamplerweights=…,num_samples=…,replacement=。。。 ... trainloader=data.DataLoadertrainset,bat

我有一个不平衡的数据集,希望对代表性过高的类进行采样不足。我该怎么做呢。我想使用加权随机抽样器,但我也愿意接受其他建议

到目前为止,我假设我的代码必须像下面这样结构化。但是我不知道怎么做

列车组=数据集。ImageFolderpath\u列车,变换=变换 ... sampler=data.WeightedRandomSamplerweights=…,num_samples=…,replacement=。。。 ... trainloader=data.DataLoadertrainset,batchsize=batchsize,sampler=sampler


我希望有人能帮忙。非常感谢

据我所知,pytorch WeightedRandomSampler“weights”参数与numpy.random.choice“p”参数有些相似,后者是随机选择样本的概率。Pytorch使用权重代替随机抽样训练示例,它们在文档中声明权重不必和1相加,所以这就是我的意思,它与numpy的随机选择不完全一样。重量越重,样品被取样的可能性就越大

当您具有replacement=True时,这意味着可以多次绘制训练示例,这意味着您可以在训练集中拥有训练示例的副本,用于训练模型;过采样。此外,如果与其他训练样本权重相比,权重较低,则情况正好相反,这意味着这些样本被随机抽样的几率较低;欠采样

我不知道num_samples参数在火车装载机上使用时是如何工作的,但我可以警告您不要将批量大小放在那里。今天,我尝试设置批量大小,结果非常糟糕。我的同事把班级数计算为*100,他的成绩要好得多。我只知道你不应该把批量放在那里。我还尝试将所有训练数据的大小放入num_样本中,结果更好,但训练需要花费很长时间。不管是哪种方式,都可以尝试一下,看看什么最适合你。我猜安全的方法是使用num_samples参数的训练示例数

这是我看到其他人使用的示例,我也使用它进行二进制分类。它似乎工作得很好。取每个类的训练示例数的倒数,并将该类的所有训练示例设置为其各自的权重

使用trainset对象的快速示例

labels=np.arraytrainset.samples[:,1]转到数组并获取所有列索引1,它们是标签

labels=labels.astypeint更改为int

多数权重=1/num\u多数类\u培训\u示例

少数群体\权重=1/少数群体\班级\培训\示例

sample\u weights=np.array[多数权重,少数权重]假设少数类是labels对象中的整数1。如果没有,就换个位置,这样就成了少数人的重量,多数人的重量

weights=samples\u weights[labels]这将遍历每个训练示例,并使用标签0和1作为sample\u weights对象中的索引,该对象是该类所需的权重

采样器=权重随机采样器权重=权重,num_samples=,替换=真

trainloader=data.DataLoadertrainset,batchsize=batchsize,sampler=sampler

因为pytorch文档说权重不必求和为1,我想你也可以使用不平衡类之间的比率。例如,如果你有100个多数班的培训示例和50个少数班的培训示例,那么比例为2:1。为了平衡这一点,我认为您可以对每个多数班培训示例使用1.0的权重,对所有少数班培训示例使用2.0的权重,因为从技术上讲,您希望少数班被选中的可能性增加2倍,这将在随机选择期间平衡您的班


我希望这有点帮助。对不起,我写得太草率了,我当时非常匆忙,看到没有人回答。我自己也在苦苦挣扎,也找不到任何帮助。如果没有意义,就这么说吧,我会重新编辑它,在我有空的时候把它说得更清楚。

据我理解,Pytork WeightedRandomSampler的“权重”参数与numpy.random.choice的“p”参数有些类似,后者是随机选择样本的概率。Pytorch使用权重代替随机抽样训练示例,它们在文档中声明权重不必和1相加,所以这就是我的意思,它与numpy的随机选择不完全一样。重量越重,样品被取样的可能性就越大

当您具有replacement=True时,这意味着可以多次绘制训练示例,这意味着您可以在训练集中拥有训练示例的副本,用于训练您的模式 L过采样。此外,如果与其他训练样本权重相比,权重较低,则情况正好相反,这意味着这些样本被随机抽样的几率较低;欠采样

我不知道num_samples参数在火车装载机上使用时是如何工作的,但我可以警告您不要将批量大小放在那里。今天,我尝试设置批量大小,结果非常糟糕。我的同事把班级数计算为*100,他的成绩要好得多。我只知道你不应该把批量放在那里。我还尝试将所有训练数据的大小放入num_样本中,结果更好,但训练需要花费很长时间。不管是哪种方式,都可以尝试一下,看看什么最适合你。我猜安全的方法是使用num_samples参数的训练示例数

这是我看到其他人使用的示例,我也使用它进行二进制分类。它似乎工作得很好。取每个类的训练示例数的倒数,并将该类的所有训练示例设置为其各自的权重

使用trainset对象的快速示例

labels=np.arraytrainset.samples[:,1]转到数组并获取所有列索引1,它们是标签

labels=labels.astypeint更改为int

多数权重=1/num\u多数类\u培训\u示例

少数群体\权重=1/少数群体\班级\培训\示例

sample\u weights=np.array[多数权重,少数权重]假设少数类是labels对象中的整数1。如果没有,就换个位置,这样就成了少数人的重量,多数人的重量

weights=samples\u weights[labels]这将遍历每个训练示例,并使用标签0和1作为sample\u weights对象中的索引,该对象是该类所需的权重

采样器=权重随机采样器权重=权重,num_samples=,替换=真

trainloader=data.DataLoadertrainset,batchsize=batchsize,sampler=sampler

因为pytorch文档说权重不必求和为1,我想你也可以使用不平衡类之间的比率。例如,如果你有100个多数班的培训示例和50个少数班的培训示例,那么比例为2:1。为了平衡这一点,我认为您可以对每个多数班培训示例使用1.0的权重,对所有少数班培训示例使用2.0的权重,因为从技术上讲,您希望少数班被选中的可能性增加2倍,这将在随机选择期间平衡您的班

我希望这有点帮助。对不起,我写得太草率了,我当时非常匆忙,看到没有人回答。我自己也在苦苦挣扎,也找不到任何帮助。如果没有意义,就这么说,我会重新编辑它,等我有空的时候再把它弄清楚。

基于免责声明:我是作者,可以创建一个自定义的下采样器

首先,均衡器基类:

为每个类创建多个随机子样本 基于功能,torch.max或torch.min将作为过采样器或欠采样器 代码:

只需将标签传递到uuu init uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

首先,均衡器基类:

为每个类创建多个随机子样本 基于功能,torch.max或torch.min将作为过采样器或欠采样器 代码:


只需将标签传递到uu init_uuu,它必须是1D,但可以有多个或二进制类,并且可以对数据进行上/下采样。

num_samples是指在完全迭代整个数据集时绘制的样本总数。因此,通常您希望它等于lendataset.num_samples是指在完全迭代整个数据集时绘制的样本总数。所以通常你希望它等于lendataset。
class _Equalizer(Sampler):
    def __init__(self, labels: torch.tensor, function):
        if len(labels.shape) > 1:
            raise ValueError(
                "labels can only have a single dimension (N, ), got shape: {}".format(
                    labels.shape
                )
            )
        tensors = [
            torch.nonzero(labels == i, as_tuple=False).flatten()
            for i in torch.unique(labels)
        ]
        self.samples_per_label = getattr(builtins, function)(map(len, tensors))
        self.samplers = [
            iter(
                RandomSubsetSampler(
                    tensor,
                    replacement=len(tensor) < self.samples_per_label,
                    num_samples=self.samples_per_label
                    if len(tensor) < self.samples_per_label
                    else None,
                )
            )
            for tensor in tensors
        ]

    @property
    def num_samples(self):
        return self.samples_per_label * len(self.samplers)

    def __iter__(self):
        for _ in range(self.samples_per_label):
            for index in torch.randperm(len(self.samplers)).tolist():
                yield next(self.samplers[index])

    def __len__(self):
        return self.num_samples
class RandomUnderSampler(_Equalizer):
    def __init__(self, labels: torch.tensor):
        super().__init__(labels, "min")

class RandomOverSampler(_Equalizer):
    def __init__(self, labels):
        super().__init__(labels, "max")