如何让Tensorflow的call函数在训练与推理阶段执行不同逻辑?
解决方案
你可以从两种修改方案里选符合你需求的:
方案1:调整input_signature加入training参数
这个方案兼容性最好,显式控制运行阶段,不会有全局状态冲突问题:
- 把
training参数加入call的输入签名,设置默认值为False,保证模型导出时默认走推理逻辑,训练时TensorFlow会自动传入training=True - 在
call内判断只有非训练状态下才调用pp_layer,避免和train_step里的调用重复
修改后的代码示例:
@tf.function(input_signature=[ tf.TensorSpec([None, 256, 256, 3], tf.float32), tf.TensorSpec([], tf.bool, default=False) ]) def call(self, data, training=False): # 仅推理阶段调用预处理层,训练阶段已在train_step中提前处理 if not training: data = self.pp_layer(data) # 原有推理逻辑保持不变 ...
train_step的代码不需要做任何修改,训练时传入的x已经经过预处理,call接收到training=True不会重复执行预处理。
方案2:不修改input_signature,用学习阶段标志判断
如果你不想调整导出模型的输入签名,可以直接调用Keras全局学习状态接口判断当前阶段,不需要修改call的参数:
@tf.function(input_signature=[tf.TensorSpec([None, 256, 256, 3], tf.float32)]) def call(self, data): # 获取当前运行阶段:训练时返回1,推理时返回0 training = tf.keras.backend.learning_phase() if not training: data = self.pp_layer(data) # 原有推理逻辑保持不变 ...
这个方案完全不需要调整原有输入签名,也不会出现参数不匹配的报错,适合需要保持导出模型输入格式不变的场景。
内容的提问来源于stack exchange,提问作者magmacollaris
相关产品推荐
相关产品推荐

