【问题标题】:Keras BatchNorm: Training accuracy increases while Testing accuracy decreasesKeras BatchNorm:训练准确性提高,而测试准确性降低
【发布时间】:2017-10-09 02:58:58
【问题描述】:

我正在尝试在 Keras 中使用 BatchNorm。训练的准确性会随着时间的推移而增加。从 12% 到 20%,缓慢而坚定。 然而,测试准确度从 12% 下降到 0%。随机基线为 12%。

我非常认为这是由于 batchnorm 层(移除 batchnorm 层会导致 ~12% 的测试准确度),它可能没有足够好地初始化参数 gamma 和 beta。应用 batchnorm 时我需要注意什么特别之处吗?我真的不明白还有什么可能出了问题。我有以下型号:

model = Sequential()

model.add(BatchNormalization(input_shape=(16, 8)))
model.add(Reshape((16, 8, 1)))

#1. Conv (64 filters; 3x3 kernel)
model.add(default_Conv2D())
model.add(BatchNormalization(axis=3))
model.add(Activation('relu'))

#2. Conv (64 filters; 3x3 kernel)
model.add(default_Conv2D())
model.add(BatchNormalization(axis=3))
model.add(Activation('relu'))

... 

#8. Affine (NUM_GESTURES units) Output layer
model.add(default_Dense(NUM_GESTURES))
model.add(Activation('softmax'))


sgd = optimizers.SGD(lr=0.1)
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])

default_Conv2D 和 default_Dense 定义如下:

def default_Conv2D():
    return Conv2D(
        filters=64,
        kernel_size=3,
        strides=1,
        padding='same',
        # activation=None,
        # use_bias=True,
        # kernel_initializer=RandomNormal(mean=0.0, stddev=0.01, seed=None), #RandomUniform(),
        kernel_regularizer=regularizers.l2(0.0001),
        # bias_initializer=RandomNormal(mean=0.0, stddev=0.01, seed=None), # RandomUniform(),
        # bias_regularizer=None
    )

def default_Dense(units):

    return Dense(
        units=units,
        # activation=None,
        # use_bias=True,
        # kernel_initializer=RandomNormal(mean=0.0, stddev=0.01, seed=None),#RandomUniform(),
        # bias_initializer=RandomNormal(mean=0.0, stddev=0.01, seed=None),#RandomUniform(),
        kernel_regularizer=regularizers.l2(0.0001),
        # bias_regularizer=None
    )

【问题讨论】:

    标签: tensorflow deep-learning keras keras-layer batch-normalization


    【解决方案1】:

    问题是过度拟合

    您的前 2 个观察结果支持这一点:

    1. 训练准确度会随着时间的推移而提高。从 12% 到 20%,.. 测试准确率从 12% 下降到 0%
    2. 移除 batchnorm 层会导致 ~12% 的测试准确度

    第一条语句告诉我你的网络正在记忆训练集。第二条语句告诉我,当您阻止网络记住训练集(甚至学习)时,它就会停止与记忆有关的错误。

    过拟合有一些解决方案,但问题比这篇文章大。请将以下列表视为“top”列表,而非详尽无遗:

    • 在最终的全连接层之前添加一个正则化器,例如 Dropout
    • 在矩阵权重上添加 L1 或 L2 正则化器
    • 在 CONV 之间添加一个像 Dropout 这样的正则化器
    • 您的网络可能有太多的空闲参数。尝试将层数减少到仅 1 个 CONV,然后一次再添加一层,每次重新训练和测试。

    准确度提高缓慢

    作为旁注,您通过说缓慢但肯定暗示您的准确性并没有像您希望的那样快速提高。完成以下所有步骤后,我取得了巨大的成功

    • 将损失函数更改为小批量中所有项目的所有预测的平均损失。这使您的损失函数独立于您的批量大小,您会发现,如果您更改批量大小并且损失函数随之发生变化,那么您将不得不更改以 SGD 为单位的学习率。
    • 您的损失是单个数字,它是所有预测类和所有样本的损失的平均值,因此使用 1.0 的学习率。不再需要扩展它。
    • 使用 tf.train.MomentumOptimizer,学习率 = 1.0,动量 = 0.5。 MomentumOptimizer 已被证明比 GradientDescent 更强大

    【讨论】:

    • 非常感谢您的回答!但是,问题是,如果我将其部署在 tensorflow 上,完全相同的代码可以工作。我是否正确使用了 BatchNorm?还是有任何已知的错误?
    • 当你说如果我在 tensorflow 上部署它就可以工作,你之前在哪里部署它?
    • 对不起,我应该更清楚.. 我之前的实现是纯 tensorflow。现在我将它部署在带有 tensorflow 后端的 Keras 上。张量流模型具有exact相同的架构。我之前也遇到过同样的问题,结果发现tensorflow中的变量需要用特殊的方式初始化(​​如here)。所以我怀疑我也必须在 Keras 中初始化一些东西,但这似乎不是这样..
    • 顺便说一句真的很棒的答案! :) 中间的层无论如何都包括辍学和正则化:)。在现有架构下,我使用纯 tensorflow(无 Keras 前端)获得了 85% 的测试准确率
    【解决方案2】:

    Keras 本身似乎出了点问题。

    天真

    pip install git+git://github.com/fchollet/keras.git --upgrade --no-deps
    

    成功了。

    @wontonimo,非常感谢您的出色回答!

    【讨论】:

    • 很高兴你找到它!
    猜你喜欢
    • 2018-09-18
    • 2020-10-17
    • 1970-01-01
    • 1970-01-01
    • 2021-08-11
    • 1970-01-01
    • 1970-01-01
    • 2017-10-05
    • 2019-01-30
    相关资源
    最近更新 更多