使用 CUDNN 进行批量标准化

数据挖掘 深度学习 美国有线电视新闻网 批量标准化
2022-03-11 18:07:16

我想在我的 CNN 的 C++/CUDNN 实现中引入批量标准化。该实现目前在 MNIST 数据集上表现良好(没有 BN)。

我正在使用 Batch Norm 的 CUDNN 实现,但是在仔细阅读了 Batch Norm 论文和 CUDNN 文档之后,我仍然有一些不清楚的地方。

  1. 据我了解,批量规范层位于卷积/密集层的输出和非线性之间,例如:

u --->[conv/dense (weights W)]--->[BN]--->[ReLU]---> y = ReLU(BN(W*u))

在一些文献中,我读到将批处理规范层放在非线性之后是一个更好的选择。这是真的?

  1. CUDNN 文档说对卷积层使用 BATCHNORM_MODE_SPATIAL,对密集层使用 BATCHNORM_MODE_PER_ACTIVATION。但是,在另一个实现(YOLO / Darknet)中,我只看到使用了 BATCHNORM_MODE_SPATIAL。所以我问自己 SPATIAL 是否也适用于密集层?

  2. 如前所述,据我了解, BATCHNORM_MODE_SPATIAL 应该用于卷积层:但是在它们的输入上(即卷积之前),还是在它们的输出上(即卷积之后)?

据我了解,它将用于输出,例如:

u ---->[ conv (weights W) ] ---->[BN with mode SPATIAL]----->[ReLU]---> y

它是否正确?

  1. 我看到在 Darknet / YOLO 中,他们没有使用从 cudnnBatchNormalizationBackward() 获得的增量显式更新参数。这种方法是否也直接执行参数更新?我没有找到这方面的任何信息,实际上在从 cudnnBatchNormalizationBackward 方法获得 Gamma 和 Beta 梯度后,我正在应用梯度下降更新。

  2. 我看到在 CUDNN 实现中,可以使用 Forward 推理方法。在推理阶段完全跳过 BN 单元可以吗?在这种情况下,我将使用 BN 单元进行训练,并在推理过程中将它们从网络中移除。

我真的提前感谢您的耐心和您的帮助。我试图独自摆脱这些问题很长时间,但我现在被阻止了......非常感谢您的帮助。

1个回答

通常,您在激活之前执行批量标准化。原论文中缩放/偏置参数()的全部意义在于缩放归一化值(论文中的),使其完全捕捉激活算子的动态范围。βγx^

例如(这是论文中使用的示例),假设相关层(卷积或密集)的归一化输出具有单位方差(矩阵内的逐点)。然后,如果您将 sigmoid 函数逐点应用为激活,您将被限制在 sigmoid 函数的线性区域内,因此否定了任何对使网络工作至关重要的非线性属性。

但是,我相信您可以找到一种切换顺序的架构。最后,人们会根据经验为他们的用例做最好的结果。

至于更新参数(你的第四个问题),他确实更新了参数。我看了一下源码。参数更新发生在与卷积层相关的“更新”函数中。即他只将批处理规范与其他层打包在一起,这是一个合理的优化。

对于问题 2 和 3:您是正确的,除了以下警告:如果您仅在 CNN 的头部使用密集层,则不需要突然切换策略。当您期望特征图的每个维度具有不同的分布时,您将使用 MODE_PER_ACTIVATION。考虑输入地图可能是不同类型特征的非视觉用例。如果您在 CNN 中使用密集层,您仍然会假设标准化在“空间”尺度上是相同的。在最后一层展平后,您基本上展平为具有 1x1 空间维度的所以你的“空间”批量规范无论如何都会有参数。 CC

对于问题 5:否。将 BatchNorm 视为一起学习的重新缩放和偏置操作。如果你用偏差训练它然后在推理时消除偏差,你不会期望你的神经网络的输出是一致的。