TF2.6自定义迁移学习模型已调用build仍提示输入形状未设置无法保存如何解决
报错根因
ValueError: Model
<__main__.MyModel object at 0x7fc66134bdd0>cannot be saved because the input shapes have not been set.
该报错的核心原因是:TensorFlow 对tf.keras.Model子类实现的自定义模型,仅在__init__中调用build()方法不会完整记录模型的输入签名元数据,SavedModel格式保存要求模型有明确的前向传播跟踪记录,仅靠build无法满足这个要求。
可行解决方案
以下两个方案任选其一即可:
- 方案1:执行一次dummy前向传播
实例化模型后,传入一个符合输入形状的随机张量触发一次前向计算,不需要调用fit或predict,即可让模型完整记录输入形状信息:model = MyModel(input_shape=(256, 256, 3)) # 新增这一行,传入batch_size为1的随机输入触发前向传播 _ = model(tf.random.uniform((1, 256, 256, 3))) model.save('./saved') - 方案2:保存时显式指定输入签名
如果不想执行额外的前向传播,也可以在调用save方法时手动指定输入签名:model = MyModel(input_shape=(256, 256, 3)) model.save( './saved', signatures=model.call.get_concrete_function( tf.TensorSpec(shape=(None, 256, 256, 3), dtype=tf.float32) ) )
代码优化建议
你当前把self.weight_dict['backbone'].trainable = False写在了call方法里,会导致每一次前向传播都重复设置backbone的可训练属性,建议挪到__init__方法中,调整后逻辑更规范:
def __init__(self, input_shape, num_classes=5, dropout_rate=0.5): super(MyModel, self).__init__() self.weight_dict = {} self.weight_dict['backbone'] = Xception(input_shape=input_shape, weights='imagenet', include_top=False) # 把冻结backbone的逻辑挪到此处 self.weight_dict['backbone'].trainable = False self.weight_dict['outputs'] = Conv2D(num_classes, (1, 1), padding="same", activation="softmax") self.build((None,) + input_shape) def call(self, inputs, training=False): x = self.weight_dict['backbone'](inputs) x = self.weight_dict['outputs'](x) return x
内容的提问来源于stack exchange,提问作者Jim
相关产品推荐
相关产品推荐

