You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Keras技术问询:如何在观测到最优(最低)指标时终止训练,不用patience耗尽后状态?

在Keras中终止于最优指标轮次并保留最优权重

我完全懂你的需求——不想耗着等patience用完,也不想最后拿到指标变差后的模型,就是要精准卡在观测到最优val_loss的那个训练轮次停止,并且直接用那个轮次的模型状态对吧?

下面给你两种靠谱的实现方式,按需选择:

方法一:自定义回调函数(精准控制,完全匹配需求)

如果你的目标是要么在得到最优指标的瞬间立刻停训,要么一旦后续指标没提升就停并自动恢复最优权重,自定义回调是最灵活的方案。

这里给你写一个针对val_loss的示例回调,逻辑清晰还能自定义停止规则:

import tensorflow as tf
from tensorflow import keras

class StopAtBestLoss(keras.callbacks.Callback):
    def __init__(self, monitor='val_loss', mode='min'):
        super().__init__()
        self.monitor = monitor
        self.mode = mode
        # 根据指标类型初始化最优值(loss越小越好,acc越大越好)
        self.best_score = float('inf') if mode == 'min' else -float('inf')
        self.best_weights = None

    def on_epoch_end(self, epoch, logs=None):
        current_score = logs.get(self.monitor)
        if not current_score:
            return
        
        # 判断当前是否刷新了最优指标
        is_best = (self.mode == 'min' and current_score < self.best_score) or \
                  (self.mode == 'max' and current_score > self.best_score)
        
        if is_best:
            # 更新最优值并保存当前模型权重
            self.best_score = current_score
            self.best_weights = self.model.get_weights()
            print(f"\nEpoch {epoch+1}: {self.monitor}刷新最优值 {self.best_score:.6f},已保存权重")
            # 如果你想拿到最优值后立刻停训,就解开下面这行注释
            # self.model.stop_training = True
        else:
            # 如果指标没提升,立刻停训并恢复最优权重
            print(f"\nEpoch {epoch+1}: {self.monitor}未超越最优值 {self.best_score:.6f},终止训练")
            self.model.set_weights(self.best_weights)
            self.model.stop_training = True

使用方式:

训练时把这个回调加到callbacks列表里就行:

# 假设你已经定义好模型并完成编译
model.compile(optimizer='adam', loss='mse', metrics=['mae'])

# 初始化回调,val_loss用min模式(越小越好)
stop_callback = StopAtBestLoss(monitor='val_loss', mode='min')

# 开始训练,epochs设大一点,让回调决定何时停止
history = model.fit(
    x_train, y_train,
    epochs=1000,
    validation_split=0.2,
    callbacks=[stop_callback]
)

逻辑说明:

  • 若把停止逻辑放在最优更新分支:只要某个epoch的val_loss刷新了历史最低,训练会立刻停止,直接保留这个最优状态。适合你确定“这个就是最优,没必要继续训”的场景。
  • 若把停止逻辑放在未提升分支:训练会持续进行,直到某个epoch的val_loss不如之前的最优值,此时立刻停训并自动恢复到最优权重。这种方式更稳妥,既不会浪费算力,又能保证拿到最好的模型。

方法二:巧用内置EarlyStopping(简洁高效)

其实Keras自带的EarlyStopping回调已经能搞定类似需求,只要调整两个参数,就能实现“不等patience,指标一不提升就停,自动恢复最优权重”:

from tensorflow.keras.callbacks import EarlyStopping

early_stop = EarlyStopping(
    monitor='val_loss',
    patience=0,  # 没有等待次数,只要一次不提升就停
    mode='min',
    restore_best_weights=True  # 停训后自动加载最优权重
)

# 训练时加入回调即可
history = model.fit(
    x_train, y_train,
    epochs=1000,
    validation_split=0.2,
    callbacks=[early_stop]
)

注意点:

这个方法的逻辑是:当某个epoch的val_loss没刷新历史最优时,立刻停训,然后自动把模型恢复到最优指标的那个轮次状态。和自定义回调的第二种逻辑完全一致,优点是不用自己写代码,简洁省心。但如果你的需求是“拿到最优值的瞬间就停”,那内置回调做不到,必须用自定义方案。

总结

  • 要在出现最优指标的epoch直接停训:选自定义回调,把停止逻辑放在最优更新分支。
  • 要允许模型尝试后续epoch,但指标一降就停并恢复最优权重:用内置EarlyStopping设置patience=0和restore_best_weights=True,简单高效。

两种方式都能完美避开“用patience耗尽后的差模型”的问题,完全符合你的要求。

内容的提问来源于stack exchange,提问作者Khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:33:15