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作为上面的代码脚本。
但在批量标准化论文中,作者说
我们在非线性之前立即添加BN变换 标准化x = Wu + b。
然后我在tensorflow中查看初始化的实现,它在非线性之前立即添加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)
答案 0 :(得分:0)
我也在激活之前使用它,这确实是它的设计方式,其他库也是如此,例如lasagne的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 (这只是一个基准)
答案 1 :(得分:0)
除了原始论文在激活前使用批归一化之外,Bengio 的书 Deep Learning, section 8.7.1 给出了一些推理为什么在激活之后(或直接在输入到下一层之前)应用批归一化可能会导致一些问题:
<块引用>很自然地想知道我们是否应该将批量归一化应用于 输入 X,或转换后的值 XW+b。 Ioffe 和 Szegedy (2015) 推荐后者。更具体地说,XW+b 应该替换为 a XW 的标准化版本。应该省略偏置项,因为它 随着批处理应用的 β 参数变得多余 归一化重新参数化。层的输入通常是 非线性激活函数的输出,例如整流线性 上一层的功能。因此,输入的统计信息是 更非高斯,更不适合线性标准化 操作。
换句话说,如果我们使用 relu 激活,所有负值都映射为零。这可能会导致平均值已经非常接近于零,但剩余数据的分布将严重偏向右侧。尝试将该数据标准化为漂亮的钟形曲线可能不会给出最佳结果。对于 relu 系列之外的激活,这可能不是什么大问题。
请记住,有报告称模型在激活后使用批量标准化获得了更好的结果,因此使用这两种配置测试您的模型可能是值得的。