pytorch dataloader_PyTorch中的可迭代数据集重采样

动机

不平衡学习是一种机器学习范例,其中分类器必须从具有倾斜的类分布的数据集中学习。不平衡的数据集可能对分类器的性能产生不利影响。

重新平衡数据集是处理类不平衡的一种方法。这可以通过以下方式完成:

  • 采样不足的普通类。
  • 对稀有类进行过度采样。
  • 两者兼而有之。

PyTorch提供了一些用于重新平衡数据集的实用程序,但它们仅限于已知长度的批处理数据集(即,它们要求数据集具有__len__方法)。诸如ufoym / imbalanced-dataset-sampler之类的社区贡献很可爱,但它们也仅适用于批处理数据集(在PyTorch行话中也称为地图样式数据集)。 pytorch / pytorch存储库上还存在一个GitHub问题,但它似乎不太活跃。

因此,该存储库实现了包装IterableDataset的数据重采样器。在此拉取请求中,后者已添加到PyTorch。特别是,提供的方法不需要您必须事先知道数据集的大小。每种方法都适用于二进制和多类分类。

安装

$ pip install pytorch_resample

用法

作为一个正在运行的示例,我们将定义一个IterableDataset,它对scikit-learn的make_classification函数的输出进行迭代。

>>> from sklearn import datasets>>> import torch>>> class MakeClassificationStream(torch.utils.data.IterableDataset):......     def __init__(self, *args, **kwargs):...         self.X, self.y = datasets.make_classification(*args, **kwargs)......     def __iter__(self):...         yield from iter(zip(self.X, self.y))

可以将以上数据集提供给DataLoader,以迭代Tensor批次。 为了举例说明,我们将生成10.000个样本,其中50%的0s,40%的1s和10%的2s。 我们可以使用collections.Counter来衡量有效的类分布。

>>> import collections>>> dataset = MakeClassificationStream(...     n_samples=10_000,...     n_classes=3,...     n_informative=6,...     weights=[.5, .4, .1],...     random_state=42... )>>> y_dist = collections.Counter()>>> batches = torch.utils.data.DataLoader(dataset, batch_size=16)>>> for xb, yb in batches:...     y_dist.update(yb.numpy())>>> for label in sorted(y_dist):...     print(f'• {label}: {y_dist[label] / sum(y_dist.values()):.2%} ({y_dist[label]})')• 0: 49.95% (4995)• 1: 39.88% (3988)• 2: 10.17% (1017)

欠采样

可以使用pytorch_resample.UnderSampler类对数据流进行欠采样。 后者是包装器,必须提供IterableDataset和所需的类分发。 它继承自IterableDataset,因此可以代替包装的数据集使用。 举个例子,让它被平等地表示。

如图所示,观察到的类分布接近指定的分布。 实际上,比上面少的0和1。 请注意,desired_dist参数的值不需要总和为1,因为这是自动完成的。

过度采样

您可以使用pytorch_resample.OverSampler来对数据进行过度采样。 它具有与pytorch_resample.UnderSampler相同的签名,因此可以完全相同的方式使用。

>>> sample = pytorch_resample.OverSampler(...     dataset=dataset,...     desired_dist={0: .33, 1: .33, 2: .33},...     seed=42... )>>> y_dist = collections.Counter()>>> batches = torch.utils.data.DataLoader(sample, batch_size=16)>>> for xb, yb in batches:...     y_dist.update(yb.numpy())>>> for label in sorted(y_dist):...     print(f'• {label}: {y_dist[label] / sum(y_dist.values()):.2%} ({y_dist[label]})')• 0: 33.21% (4995)• 1: 33.01% (4965)• 2: 33.78% (5080)

在这种情况下,1和2已过采样。

混合法

pytorch_resample.HybridSampler类可用于在欠采样和过采样之间折衷。 它接受一个名为sample_rate的额外参数,该参数确定要使用的数据百分比。 这样可以控制用于训练的数据量,同时确保班级分配遵循所需的分配。

>>> sample = pytorch_resample.HybridSampler(...     dataset=dataset,...     desired_dist={0: .33, 1: .33, 2: .33},...     sampling_rate=.5,  # use 50% of the dataset...     seed=42... )>>> y_dist = collections.Counter()>>> batches = torch.utils.data.DataLoader(sample, batch_size=16)>>> for xb, yb in batches:...     y_dist.update(yb.numpy())>>> for label in sorted(y_dist):...     print(f'• {label}: {y_dist[label] / sum(y_dist.values()):.2%} ({y_dist[label]})')• 0: 33.01% (1672)• 1: 32.91% (1667)• 2: 34.08% (1726)

可以看出,流样本的数量接近5000,是数据集大小的一半。

预期样本数

只要知道数据的类别分布,就可以预先确定每个重采样器将流回的确切样本数。

>>> n = 10_000>>> desired = {'cat': 1 / 3, 'mouse': 1 / 3, 'dog': 1 / 3}>>> actual = {'cat': .5, 'mouse': .4, 'dog': .1}>>> pytorch_resample.UnderSampler.expected_size(n, desired, actual)3000>>> pytorch_resample.OverSampler.expected_size(n, desired, actual)15000>>> pytorch_resample.HybridSampler.expected_size(n, .5)5000

性能提示

根据设计,UnderSampler和HybridSampler可以一个接一个地重复采样。 这可能不是理想的,因为通常需要在每个批次中使样品多样化。 因此,我们建议您使用改组缓冲区,例如此处建议的ShuffleDataset类。

它是如何工作的?

据我所知,该软件包中实现的方法在文献中并不存在。 我首先偶然发现了欠采样方法,该方法等效于拒绝采样。 然后,我为过采样和混合方法制定了必要的公式。 后者都基于从Poisson分布中抽样的想法,我是从Nikunj Oza和Stuart Russell的Online Bagging and Boosting论文中选取的。 创新之处在于确定满足所需类别分布的比率。

发展历程

$ python -m venv .env$ source .env/bin/activate$ pip install poetry$ poetry install$ pytest
pytorch dataloader_PyTorch中的可迭代数据集重采样_第1张图片

你可能感兴趣的:(pytorch,dataloader,pytorch,dataset,pytorch,dataset,dataloader,pytorch安装到一半中断,torch,dataloader,数据并行,样本不平衡,pytorch)