Keras BatchNorm:训练准确度提高,而测试精度降低

时间:2017-05-10 12:41:55

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

我正在尝试在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
    )

2 个答案:

答案 0 :(得分:4)

问题是过度拟合

前两个观察结果支持这一点:

  1. 训练准确性随着时间的推移而增加。从12%到20%,但测试精度从12%降低到0%
  2. 移除batchnorm层导致约12%的测试准确度
  3. 第一个声明告诉我你的网络正在记忆训练集。第二个声明告诉我,当你阻止网络记忆训练集(甚至学习)时,它会停止记忆的错误。

    有一些过度拟合的解决方案,但这是一个比这篇文章更大的问题。请将以下列表视为" top" 列表,并非详尽无遗:

    • 在最终完全连接的图层之前添加 Dropout 等正规化器。
    • 在矩阵权重上添加L1或L2正则化器
    • 在CONV
    • 之间添加 Dropout 等正规化器
    • 您的网络可能包含太多免费参数。尝试将图层减少到1 CONV,并且每次重新添加一层再培训和测试。

    准确度增长缓慢

    作为旁注,你暗示你的准确度并没有随着缓慢但肯定地快速增加。当我完成以下所有步骤时,我取得了巨大的成功

    • 将您的损失函数更改为小批量中所有项目的所有预测的平均损失。这使您的损失函数与批量大小无关,您发现如果您更改批量大小并且损失函数随之改变,那么您将不得不以SGD更改学习率。
    • 您的损失是单个数字,即所有预测类别和所有样本的平均损失,因此使用1.0的学习率。无需再缩放它。
    • 使用 tf.train.MomentumOptimizer ,其中learning_rate = 1.0且动量= 0.5。 MomentumOptimizer已被证明比GradientDescent 更强大

答案 1 :(得分:0)

Keras本身似乎有些事情已经破裂。

天真的

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

做了这个伎俩。

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