
在 Jupyter 中多次调用 Keras 模型训练时,若仅依赖 clear_session() 但未重置数据预处理层(如 normalizer),会导致后续训练使用过期统计量、权重污染或图状态残留,从而模型无法收敛或性能骤降。
在 jupyter 中多次调用 keras 模型训练时,若仅依赖 clear_session() 但未重置数据预处理层(如 normalizer),会导致后续训练使用过期统计量、权重污染或图状态残留,从而模型无法收敛或性能骤降。
问题的核心并非“Keras 只能运行一次”,而是状态残留——尤其是 normalizer.adapt(X_train) 的副作用被严重低估。
在您提供的代码中,normalizer 是一个 tf.keras.layers.Normalization 层(或类似预处理层),它会在首次调用 .adapt() 时内部计算并固化 mean 和 std。但关键在于:.adapt() 不会自动重置其内部状态。因此,当第二次进入 nn_fit() 时:
-
normalizer仍保留第一次adapt()所得的均值/标准差; - 若第二次传入的
X_train(例如不同平滑程度的q)分布显著不同(如方差更小、范围偏移),归一化后输入将严重失真; - 模型虽重建(
clear_session()有效),但输入数据已“错配”,导致梯度异常、loss 不下降、NSE 持续低于阈值——表面无报错,实则训练失效。
✅ 正确做法:每次训练前,必须显式重置 normalizer 状态。不能仅靠 clear_session()。
✅ 修复方案(三步关键操作)
-
重实例化
normalizer(推荐)
将normalizer创建移入循环内,确保每次训练使用全新、干净的归一化层:for mode in reof_ds.mode.values: keras.backend.clear_session() print('Building models for mode-'+str(mode).zfill(2)) # ✅ 关键修复:每次新建 normalizer,避免状态污染 normalizer = tf.keras.layers.Normalization(axis=-1) # 或按需配置 input_shape tpc = reof_ds.temporal_modes.sel(mode=int(mode)) X = q.values.reshape(-1, 1) Y = tpc.values.reshape(-1, 1) X_train = X Y_train = Y # ✅ 现在 adapt 是安全的:作用于全新 normalizer normalizer.adapt(X_train) model = build_and_compile_model(normalizer) # ... 训练、评估、保存 ... -
若
normalizer需复用(如跨模式共享统计量),则显式重置# 在循环开始前初始化 normalizer = tf.keras.layers.Normalization(axis=-1) for mode in reof_ds.mode.values: keras.backend.clear_session() # ✅ 强制清除 normalizer 内部状态(适用于 TF ≥ 2.10+) normalizer.reset_state() # ⚠️ 注意:此方法在旧版 TF 中不可用 # 或更兼容的方式:重新调用 adapt 并确保输入为当前数据 normalizer.adapt(X_train) # ✅ adapt 本身会覆盖旧统计量,但前提是 normalizer 未被 compile 过 -
补充健壮性措施
- 移除冗余
del:Python 的局部变量在函数退出时自动回收,del对内存释放帮助极小,反而降低可读性; - 避免全局
normalizer:将其作为函数参数传入,或在build_and_compile_model()内部创建,杜绝隐式状态耦合; - 添加调试检查:
print(f"Mode {mode}: X_train range = [{X_train.min():.3f}, {X_train.max():.3f}], " f"normalizer.mean = {normalizer.mean.numpy().flatten()}, " f"normalizer.variance = {normalizer.variance.numpy().flatten()}")
- 移除冗余
? 总结
| 问题现象 | 根本原因 | 解决动作 |
|---|---|---|
| 第二次训练 NSE 极低 |
normalizer 复用首次统计量,导致归一化失真 |
每次循环新建 normalizer 或显式 reset_state()
|
clear_session() 无效 |
它只清计算图与权重,不清理 layer 的统计状态 |
clear_session() 必须配合预处理层重置 |
| 需要多组平滑对比实验 | 各组 q 分布差异大,要求独立归一化 |
每组数据对应独立 normalizer.adapt()
|
遵循以上修正后,您即可在单次 Notebook 运行中无缝完成「无平滑」「轻度平滑」「重度平滑」等多组神经网络建模与 NSE 对比分析,无需重启内核,真正实现可复现、可迭代的科学计算流程。










