在 pytorch ImageFolder 中创建新观察

Creating new observations in pytorch ImageFolder

我是 pythorch 的新手,我想做的事情可能很简单,但我没有在网上找到任何关于实际增加观察数量而不将它们添加到图像(在我的例子中)文件夹中的信息。我不想将图像添加到文件夹中,因为我想尝试不同的转换,看看什么是最好的,而不是一直删除图像。所以我做的是:

trf = transforms.Compose([
    transforms.ToTensor(),
    transforms.RandomRotation(degrees=45),
    transforms.Grayscale(num_output_channels=1),
    transforms.Normalize(0, 1),
    transforms.functional.invert
])
train_data = torchvision.datasets.ImageFolder(root='./splitted_data/train', transform= trf)
print(len(train_data))
train = DataLoader(train_data, batch_size= batch_size, shuffle= True,  num_workers= os.cpu_count())

这里的输出将与所有文件夹中的图像数量相同,这意味着对现有观察应用了转换,但这不是我想要实现的。我希望每个转换都是一个单独的副本。我该怎么做?

您可以实现一个转换包装器,它将按顺序应用转换并输出每个转换组合。 Torchvision 随机变换的问题是调用变换时对参数进行采样。这使得很难重现相同的转换。一种替代方法是堆叠或连接所有图像并在该堆叠上应用一次变换。

我将转换管道分为三个部分:预处理和 post 处理转换(后者不应该是随机的,因为它是单独应用的)。至于主要转换,它们是您要从中创建组合的转换列表,此处 RandomRotationGrayscale.

请注意,此解决方案在处理影响通道数的变换(例如灰度)时存在局限性。通常,您希望保持相同的张量维度,否则您的串联 and/or 堆栈将失败。

这是一个可能的解决方案:

class Combination(nn.Module):
    def __init__(self, transforms, pre, post):
        super().__init__()
        self.transforms = transforms
        self.pre = T.Compose(pre)
        self.post = T.Compose(post)

    def stacked_t(self, t, x):
        lengths = [len(o) for o in x]
        return t(torch.cat(x)).split(lengths)

    def forward(self, x):
        out = [self.pre(x)[None]]
        for t in transforms:
            out += self.stacked_t(t, out) # <- for every transform `t` we double
                                          #    the number of instances in` out`
        out = [self.post(o)[0] for o in out]
        return out

这是输入图像的示例用法:

>>> img

初始化变换组合:

>>> t = Combination(pre=[T.ToTensor()],
...                 post=[T.Normalize(0, 1),
...                       T.functional.invert],
...                 transforms=[T.RandomRotation(degrees=45),
...                             T.Grayscale(num_output_channels=1)])

这里是不同变换组合的预览:

>>> img_ = t(img)
img_[0] img_[1] img_[2] img_[3]