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])
    ]),
}
在这里,对于训练,我们首先随机裁剪图像并调整其形状(224,224).然后我们拍摄这些(224,224)图像并水平翻转它们.因此,我们的数据集现在只包含水平翻转的图像,因此在这种情况下我们的原始图像会丢失.
我对吗?这种理解是否正确?如果没有,那么我们在上面的代码(取自官方文档)中告诉PyTorch在哪里保留原始图像并将它们调整到预期的形状(224,224)?
谢谢
Ash*_*372 31
我假设您在询问这些数据扩充变换(例如RandomHorizontalFlip)是否实际上也增加了数据集的大小,或者它们是否逐个应用于数据集中的每个项目而不是添加到数据集的大小.
运行以下简单的代码片段,我们可以观察到后者是正确的,即,如果您有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)
结果:(浮点的微小差异是由转换为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]]]])
转换数据集:
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]]])
ben*_*che 16
transforms每批次都会将操作应用于原始图像.因此,您的数据集保持不变,每次迭代仅复制和转换批处理图像.
混淆可能来自这样一个事实,即在您的示例中,transforms通常用于数据准备(调整大小/裁剪到预期尺寸,规范化值等)和数据增强(随机调整大小/裁剪,随机翻转图像)等).
你data_transforms['train']做的是:
(224, 224)修补程序TensorTensor您提供的平均值和偏差值,对结果进行归一化你data_transforms['val']做的是:
(256, 256)(224, 224)补丁TensorTensor您提供的平均值和偏差值,对结果进行归一化(即,训练数据的随机大小调整/裁剪由验证操作的固定操作替换,以获得可靠的验证结果)
如果您不希望您的训练图像以50/50的比例水平翻转,只需删除该transforms.RandomHorizontalFlip()线.
同样,如果你希望你的图片永远是中心,裁剪,替换transforms.RandomResizedCrop用transforms.Resize和transforms.CenterCrop,作为完成data_transforms['val'].
小智 5
是的,数据集大小在转换后不会改变。每个 Image 都传递给转换并返回,因此大小保持不变。
如果您希望使用转换后的原始数据集连接它们。
例如 increased_dataset = torch.utils.data.ConcatDataset([transformed_dataset,original])