应在外层用 try...except 捕获 KeyboardInterrupt、RuntimeError(如OOM)、ValueError(如NaN)并在异常时保存模型,同时结合 SafeSaveCallback 实现周期性保存和 on_train_error 异常捕获,并配合 ModelCheckpoint 与 .keras 格式推荐使用。

捕获 tf.keras.Model.fit() 中的 KeyboardInterrupt 和训练崩溃
TensorFlow 训练中途被 Ctrl+C 中断,或因 OOM、NaN 梯度等意外退出时,默认不保存模型。关键是要在异常传播前介入,而不是依赖训练结束后的回调。
最直接的方式是用 try...except 包裹 model.fit() 调用,并在 except 和 finally 中主动调用保存逻辑:
try:
history = model.fit(x_train, y_train, epochs=100, callbacks=[...])
except (KeyboardInterrupt, RuntimeError, ValueError) as e:
print(f"Training interrupted: {e}")
model.save("model_interrupted.h5") # 或 save_weights_only=True
finally:
# 即使没异常,也建议在最后再存一次(防 fit 内部静默失败)
model.save("model_final.h5")注意:RuntimeError 常见于 GPU 显存耗尽;ValueError 可能由 NaN loss 触发(尤其开启 tf.debugging.enable_check_numerics() 后)。
用 tf.keras.callbacks.Callback 实现自动快照
手动捕获只管“终局”,但训练跑几十小时,中间出问题就全白干。必须靠回调做周期性保存——不是等训练完,而是每 N 个 epoch 就落盘一次。
立即学习“Python免费学习笔记(深入)”;
自定义回调比内置 ModelCheckpoint 更灵活,能响应异常事件:
class SafeSaveCallback(tf.keras.callbacks.Callback):
def __init__(self, filepath, save_weights_only=False):
self.filepath = filepath
self.save_weights_only = save_weights_only
<pre class='brush:python;toolbar:false;'>def on_train_batch_end(self, batch, logs=None):
# 可选:每 batch 保存(仅调试用,I/O 开销大)
pass
def on_epoch_end(self, epoch, logs=None):
self.model.save(self.filepath.format(epoch=epoch),
save_weights_only=self.save_weights_only)
def on_train_end(self, logs=None):
self.model.save(self.filepath.format(epoch="final"))
def on_train_error(self, error):
# TensorFlow 2.11+ 支持该钩子,捕获 fit 内部抛出的异常
print(f"Train error caught: {error}")
self.model.save(self.filepath.format(epoch="error"))</pre>使用时传入:model.fit(..., callbacks=[SafeSaveCallback("model_ep{epoch}.h5")])。注意 on_train_error 在较新 TF 版本才可用,旧版本需退回到外层 try/catch。
ModelCheckpoint 的陷阱:它不处理训练中断
很多人以为加了 tf.keras.callbacks.ModelCheckpoint 就万无一失,其实不然——它只在 on_epoch_end 触发,对 KeyboardInterrupt 或训练中途崩溃完全无感知。
常见误配置:
- 设
save_best_only=True但没配monitor→ 从不保存 - 路径写成
"./checkpoints/model"却没确保目录存在 → 静默失败 - 用
save_weights_only=True但后续加载时忘了调用model.load_weights()→ 加载报错ValueError: Unable to load weights...
真正保险的做法是:ModelCheckpoint + 外层 try/except + 自定义错误回调三者并存,覆盖不同失败粒度。
保存格式选 .keras 还是 .h5?
TensorFlow 2.12+ 默认推荐 .keras 格式(Keras-native),它序列化更完整(含自定义层、损失函数、甚至部分训练状态),且不依赖 HDF5 库。
但要注意兼容性:
- 用
model.save("model.keras")保存后,必须用tf.keras.models.load_model("model.keras")加载,不能混用load_weights - 若模型含非标准对象(如未注册的自定义
tf.keras.layers.Layer子类),.keras会保存失败,报错NotImplementedError: Saving the model to HDF5 format requires the model to be a Functional model or a Sequential model - 老项目依赖
.h5的,可继续用,但需确保环境装了h5py,否则model.save("x.h5")报错ImportError: Unable to import h5py
多机训练、断点续训场景下,权重文件(save_weights_only=True)比完整模型更轻量、更易校验一致性,但得自己维护优化器状态——这点常被忽略。


















