是否可以将可变大小的图像作为卷积神经网络的输入?

机器算法验证 神经网络 张量流 喀拉斯 计算机视觉 物体检测
2022-02-01 13:29:25

我们可以将可变大小的图像作为卷积神经网络的输入来进行目标检测吗?如果可能,我们该怎么做?


但是如果我们尝试裁剪图像,我们将丢失图像的某些部分,如果我们尝试调整大小,那么图像的清晰度将会丢失。这是否意味着如果图像清晰度是主要考虑点,则使用固有的网络属性是最好的?

4个回答

有很多方法可以做到这一点。其中大部分已经在 StackOverflow、Quora 和其他内容网站上的许多帖子中有所介绍。

总而言之,列出的大多数技术可以分为两类解决方案,即,

  1. 转型
  2. 固有网络属性

在转换中,可以查找诸如

  • 调整大小,这是所有提到的技术中最简单的
  • 裁剪,可以作为滑动窗口或一次性裁剪,信息丢失

人们还可以通过构建网络的层行为来研究具有固有属性的网络,即不受输入大小的影响。这方面的例子可以在以下方面找到,

  • 全卷积网络(FCN),它对输入大小完全没有限制,因为一旦描述了内核和步长,每一层的卷积就可以根据相应的输入生成适当的维度输出。

  • Spatial Pyramid Pooling (SPP),FCN 没有完全连接的密集层,因此与图像大小无关,但是如果想在不考虑输入变换的情况下使用密集层,那么有一篇有趣的论文解释了该层一个深度学习网络。

参考:

  1. https://www.quora.com/How-are-variably-shape-and-sized-images-given-inputs-to-convoluted-neural-networks
  2. https://ai.stackexchange.com/questions/2008/how-can-neural-networks-deal-with-varying-input-sizes
  3. https://discuss.pytorch.org/t/how-to-create-convnet-for-variable-size-input-dimension-images/1906

PS我可能错过了引用一些技术。不声称这是一个详尽的清单。

卷积层和池化层本身与输入维度无关。然而,对于不同大小的图像,卷积层的输出将具有不同的空间大小,如果我们之后有一个全连接层,这将导致问题(因为我们的全连接层需要一个固定大小的输入)。有几种解决方案:

1. 全局池化:避免在卷积层末尾使用全连接层,而是使用池化(例如全局平均池化)将特征图从 (N,H,W,C) 的形状减少(在全局池之前) ) 对 (N,1,1,C) 进行整形(在全局池之后),其中:

N = minibatch 样本数
H = 特征图的空间高度
W = 特征图的空间宽度
C = 特征图(通道)的

数量可以看出,输出维度(N*C)现在独立于特征图的空间大小(H,W)。在分类的情况下,您可以继续使用顶部的全连接层来获取类的 logits。

2.可变大小的池:使用可变大小的池化区域为不同的输入大小获得相同的特征图大小。

3. 裁剪/调整大小/填充输入图像:您可以尝试重新缩放/裁剪/填充输入图像,使其具有相同的形状。


在迁移学习的上下文中,您可能希望使用与训练模型的原始输入不同大小的输入。以下是一些这样做的选项:

4. 创建新的全连接层:您可以完全抛弃原来的全连接层,并使用您需要的维度初始化一个新的全连接层,然后从头开始训练。

5. 将全连接层视为卷积:通常,我们将特征图从 (N,H,W,C) 重塑为 (N,H*W*C),然后再将其馈送到全连接层。但是您也可以将全连接层视为具有 (H,W) 感受野的卷积。然后,你可以只用你的特征图卷积这个内核,不管它们的大小(如果需要,使用零填充)[http://cs231n.github.io/transfer-learning/ ]。

我今天必须解决这个问题,所以我想我会分享我发现有效的方法。我发现网上有很多“这在理论上可行”的答案和花絮,但从实际的“这就是你如何具体实现它”中得到的却很少。

要使用 Tensorflow Keras 实现这一点,我必须执行以下操作。也许其他人可以发现其中一些可以修改、放松或删除。

  1. 设置网络的输入以允许使用“无”作为 input_shape 上的占位符维度进行可变大小输入。在此处查看Francois Chollet 的回答
  2. 仅在发生全局池化操作之前使用卷积层(例如 GlobalMaxPooling2D)。然后可以使用密集层等,因为现在大小是固定的。
  3. 仅使用 1 的批量大小。这避免了处理批次中的混合尺寸。
  4. 编写一个小的自定义序列,从输入列表中创建大小为 1 的批次。我这样做是为了避免在单个 Numpy 数组中处理不同的大小。
  5. 在您的自定义序列上使用 Model.fit_generator 进行训练和验证。(与 Model.fit 相比)
  6. 出于某种原因,即使使用上述序列,Model.predict_generator 也会弹出。我不得不求助于对单个输入使用 Model.predict。

请注意,对 Model.predict 的调用确实抱怨性能 - 鉴于解决方案效率低下,这并不奇怪 - 但它确实有效!

是的,只需选择一个适当的骨干网络,它不依赖于输入图像的大小来获得某个精确值——大多数网络都满足这个标准。