如何让Keras EarlyStopping使用未训练模型的验证损失而非Inf
解决方法
要实现让EarlyStopping初始使用未训练模型的验证损失,核心思路是先提前计算未训练模型的验证损失,再替换EarlyStopping的初始基准值,同时配合保存初始模型,具体步骤如下:
1. 计算未训练模型的验证损失
在开始训练前,先初始化你的模型,然后直接在验证集上评估它的损失,这就是未训练模型的基准损失:
# 初始化你的模型(替换成你实际的模型构建代码) model = create_your_model() # 在验证集上评估未训练模型的损失(val_dataset是你的验证数据集) val_loss_untrained = model.evaluate(val_dataset, verbose=0)[0]
2. 自定义EarlyStopping回调,替换初始基准
默认的EarlyStopping会把初始best值设为Inf(损失类指标),我们可以继承它,重写训练开始时的逻辑,把初始best值改成刚才计算的未训练模型损失:
from tensorflow.keras.callbacks import EarlyStopping class CustomEarlyStopping(EarlyStopping): def __init__(self, initial_best, **kwargs): super().__init__(**kwargs) self.initial_best = initial_best def on_train_begin(self, logs=None): # 先调用父类的初始化逻辑 super().on_train_begin(logs) # 把初始最优损失替换成未训练模型的损失 self.best = self.initial_best # 记录初始最优轮次为0 self.best_epoch = 0
3. 提前保存未训练模型(配合ModelCheckpoint)
默认的ModelCheckpoint只会在训练轮次结束后保存模型,所以我们需要手动先保存未训练的轮次0模型,确保后续如果第一轮训练效果更差时,能保留这个最优版本:
from tensorflow.keras.callbacks import ModelCheckpoint # 先保存未训练的轮次0模型 model.save('best_model_epoch_0.h5') # 初始化ModelCheckpoint,设置只保存最优模型 checkpoint = ModelCheckpoint( 'best_model.h5', monitor='val_loss', save_best_only=True, mode='min', verbose=1 )
4. 组装回调并开始训练
把自定义的EarlyStopping和ModelCheckpoint传入训练流程:
# 实例化自定义早停回调,传入初始基准损失 early_stop = CustomEarlyStopping( initial_best=val_loss_untrained, monitor='val_loss', patience=3, # 按你的需求设置 patience mode='min', verbose=1, restore_best_weights=True # 训练结束后自动恢复最优权重 ) # 开始训练 history = model.fit( train_dataset, validation_data=val_dataset, epochs=50, # 你的总训练轮次 callbacks=[checkpoint, early_stop] )
效果说明
这样设置后:
- 如果第一轮训练后的验证损失比未训练模型的损失高,EarlyStopping会判定这没有提升,最优轮次保持为0,
restore_best_weights会恢复到未训练模型的权重,ModelCheckpoint也不会覆盖之前保存的轮次0模型。 - 如果第一轮训练后的验证损失更低,就会正常更新最优模型和轮次。
内容的提问来源于stack exchange,提问作者xxxyyy
相关产品推荐
相关产品推荐

