加载H5格式CNN模型后继续训练时遇到Eager Execution相关报错问题
看起来你遇到的问题有点棘手——明明日志显示Eager Execution已经启用,但加载现有H5模型后调用model.fit()时还是触发了numpy() is only available when eager execution is enabled的报错。结合你的代码和报错信息,我来帮你分析可能的原因和解决办法:
可能的原因分析
这个报错的核心矛盾点在于:当前环境确实是Eager模式,但代码中某一步在尝试将图模式张量转换为Numpy数组(图张量在非Eager模式下无法调用numpy())。结合你的代码逻辑,问题大概率出在两个地方:
- 加载的H5模型中保存的优化器状态是在图模式下序列化的,加载到Eager环境后无法正常兼容;
- 加载现有模型时重新读取的数据集
x_train/y_train不是Numpy数组,而是图模式生成的张量。
具体解决办法
1. 重新编译加载的模型,避免优化器兼容性问题
当你用tf.keras.models.load_model()加载保存的H5模型时,模型会连同之前的优化器状态一起加载。如果模型是在图模式下保存的(或者优化器是在图模式下初始化的),即使当前环境是Eager,优化器的状态也可能无法正确适配,导致fit()过程中触发张量转换错误。
修改你加载模型的代码,显式禁用自动编译,然后在当前Eager环境下重新编译模型:
if USE_EXISTING_MODELS and os.path.exists(f"models/{model_name}.h5"): # 加载模型但不自动编译,避免旧优化器状态的兼容性问题 model = tf.keras.models.load_model(f"models/{model_name}.h5", compile=False) # 根据你的任务需求重新编译模型(这里假设是分类任务,可根据实际情况调整) model.compile( optimizer="adam", # 或者你原来用的优化器,比如SGD loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), # 对应你的任务损失函数 metrics=["accuracy"] ) # 读取数据集 (x_train, y_train), (x_test, y_test) = model_handler.load_data() else: # 原来的模型创建逻辑保持不变 if model_name == "base_model": model = model_handler.create_cnn() else: model = model_handler.create_cnn(batch_normalisation=True)
2. 确保加载的数据集是Numpy数组
在加载现有模型的分支里,你重新调用了model_handler.load_data(),要确保这个方法返回的是Numpy数组,而不是TensorFlow的图模式张量。如果你的数据加载逻辑是基于图模式的(比如用tf.data.Dataset且没有转换为Numpy),可以显式将数据转换为Numpy数组:
# 在加载数据后添加转换逻辑 (x_train, y_train), (x_test, y_test) = model_handler.load_data() # 转换为Numpy数组(确保在Eager模式下执行) x_train = tf.convert_to_tensor(x_train).numpy() y_train = tf.convert_to_tensor(y_train).numpy() x_test = tf.convert_to_tensor(x_test).numpy() y_test = tf.convert_to_tensor(y_test).numpy()
3. 修正代码中的小笔误
你的代码里有个重复赋值的小问题:model = model = tf.keras.models.load_model(...),虽然不影响运行,但还是建议改成model = tf.keras.models.load_model(f"models/{model_name}.h5"),保持代码整洁。
验证修改效果
修改完成后,重新运行代码:
- 确保日志依然输出
Eager enabled: True; - 加载现有模型后调用
model.fit()时,应该不会再触发numpy()相关的报错; - 训练完成后,模型依然可以正常保存为H5格式。
备注:内容来源于stack exchange,提问作者Arief Kurniawan

