【问题标题】:add Batch Normalization immediately before non-linearity or after in Keras?在 Keras 的非线性之前或之后添加批量标准化?
【发布时间】:2017-07-10 15:14:54
【问题描述】:
def conv2d_bn(x, nb_filter, nb_row, nb_col,
              border_mode='same', subsample=(1, 1),
              name=None):
    '''Utility function to apply conv + BN.
    '''

    x = Convolution2D(nb_filter, nb_row, nb_col,
                      subsample=subsample,
                      activation='relu',
                      border_mode=border_mode,
                      name=conv_name)(x)
    x = BatchNormalization(axis=bn_axis, name=bn_name)(x)
    return x

当我在 keras 中使用官方 inception_v3 模型时,我发现他们在 'relu' 非线性之后使用了 BatchNormalization,如上面的代码脚本。

但在 Batch Normalization 论文中,作者说

我们在非线性之前立即添加 BN 变换,通过 归一化 x=Wu+b。

然后我查看了 tensorflow 中 inception 的实现,正如他们所说,它在非线性之前立即添加了 BN。更多详情inception ops.py

我很困惑。为什么人们在 Keras 中使用上述样式而不是以下样式?

def conv2d_bn(x, nb_filter, nb_row, nb_col,
              border_mode='same', subsample=(1, 1),
              name=None):
    '''Utility function to apply conv + BN.
    '''

    x = Convolution2D(nb_filter, nb_row, nb_col,
                      subsample=subsample,
                      border_mode=border_mode,
                      name=conv_name)(x)
    x = BatchNormalization(axis=bn_axis, name=bn_name)(x)
    x = Activation('relu')(x)
    return x

在密集的情况下:

x = Dense(1024, name='fc')(x)
x = BatchNormalization(axis=bn_axis, name=bn_name)(x)
x = Activation('relu')(x)

【问题讨论】:

    标签: tensorflow deep-learning theano keras


    【解决方案1】:

    我也在激活前使用它,确实是这样设计的,其他库也是如此,例如千层面的batch_norm http://lasagne.readthedocs.io/en/latest/modules/layers/normalization.html#lasagne.layers.batch_norm

    但实际上在激活之后放置它似乎效果更好:

    https://github.com/ducha-aiki/caffenet-benchmark/blob/master/batchnorm.md (不过这只是一个基准)

    【讨论】:

      【解决方案2】:

      除了原论文在激活前使用批量归一化外,Bengio 的书Deep Learning, section 8.7.1 给出了为什么在激活之后(或直接在输入到下一层之前)应用批量归一化可能会导致一些问题的原因:

      很自然地想知道我们是否应该将批量标准化应用于 输入 X,或转换后的值 XW+b。约夫和塞格迪 (2015) 推荐后者。更具体地说,XW+b 应该被替换为 XW 的标准化版本。应该省略偏置项,因为它 随着批次应用的 β 参数变得多余 归一化重新参数化。层的输入通常是 非线性激活函数的输出,例如修正后的线性 在前一层中起作用。输入的统计数据因此是 更非高斯且更不易通过线性标准化 操作。

      换句话说,如果我们使用 relu 激活,所有负值都映射为零。这可能会导致平均值已经非常接近于零,但剩余数据的分布将严重向右倾斜。试图将数据归一化为漂亮的钟形曲线可能不会给出最好的结果。对于 relu 系列之外的激活,这可能不是什么大问题。

      请记住,有报告称在激活后使用批量标准化时模型会获得更好的结果,因此使用这两种配置测试您的模型可能是值得的。

      【讨论】:

        猜你喜欢
        • 2018-04-26
        • 2017-10-21
        • 2019-12-18
        • 1970-01-01
        • 1970-01-01
        • 2019-05-23
        • 2018-07-28
        • 2019-10-30
        • 2018-03-01
        相关资源
        最近更新 更多