Python 即使使用相同的数据(逻辑回归),Keras序列和验证度量值也不同

Python 即使使用相同的数据(逻辑回归),Keras序列和验证度量值也不同,python,tensorflow,machine-learning,keras,deep-learning,Python,Tensorflow,Machine Learning,Keras,Deep Learning,我一直在努力更好地理解kerasmodelfit()循环中的训练/验证序列。因此,我尝试了一个简单的训练循环,尝试用一个单一特征组成的输入数据拟合一个简单的逻辑回归模型 我为培训和验证提供了相同的数据。在这些条件下,通过指定批大小与总数据大小相同,可以期望获得完全相同的损失和准确性。但事实并非如此 这是我的密码: 使用两个类生成两个随机数据: N = 100 x = np.concatenate([np.random.randn(N//2, 1), np.random.randn(N//2, 1

我一直在努力更好地理解
keras
model
fit()
循环中的训练/验证序列。因此,我尝试了一个简单的训练循环,尝试用一个单一特征组成的输入数据拟合一个简单的逻辑回归模型

我为培训验证提供了相同的数据。在这些条件下,通过指定批大小与总数据大小相同,可以期望获得完全相同的损失和准确性。但事实并非如此

这是我的密码:

使用两个类生成两个随机数据:

N = 100
x = np.concatenate([np.random.randn(N//2, 1), np.random.randn(N//2, 1)+2])
y = np.concatenate([np.zeros(N//2), np.ones(N//2)])
并绘制两类数据分布图(一个特征x):

构建并安装keras模型:

model = tf.keras.Sequential([tf.keras.layers.Dense(1, activation='sigmoid', input_dim=1)])
model.compile(optimizer=tf.keras.optimizers.SGD(2), loss='binary_crossentropy', metrics=['accuracy'])
model.fit(x, y, epochs=10, validation_data=(x, y), batch_size=N)
请注意,我已经为培训和验证数据指定了数据
x
和目标
y
。此外,批次大小与总大小相同
batch\u size=N

培训结果如下:

100/100 [==============================] - 1s 5ms/step - loss: 1.4500 - acc: 0.2300 - val_loss: 0.5439 - val_acc: 0.7200
Epoch 2/10
100/100 [==============================] - 0s 18us/step - loss: 0.5439 - acc: 0.7200 - val_loss: 0.4408 - val_acc: 0.8000
Epoch 3/10
100/100 [==============================] - 0s 16us/step - loss: 0.4408 - acc: 0.8000 - val_loss: 0.3922 - val_acc: 0.8300
Epoch 4/10
100/100 [==============================] - 0s 16us/step - loss: 0.3922 - acc: 0.8300 - val_loss: 0.3659 - val_acc: 0.8400
Epoch 5/10
100/100 [==============================] - 0s 17us/step - loss: 0.3659 - acc: 0.8400 - val_loss: 0.3483 - val_acc: 0.8500
Epoch 6/10
100/100 [==============================] - 0s 16us/step - loss: 0.3483 - acc: 0.8500 - val_loss: 0.3356 - val_acc: 0.8600
Epoch 7/10
100/100 [==============================] - 0s 17us/step - loss: 0.3356 - acc: 0.8600 - val_loss: 0.3260 - val_acc: 0.8600
Epoch 8/10
100/100 [==============================] - 0s 18us/step - loss: 0.3260 - acc: 0.8600 - val_loss: 0.3186 - val_acc: 0.8600
Epoch 9/10
100/100 [==============================] - 0s 18us/step - loss: 0.3186 - acc: 0.8600 - val_loss: 0.3127 - val_acc: 0.8700
Epoch 10/10
100/100 [==============================] - 0s 23us/step - loss: 0.3127 - acc: 0.8700 - val_loss: 0.3079 - val_acc: 0.8800
结果表明,val_损失val_损失在每个时期结束时都不相同,accval_acc也不完全相同。然而,基于这种设置,人们期望它们是相同的

我已经阅读了keras中的代码,特别是这一部分:

到目前为止,我所能说的差异是由于通过计算图进行了不同的计算


有人知道为什么会有这种差异吗?

因此,在更仔细地观察结果之后,在使用当前批次更新模型之前,将计算训练步骤中的
损失
acc

因此,在每个历元一个批次的情况下,当该批次输入时,对序列
acc
loss
进行评估,然后根据提供的优化器更新模型参数。训练步骤完成后,我们通过输入验证数据来计算损失和精度,现在使用新的更新模型对验证数据进行评估

这从训练结果输出中可以明显看出,其中第1纪元的验证精度和损失等于第2纪元的训练精度和损失,等等

使用tensorflow进行快速检查,确认在更新变量之前已获取值:

import tensorflow as tf
import numpy as np
np.random.seed(1)

x = tf.placeholder(dtype=tf.float32, shape=(None, 1), name="x")
y = tf.placeholder(dtype=tf.float32, shape=(None), name="y")

W = tf.get_variable(name="W", shape=(1, 1), dtype=tf.float32, initializer=tf.constant_initializer(0))
b = tf.get_variable(name="b", shape=1, dtype=tf.float32, initializer=tf.constant_initializer(0))
z = tf.matmul(x, W) + b

error = tf.square(z - y)
obj = tf.reduce_mean(error, name="obj")

opt = tf.train.MomentumOptimizer(learning_rate=0.025, momentum=0.9)
grads = opt.compute_gradients(obj)
train_step = opt.apply_gradients(grads)

N = 100
x_np = np.random.randn(N).reshape(-1, 1)
y_np = 2*x_np + 3 + np.random.randn(N)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for i in range(2):
        res = sess.run([obj, W, b, train_step], feed_dict={x: x_np, y: y_np})
        print('MSE: {}, W: {}, b: {}'.format(res[0], res[1][0, 0], res[2][0]))
输出:

MSE: 14.721437454223633, W: 0.0, b: 0.0
MSE: 13.372591018676758, W: 0.08826743811368942, b: 0.1636980175971985
由于参数
W
b
已初始化为0,因此很明显,即使使用梯度更新请求运行会话,获取的值仍为0

MSE: 14.721437454223633, W: 0.0, b: 0.0
MSE: 13.372591018676758, W: 0.08826743811368942, b: 0.1636980175971985