【问题标题】:Why PyTorch model takes multiple image size inside the model?为什么 PyTorch 模型在模型内部采用多个图像大小?
【发布时间】:2020-10-24 10:16:17
【问题描述】:

我在 PyTorch 中使用简单的对象检测模型,并使用 Pytoch 模型进行推理。

当我在代码上使用简单的迭代器时

for k, image_path in enumerate(image_list):
    image = imgproc.loadImage(image_path)
    print(image.shape)
    with torch.no_grad():
        y, feature = net(x)        
    result = image.cuda()

它打印我们可变大小的图像,例如

torch.Size([1, 3, 384, 320])

torch.Size([1, 3, 704, 1024])

torch.Size([1, 3, 1280, 1280])

因此,当我使用 DataLoader 使用批处理推理应用相同的转换时,代码不会运行。 但是,当我将所有图像的大小调整为 600.600 时,批处理会成功运行。

我有两个疑问,

首先为什么 Pytorch 能够在深度学习模型中输入动态大小的输入,以及为什么动态大小的输入在批处理中失败。

【问题讨论】:

    标签: python machine-learning deep-learning computer-vision pytorch


    【解决方案1】:

    PyTorch 具有所谓的Dynamic Computational Graph (other explanation)。

    它允许神经网络的图形在训练或推理期间动态适应其输入大小,从一个输入到下一个输入。 这就是您在第一个示例中观察到的情况:将图像作为大小为 [1, 3, 384, 320] 的张量提供给您的模型,然后将另一个图像作为大小为 [1, 3, 384, 1024] 的张量,依此类推,因为对于每个输入都是完全可以的,您的模型将动态适应。

    但是,如果您的输入实际上是一组输入(批次),那就另当别论了。对于 PyTorch,批次将被转换为具有一个额外维度的单个张量输入。例如,如果您提供一个包含 n 个图像的列表,每个图像的大小为 [1, 3, 384, 320],PyTorch 会将它们堆叠起来,这样您的模型就有一个单一的张量输入,形状为 [n, 1, 3, 384, 320]

    这种“堆叠”只能发生在相同形状的图像之间。为了提供比以前的答案更“直观”的解释,这种堆叠操作不能在不同形状的图像之间完成,因为网络无法“猜测”不同的图像应该如何在一批中“对齐”,如果它们不是大小都一样。

    无论是在训练还是测试期间发生,如果您从不同大小的图像中创建批次,PyTorch 都会拒绝您的输入

    通常会使用几种解决方案:按照您的做法进行整形、添加填充(通常是图像边框上的小值或空值)以将较小的图像扩展到最大图像的大小,等等。

    【讨论】:

    • 可以按尺寸整理吗?
    • 如果您的意思是创建一批相同大小的项目(一批用于 [1, 3, 384, 320] 的项目,一批用于 [1, 3, 384, 1024] 的项目,. ..),是的,它被称为“bucketing”。
    • 你能分享一些关于分桶的文档吗?我找不到任何计算机视觉的例子。
    • 这个link是对分桶概念的基本解释(不适用于CV)。你能详细说明你不了解的地方吗?
    • 很棒的答案,Clef!
    【解决方案2】:

    为什么网络可以处理不同大小的图像,我想到了两个原因:

    1. 最简单的原因是,在网络的输入中有一个插值层,可将输入的大小调整为网络的预期值。
    2. 当您有一个完全卷积网络时,您可以向模型插入动态大小的输入,这意味着网络中的所有操作都不依赖于输入空间大小。例如,如果所有层都是卷积 Relu 和池化,则网络可以处理您将插入的任何大小。因此,您可以插入一个大小为 [N, 3, 384, 320] 或 [N, 3, 704, 1024] 的批次,网络将同时运行

    您认为无法运行不同大小的推理的原因是因为您不能拥有具有多个不同大小的张量。图像的张量需要是固定大小,(N,C,H,W),您不能在张量中使用尺寸为(H',W')和另一个尺寸为(H,W)的图像,因为它们需要在具有特定大小的同一张量中。

    但是您可以为每个批次使用不同的大小进行训练/推断。所以例如第一批图像可以是(N,C,H,W),下一批图像可以是(N,C,H',W')。

    【讨论】:

    • 我这是第二个原因,我不想训练网络,而是对它们进行批量推理。目前是不可能的。
    • 不,你不能对一批不同大小的图像进行推理
    • 你能解释一下原因吗?
    • 就像我在答案中写的那样:“图像的张量需要是固定大小,(N,C,H,W),你不能在张量中有大小(H ', W') 和另一个带有 (H, W) 因为它们需要在具有特定大小的同一张量中。"
    【解决方案3】:

    它可能适用于单个图像但不适用于批处理图像的原因是,对于批处理图像,数据集将尝试在您的批处理中调用 torch.stack。这不起作用,因为尽管通道尺寸可能对齐(1 表示灰度或 RGB 表示颜色),但图像的高度和宽度尺寸不会正确对齐!上面已经介绍过了。

    解决此问题的一种方法是找到数据集中任何图像的最大尺寸。然后您可以将每个图像调整为该大小!执行此操作的正确方法可能是填充图像,同时保存每个图像的真实大小,以便您以后可以对其进行整形。这是一个例子:

    DataSet 返回的对象:

    size = [1024, 1024]
    
    return {'image': image,
            'size': size}
    

    您在哪里使用数据:

    image = batch['image']
    single_image = image[batch_index, :size[0], :size[1]] 
    

    现在,返回了一批图像,但您可以将它们提取为原始大小。如果您需要一次通过网络运行整个批次,您可能不想这样做,但值得考虑。

    【讨论】:

      猜你喜欢
      • 2021-11-02
      • 1970-01-01
      • 2021-02-09
      • 2021-11-05
      • 1970-01-01
      • 2012-08-11
      • 2023-03-10
      • 2023-01-14
      • 2022-09-29
      相关资源
      最近更新 更多