TensorFlow.Keras模型分两次训练与单次训练结果不一致的疑问
问题原因分析
你遇到的两次训练结果不一致的核心原因是两次model.fit()调用时,数据shuffle的随机序列生成逻辑不同,结合Adam优化器的自适应特性,最终导致权重更新轨迹出现差异。
具体拆解:
前3个epoch结果一致的原因
由于你固定了np.random.seed(42)和tf.random.set_seed(42),模型初始化参数、前3个epoch的训练数据shuffle序列、优化器的初始更新逻辑完全一致,因此前3个epoch的loss输出完全匹配。后续epoch结果不同的关键
- 代码1中,两次调用
model.fit()时,TensorFlow会重新构建输入数据管道(将numpy数组转为tf.data.Dataset)。在TensorFlow 2.2/2.3版本中,全局种子固定的情况下,新构建的Dataset会重复使用相同的shuffle随机序列——也就是说,代码1的第4个epoch(第二次fit的第1个epoch)使用的训练数据顺序,和第1个epoch完全相同。 - 代码2中,单次
fit(epochs=6)使用的是同一个输入管道,每个epoch的shuffle序列是连续生成的,第4-6个epoch的训练数据顺序是全新的、和前3个epoch不同的。 - Adam是自适应优化器,其更新依赖于之前迭代积累的梯度动量(
m和v参数)。相同的模型状态下,不同的训练数据顺序会产生不同的梯度,进而导致权重更新的方向和幅度不同,最终loss结果出现差异。
- 代码1中,两次调用
验证与解决方法
如果要让两次训练结果一致,可以手动创建固定shuffle逻辑的Dataset,确保两次fit调用使用同一个数据管道:
keras.backend.clear_session() np.random.seed(42) tf.random.set_seed(42) optimizer = tf.keras.optimizers.Adam(lr=1e-2) model = keras.models.Sequential([keras.layers.Dense(1, input_shape=[8])]) model.compile(loss="mse", optimizer=optimizer) # 手动构建Dataset,固定shuffle种子并开启每轮重洗牌 train_dataset = tf.data.Dataset.from_tensor_slices((X_train_scaled, y_train)) train_dataset = train_dataset.shuffle( buffer_size=len(X_train_scaled), seed=42, reshuffle_each_epoch=True ).batch(32) model.fit(train_dataset, epochs=3) model.fit(train_dataset, epochs=3)
此时两次fit调用会共享同一个Dataset的shuffle序列,训练轨迹会和代码2完全一致。
内容的提问来源于stack exchange,提问作者Pascal
相关产品推荐
相关产品推荐

