PyTorch中的数据增强

H.S*_*H.S 27 python image-processing dataset pytorch data-augmentation

我对PyTorch中执行的数据扩充有点困惑.现在,据我所知,当我们执行数据扩充时,我们将保留原始数据集,然后添加其他版本(Flipping,Cropping ...等).但这似乎并没有发生在PyTorch中.据我data.transforms所知,当我们在PyTorch中使用时,它会逐一应用它们.例如:

data_transforms = {
    'train': transforms.Compose([
        transforms.RandomResizedCrop(224),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ]),
    'val': transforms.Compose([
        transforms.Resize(256),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ]),
}
Run Code Online (Sandbox Code Playgroud)

在这里,对于训练,我们首先随机裁剪图像并调整其形状(224,224).然后我们拍摄这些(224,224)图像并水平翻转它们.因此,我们的数据集现在只包含水平翻转的图像,因此在这种情况下我们的原始图像会丢失.

我对吗?这种理解是否正确?如果没有,那么我们在上面的代码(取自官方文档)中告诉PyTorch在哪里保留原始图像并将它们调整到预期的形状(224,224)

谢谢

Ash*_*372 31

我假设您在询问这些数据扩充变换(例如RandomHorizo​​ntalFlip)是否实际上也增加了数据集的大小,或者它们是否逐个应用于数据集中的每个项目而不是添加到数据集的大小.

运行以下简单的代码片段,我们可以观察到后者是正确的,即,如果您有8个图像的数据集,并在迭代数据集时为此数据集创建PyTorch数据集对象,则会在每个数据点上调用转换,并返回转换后的数据点.因此,例如,如果您有随机翻转,一些数据点将作为原始数据返回,一些数据点将作为翻转返回(例如,4个翻转和4个原始数据).换句话说,通过对数据集项的一次迭代,您将获得8个数据点(一些是翻转的,一些不是).[这与增加数据集的传统理解不一致(例如,在这种情况下,在增强数据集中有16个数据点)]

class experimental_dataset(Dataset):

    def __init__(self, data, transform):
        self.data = data
        self.transform = transform

    def __len__(self):
        return len(self.data.shape[0])

    def __getitem__(self, idx):
        item = self.data[idx]
        item = self.transform(item)
        return item

    transform = transforms.Compose([
        transforms.ToPILImage(),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor()
    ])

x = torch.rand(8, 1, 2, 2)
print(x)

dataset = experimental_dataset(x,transform)

for item in dataset:
    print(item)
Run Code Online (Sandbox Code Playgroud)

结果:(浮点的微小差异是由转换为pil图像和背面引起的)

原始虚拟数据集:

tensor([[[[0.1872, 0.5518],
          [0.5733, 0.6593]]],


    [[[0.6570, 0.6487],
      [0.4415, 0.5883]]],


    [[[0.5682, 0.3294],
      [0.9346, 0.1243]]],


    [[[0.1829, 0.5607],
      [0.3661, 0.6277]]],


    [[[0.1201, 0.1574],
      [0.4224, 0.6146]]],


    [[[0.9301, 0.3369],
      [0.9210, 0.9616]]],


    [[[0.8567, 0.2297],
      [0.1789, 0.8954]]],


    [[[0.0068, 0.8932],
      [0.9971, 0.3548]]]])
Run Code Online (Sandbox Code Playgroud)

转换数据集:

tensor([[[0.1843, 0.5490],
     [0.5725, 0.6588]]])
tensor([[[0.6549, 0.6471],
     [0.4392, 0.5882]]])
tensor([[[0.5647, 0.3255],
         [0.9333, 0.1216]]])
tensor([[[0.5569, 0.1804],
         [0.6275, 0.3647]]])
tensor([[[0.1569, 0.1176],
         [0.6118, 0.4196]]])
tensor([[[0.9294, 0.3333],
         [0.9176, 0.9608]]])
tensor([[[0.8549, 0.2275],
         [0.1765, 0.8941]]])
tensor([[[0.8902, 0.0039],
         [0.3529, 0.9961]]])
Run Code Online (Sandbox Code Playgroud)

  • @pooria 不一定。数据增强的目的是试图获得未见(测试)数据的数据分布的上限,希望神经网络能够逼近该数据分布,但需要权衡它逼近火车的原始分布数据(测试数据在现实中不太可能相似)。没有一种方法或定义适合所有的数据增强方法或定义。 (5认同)
  • 我认为这是OP真正提出的问题的答案。 (4认同)
  • @NicoleFinnie但是我怎样才能使用所有这些,原始数据集和转换后的数据集。因为增强的目的之一是增加数据集大小,对吗? (4认同)
  • 因此,这意味着在每个时期您都会获得不同版本的数据集,对吗? (3认同)
  • @Alexandros是的 (2认同)
  • @pooria,你不需要这样做(由@NicoleFinnie解释)...但是,如果由于某种原因你必须这样做,你可以使用pytorch中可用的转换生成一个新的数据集,保存它..并训练新的..(虽然我不会推荐它,但只有当你有特定的原因时才这样做) (2认同)

ben*_*che 16

transforms每批次都会将操作应用于原始图像.因此,您的数据集保持不变,每次迭代仅复制和转换批处理图像.

混淆可能来自这样一个事实,即在您的示例中,transforms通常用于数据准备(调整大小/裁剪到预期尺寸,规范化值等)和数据增强(随机调整大小/裁剪,随机翻转图像)等).


data_transforms['train']做的是:

  • 随机调整提供的图像大小并随机裁剪以获得(224, 224)修补程序
  • 对此补丁应用或不应用随机水平翻转,有50/50的几率
  • 将其转换为 Tensor
  • 根据Tensor您提供的平均值和偏差值,对结果进行归一化

data_transforms['val']做的是:

  • 调整图像大小 (256, 256)
  • 居中裁剪已调整大小的图像以获取(224, 224)补丁
  • 将其转换为 Tensor
  • 根据Tensor您提供的平均值和偏差值,对结果进行归一化

(即,训练数据的随机大小调整/裁剪由验证操作的固定操作替换,以获得可靠的验证结果)


如果您不希望您的训练图像以50/50的比例水平翻转,只需删除该transforms.RandomHorizontalFlip()线.

同样,如果你希望你的图片永远是中心,裁剪,替换transforms.RandomResizedCroptransforms.Resizetransforms.CenterCrop,作为完成data_transforms['val'].

  • @insanely_sin:所有转换都会以某种方式更改图像(它们保持原始状态不变,只是返回更改后的副本)。给定相同的输入图像,某些方法将始终应用相同的更改(例如,将其转换为“张量”,调整大小为固定形状等)。其他方法将应用具有随机参数的变换,每次返回不同的结果(例如,随机裁剪图像,随机更改其亮度或饱和度等)。由于后面的转换每次都会返回不同的图像(来自相同的原始样本),因此它们会_增强_数据集。 (4认同)
  • 我仍然不清楚哪些转换会增加数据集的大小,哪些转换会更改原始图像? (3认同)

小智 5

是的,数据集大小在转换后不会改变。每个 Image 都传递给转换并返回,因此大小保持不变。

如果您希望使用转换后的原始数据集连接它们。

例如 increased_dataset = torch.utils.data.ConcatDataset([transformed_dataset,original])

  • 通过这种技术,我成功地增强了我的数据*2,但我仍然想知道是否有一种方法可以帮助我自动执行此任务,例如,您只需提供原始数据,然后收到增强数据*2或*4次取决于你所做的转变? (2认同)