TensorFlow跨环境加载DCN排序模型权重预测结果不一致及模型完整保存问题求解
这个问题我之前在做推荐排序模型时也碰到过,结合你的场景,咱们一步步拆解解决:
一、先搞定Colab与本地预测结果不一致的问题
虽然你已经对齐了TF相关库的版本,但还有几个容易忽略的点会导致结果差异:
- 固定所有随机种子:训练和预测过程中的随机性是最大的“隐形坑”。不管是Colab训练还是本地预测,都要在代码开头设置全局随机种子,确保初始化、dropout、数据 shuffle 等操作的一致性:
import tensorflow as tf import numpy as np import random # 固定基础随机种子 tf.random.set_seed(42) np.random.seed(42) random.seed(42) # 如果用GPU,强制开启确定性运算(避免GPU并行带来的随机差异) tf.config.experimental.enable_op_determinism()
确保模型结构完全复刻:子类模型(比如你用的DCN)对结构一致性要求极高,本地定义的模型必须和Colab中训练时的模型完全一致——包括所有层的参数、命名、顺序,甚至是
__init__和call方法里的每一行逻辑,哪怕是变量名改了都可能导致权重加载错位。统一计算精度:Colab通常用GPU(可能默认FP16混合精度),本地如果用CPU,浮点数计算精度可能有细微差别。可以强制两边都用FP32精度:
tf.keras.mixed_precision.set_global_policy('float32')
二、正确保存/加载子类模型(解决SavedModel警告和序列化问题)
你的DCN模型属于子类模型(继承tf.keras.Model自定义的),所以HDF5(.h5)和to_json方法确实不支持,这是TensorFlow的设计限制。不过用SavedModel格式是完全可行的,只要解决untraced functions的警告:
保存模型(Colab端)
在保存前,先给模型喂一个和实际输入形状一致的dummy样本,让TensorFlow追踪到所有自定义函数的计算图:
# 生成符合你模型输入形状的假数据(替换成你的实际输入维度) # 比如你的模型输入是(None, 100)的特征向量,就生成(1, 100)的dummy dummy_input = tf.random.uniform(shape=(1, 你的输入特征数量)) # 前向传播一次,让TF追踪计算图 _ = model(dummy_input) # 保存为SavedModel格式 model.save('dcn_ranking_model')
这样保存的模型就不会有untraced functions的警告,加载后可以直接调用。
加载模型(本地端)
不需要重新定义模型结构,直接加载即可:
loaded_model = tf.keras.models.load_model('dcn_ranking_model') # 验证:用相同输入测试 test_input = ... # 你之前用的测试输入 print(loaded_model(test_input))
三、如果坚持用权重文件(save_weights/load_weights)
如果还是不想用SavedModel,那必须保证本地模型在加载权重前已经完成构建:
# 本地定义完模型后,先喂dummy input构建模型 dummy_input = tf.random.uniform(shape=(1, 你的输入特征数量)) _ = model(dummy_input) # 再加载权重 model.load_weights('your_weights_path')
因为子类模型在未进行前向传播前,层的参数是未初始化的,直接加载权重可能导致权重分配错误。
补充说明
为什么HDF5和to_json不行?因为子类模型的逻辑是写在Python方法(比如call)里的,这种动态代码无法被HDF5格式安全序列化,而SavedModel会同时保存计算图和权重,是TensorFlow官方推荐的子类模型保存方式。
内容的提问来源于stack exchange,提问作者Meghana S

