TensorFlow带TimeDistributed封装模型的保存与加载问题求助
解决TimeDistributed包裹预训练模型的保存与加载问题
错误原因
你遇到的ValueError: Cannot convert '16' to a shape是因为:
- 模型未明确指定输入形状,导致TimeDistributed层序列化时丢失了序列维度(16)的关键信息
- 预训练EfficientNetB0未绑定固定输入形状,加载时Keras无法正确推断TimeDistributed的输入维度
修正后的模型定义
首先需要明确输入形状并完成模型构建,确保所有层的形状信息被正确记录:
import tensorflow as tf # 预训练模型指定单帧输入形状 net = tf.keras.applications.EfficientNetB0(include_top=False, input_shape=(224, 224, 3)) net.trainable = False # Sequential模型开头明确完整输入形状 model = tf.keras.Sequential([ tf.keras.layers.Input(shape=(16, 224, 224, 3)), tf.keras.layers.Rescaling(scale=1/255), # 修正:将0-255像素归一化到0-1,符合EfficientNet输入要求 tf.keras.layers.TimeDistributed(net), tf.keras.layers.GlobalAveragePooling3D(), # 先做3D全局平均池化,再连接全连接层 tf.keras.layers.Dense(10) ]) # 强制模型完成构建(可选,也可以用样例输入触发) model.build((None, 16, 224, 224, 3))
方法1:完整模型保存与加载(推荐)
修正模型后,使用Keras原生的完整保存方法即可正常加载:
# 保存模型 model.save('video_classifier.keras') # 加载模型 loaded_model = tf.keras.models.load_model('video_classifier.keras') # 验证加载结果 dummy_input = tf.random.normal((1, 16, 224, 224, 3)) print(loaded_model(dummy_input).shape) # 输出应为 (1, 10)
方法2:JSON结构+权重分离保存与加载
如果需要分离保存结构和权重,确保模型已完成构建后再序列化:
# 保存结构与权重 model_json = model.to_json() with open("video_classifier.json", "w") as json_file: json_file.write(model_json) model.save_weights("video_classifier.weights.h5") # 加载结构与权重 from tensorflow.keras.models import model_from_json json_file = open('video_classifier.json', 'r') loaded_model_json = json_file.read() json_file.close() loaded_model = model_from_json(loaded_model_json) loaded_model.load_weights("video_classifier.weights.h5") # 验证加载结果 dummy_input = tf.random.normal((1, 16, 224, 224, 3)) print(loaded_model(dummy_input).shape) # 输出应为 (1, 10)
额外注意事项
- 原模型中
Dense(10)放在GlobalAveragePooling3D()之前虽然不会报错,但先池化再做全连接更符合常规视频分类模型的结构,且能减少计算量 Rescaling层的scale参数需修正为1/255,否则会将像素值放大到不合理范围,影响模型推理结果
内容的提问来源于stack exchange,提问作者Mohammed Khan
相关产品推荐
相关产品推荐

