GCMLE中从learn_runner.run迁移至tf.estimator.train_and_evaluate的问题
迁移到tf.estimator.train_and_evaluate()后复刻Servo时间戳路径导出
我刚帮几个朋友解决过类似的迁移问题,其实核心是原来learn_runner.run()里的export_strategies自动帮你处理了带时间戳的Servo路径生成,而tf.estimator.train_and_evaluate()需要你手动复刻这个逻辑。下面是基于GCMLE自定义估算器场景的完整实现步骤:
1. 核心思路
原来的export_strategies会在$job_dir/export/Servo/下自动创建带时间戳的子目录来保存模型;切换到train_and_evaluate()后,默认的LatestExporter会覆盖最新导出的模型,不会保留历史时间戳目录。我们需要通过自定义导出路径生成逻辑或者自定义Exporter类来复刻原行为。
2. 具体实现方案
方案一:训练结束后手动导出(最简单,适合仅需最终导出的场景)
这种方式直接在train_and_evaluate()执行完成后,手动调用模型导出API并指定带时间戳的路径:
步骤1:编写时间戳路径生成函数
import os from datetime import datetime def get_servo_export_path(job_dir): # 生成格式如20240520143022的时间戳 timestamp = datetime.now().strftime("%Y%m%d%H%M%S") return os.path.join(job_dir, "export", "Servo", timestamp)
步骤2:定义Serving输入接收函数(和原代码保持一致)
def serving_input_receiver_fn(): # 替换成你的特征列定义 feature_spec = tf.feature_column.make_parse_example_spec(your_feature_columns) return tf.estimator.export.build_parsing_serving_input_receiver_fn(feature_spec)()
步骤3:执行训练评估+手动导出
# 初始化自定义估算器 estimator = tf.estimator.Estimator( model_fn=your_custom_model_fn, model_dir=job_dir, params=your_hyperparameters ) # 配置TrainSpec和EvalSpec train_spec = tf.estimator.TrainSpec( input_fn=train_input_fn, max_steps=TRAIN_STEPS ) eval_spec = tf.estimator.EvalSpec( input_fn=eval_input_fn, steps=EVAL_STEPS, start_delay_secs=10, # 首次评估延迟时间 throttle_secs=60 # 评估间隔时间 ) # 运行训练和评估 tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec) # 训练完成后导出模型到带时间戳的Servo路径 final_export_path = get_servo_export_path(job_dir) estimator.export_saved_model(final_export_path, serving_input_receiver_fn)
方案二:自定义Exporter类(适合需要在评估过程中多次导出的场景)
如果你需要在每次评估后都导出模型并保留时间戳目录,可以自定义一个Exporter子类,让它自动生成时间戳路径:
步骤1:实现自定义TimestampedServoExporter
import os from datetime import datetime import tensorflow as tf class TimestampedServoExporter(tf.estimator.Exporter): def __init__(self, name="Servo", serving_input_receiver_fn=None, job_dir=None): self._name = name self._serving_input_receiver_fn = serving_input_receiver_fn self._job_dir = job_dir @property def name(self): return self._name def export(self, estimator, export_path, checkpoint_path=None, eval_result=None, is_the_final_export=True): # 生成带时间戳的导出路径 timestamp = datetime.now().strftime("%Y%m%d%H%M%S") timestamped_path = os.path.join(self._job_dir, "export", self._name, timestamp) # 执行导出 return estimator.export_saved_model( timestamped_path, self._serving_input_receiver_fn, checkpoint_path=checkpoint_path )
步骤2:在EvalSpec中配置自定义Exporter
# 初始化估算器、TrainSpec和之前一致 estimator = tf.estimator.Estimator(...) train_spec = tf.estimator.TrainSpec(...) # 配置EvalSpec时添加自定义Exporter eval_spec = tf.estimator.EvalSpec( input_fn=eval_input_fn, steps=EVAL_STEPS, exporters=[TimestampedServoExporter( name="Servo", serving_input_receiver_fn=serving_input_receiver_fn, job_dir=job_dir )], start_delay_secs=10, throttle_secs=60 ) # 运行训练和评估,每次评估(包括最终评估)都会生成新的时间戳目录 tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec)
3. 验证路径是否符合预期
运行代码后,你可以检查$job_dir/export/Servo/目录下,会生成类似20240520143022的时间戳子目录,里面存放着完整的模型二进制文件,和原来learn_runner.run()的行为完全一致。
内容的提问来源于stack exchange,提问作者reese0106
相关产品推荐
相关产品推荐

