【问题标题】:Using Global Sum Pooling instead of Global Average Pooling in a CNN在 CNN 中使用全局总和池化而不是全局平均池化
【发布时间】:2021-08-20 02:54:38
【问题描述】:

我有一个CNN,其基本结构如下,

卷积层 -> 全局平均池化 -> 扁平化 -> 密集 -> 输出

我拥有的网络与输入大小无关,因此我可以在不同大小的输入上使用它。但是,全局平均池化操作使用输入大小来平均通道中的所有值。例如,如果我对图像进行零填充以更改其输入大小,则在全局平均池化之后我会得到一个不同的向量。因此,我正在考虑使用 sum pooling 代替,因为它与输入大小无关(我也不确定使用 sum pooling 是否可行)。由于 PyTorch 中没有内置的 sum pooling(据我所知),因此我将其实现如下,

def forward(self, x):
    features = self.features(x)
    out = F.relu(features, inplace=True)
    fshape = float(out.shape[-1])
    fshape3 = np.power(fshape, 3)
    out = F.adaptive_avg_pool3d(out, (1, 1, 1))
    out = torch.flatten(out, 1)
    out = torch.mul(out, fshape3)
    out = self.classifier(out)
    return out

不幸的是,在用总和池替换平均池后,我得到了nan 作为损失,这可能是因为在我将层与大量相乘后梯度爆炸了。所以,为了解决这个问题,我在乘法层之后应用了一个批量标准化层。这解决了nan 丢失问题;然而,学习(或优化)变得非常缓慢。我或许可以尝试提高学习率,看看是否能解决问题。

但是,我想了解为什么总和池会提供不稳定的结果,而从技术上讲,我只是将层乘以(或缩放)一个常数?如果有人能对此有所了解,我将不胜感激。如果其他人在实施 sum pooling 时遇到任何问题,我也想了解更多关于他们的经验。

【问题讨论】:

  • 为什么要在输入图像上启用/禁用零填充?您在 CNN 部分中使用的第一个卷积层是什么?
  • @Ivan 我当然可以使用零填充来使所有输入的大小相同,但目前,我正试图避免它。此外,我用较小的输入尺寸(比如 20x20)训练了某些模型,但现在,我想在更大的输入(比如 24x24)上使用该训练模型。我不能真正使用我正在处理的数据类型进行裁剪和重新缩放。第一个 conv 层的 kernel size=3、stride=1 和 out_channels=64,尽管我认为我使用什么类型的 conv 层并不重要。

标签: python pytorch conv-neural-network batch-normalization


【解决方案1】:

在稳定性方面:模型在[0, 1] 范围内进行训练。话虽这么说,当你求和而不是平均你的激活时,你实际上最终超出了这个范围。这意味着后续层很可能饱和,并且无法在反向传播期间学习。这就是为什么 PyTorch 中没有“总和池”层这样的东西的原因,它根本不起作用。

在这里,您正在使用 (h, w) 输入训练您的模型,并希望在不同大小的数据集上使用它。无论该层的输出形状如何,您都不需要在第一层有零填充。您正在使用自适应池,其中输出具有可预测形状的形状。所以最终你的CNN输出什么并不重要。这意味着您可以在之后独立于输入大小插入任意完全连接的网络。这是设计自适应池化层的主要原因。

【讨论】:

    猜你喜欢
    • 2019-04-10
    • 1970-01-01
    • 1970-01-01
    • 2020-04-21
    • 2020-09-05
    • 2020-02-29
    • 2020-04-18
    • 2019-01-30
    • 1970-01-01
    相关资源
    最近更新 更多