K折交叉验证训练深度学习回归模型时Early stopping的val_loss未重置问题
问题原因与解决方案
核心错误原因
你将EarlyStopping和ModelCheckpoint两个回调的实例定义在了K折循环的外部,Keras的回调对象会在自身属性中保存所有运行状态:
- 早停回调会保存历史最优val_loss、剩余等待轮次计数
- 模型保存回调会保存历史最优val_loss、上次保存的权重文件记录
这些状态都是Python层面的实例属性,你调用的clear_session只会清空TensorFlow/Keras的计算图、模型权重、会话资源,完全不会改动回调实例的内部状态,所以新一折训练时会直接沿用之前折的最优val_loss做判断,才会出现第一轮就提示val_loss未优于历史最优的问题。
修复方法
将两个回调的实例化逻辑移动到K折循环内部,每折训练前生成全新的回调实例即可自动重置所有状态,同时建议给每折的权重文件设置独立命名,避免不同折的最优权重互相覆盖:
for k in range(0,5): keras.backend.clear_session() tf.keras.backend.clear_session() trainInputsAll, trainTargets, trainMeta, testInputsAll, testTargets, testMeta = merge_splits(inputsK, targetsK, metaK, k) # 原有数据预处理逻辑保持不变 train_graphinput = graph_input[0:length_size_max,:,:] train_graphfeatureinput = graph_features[0:length_size_max,:,:] test_graphinput = graph_input[0:length_size_min,:,:] test_graphfeatureinput = graph_features[0:length_size_min,:,:] trainInputs, trainMaxes = normalize(trainInputsAll[:, :, :, :]) testInputs, testMaxes = normalize(testInputsAll[:, :, :, :]) model = build_model(testInputs[0].shape) # ===== 新增:每折重新实例化回调,重置所有状态 ===== # 文件名加入折数标识,避免不同折权重覆盖 model_checkpoint = keras.callbacks.ModelCheckpoint(f'models/graph_model_fold_{k}.h5', monitor='val_loss',verbose=1, save_best_only=True) es = keras.callbacks.EarlyStopping(patience=10, verbose=1, min_delta=0.001, monitor='val_loss', mode='min',baseline=None) print(model.summary()) history = model.fit(x=[trainInputs, trainMaxes, train_graphinput,train_graphfeatureinput], y=targets_to_list(trainTargets), epochs=100, batch_size=30, validation_data=([testInputs, testMaxes,test_graphinput,test_graphfeatureinput], targets_to_list(testTargets)),verbose=0,callbacks=[model_checkpoint,es]) # 加载当前折的最优权重 model.load_weights(f'models/graph_model_fold_{k}.h5') # 后续评估逻辑保持不变
如果不需要保留每折的权重文件,也可以保持原文件名不变,只要保证每折重新实例化回调即可正常运行。
内容的提问来源于stack exchange,提问作者intStdu
相关产品推荐
相关产品推荐

