对于玩具示例,批次标准化在Keras和Tensorflow中的结果不一致:为什么?

时间:2019-04-24 19:12:33

标签: python tensorflow machine-learning keras

我正在尝试使BatchNormalization在Keras(2.2.4)中正常工作,并且还没有运气。在model.fit()model.predict() / evaluate()中,其行为似乎不一致。

我最初的问题是在一个复杂的GAN设置的背景下,它具有在冻结和未冻结之间切换的各个层。为了弄清失败的原因,我创建了这个玩具示例,其中只有一个BatchNormalization层试图学习身份函数,并且不再冻结/解冻废话了:

import numpy as np
import keras
from keras.layers import Input, BatchNormalization

if __name__ == '__main__':
    x = np.random.uniform(low=-1.0, high=1.0, size=(20,1,))
    y = x

    ip = tx =Input(shape=[1,])
    tx = BatchNormalization()(tx)
    mod = keras.Model(inputs=ip, outputs=tx)

    mod.compile(optimizer=keras.optimizers.SGD(lr=0.01), loss="mse")
    mod.fit(x, y, epochs=2000)
    print("mod evaluate", mod.evaluate(x, y))

我还创建了一个纯tensorflow实现,尝试执行完全相同的操作:

import tensorflow as tf
import numpy as np

if __name__ == '__main__':
    x = np.random.uniform(low=-1.0, high=1.0, size=(20,1))
    y = x

    input = tx = tf.Variable(initial_value=x)
    is_training = tf.Variable(initial_value=False)
    tx = tf.layers.batch_normalization(tx, training=is_training)
    output = tx
    train_output = tf.placeholder(tf.float32, shape=(None, 1))

    update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
    loss = tf.losses.mean_squared_error(train_output, output)
    train_op = tf.train.MomentumOptimizer(learning_rate=0.01, momentum=0.9).minimize(loss)
    train_op = tf.group([train_op, update_ops])

    sess = tf.Session()
    sess.run(tf.global_variables_initializer())

    is_training.load(False, sess)
    py = sess.run(output)
    print("py", py)
    print("mse", np.mean(np.square(py - x)))

    print("training...")
    for i in range(2000):
        is_training.load(True, sess)
        sess.run(train_op, {train_output: y})

        is_training.load(False, sess)
        py = sess.run(output)
        print("step", i, "mse", np.mean(np.square(py - x)))

    is_training.load(False, sess)
    py = sess.run(output)
    print("mse", np.mean(np.square(py - x)))

我希望Keras和Tensorflow的结果相似。但是Keras代码最后会打印出约0.0002的MSE错误,而在训练过程中损失约1e-12。 Tensorflow代码为训练和测试提供了一种更低的误差,大约为1e-16。 Tensorflow结果是预期结果,因为学习恒等函数应该是微不足道的,并且一旦BN的移动平均值和方差收敛,在整个训练/测试中结果应该是相同的。

为什么会这样?为什么Tensorflow和Keras之间的行为不一致,如何使用纯Keras获得较低的错误?对情况有任何见识将不胜感激。

0 个答案:

没有答案