TensorFlow 1.10+ 自定义估算器提前停止 train_and_evaluate
TensorFlow 1.10+ custom estimator early stopping with train_and_evaluate
假设您正在训练自定义 tf.estimator.Estimator
with tf.estimator.train_and_evaluate
using a validation dataset in a setup similar to that of :
classifier = tf.estimator.Estimator(
model_fn=model_fn,
model_dir=model_dir,
params=params)
train_spec = tf.estimator.TrainSpec(
input_fn = training_data_input_fn,
)
eval_spec = tf.estimator.EvalSpec(
input_fn = validation_data_input_fn,
)
tf.estimator.train_and_evaluate(
classifier,
train_spec,
eval_spec
)
通常,当训练数据集的损失继续改善但验证数据集的损失没有改善时,人们通常使用验证数据集来切断训练以防止过度拟合。
目前 tf.estimator.EvalSpec
允许指定在多少 steps
(默认为 100)之后评估模型。
如何(如果可能不使用 tf.contrib
函数)指定在 n
次评估调用 (n * steps
) 后终止训练,其中评估损失没有改善,然后将 "best" 模型/检查点(由验证数据集确定)保存为唯一的文件名(例如 best_validation.checkpoint
)
我现在明白你的困惑了。 stop_if_no_decrease_hook
的文档指出(强调我的):
max_steps_without_decrease: int, maximum number of training steps with
no decrease in the given metric.
eval_dir: If set, directory
containing summary files with eval metrics. By default,
estimator.eval_dir() will be used.
浏览 the code of the hook (version 1.11),您会发现:
def stop_if_no_metric_improvement_fn():
"""Returns `True` if metric does not improve within max steps."""
eval_results = read_eval_metrics(eval_dir) #<<<<<<<<<<<<<<<<<<<<<<<
best_val = None
best_val_step = None
for step, metrics in eval_results.items(): #<<<<<<<<<<<<<<<<<<<<<<<
if step < min_steps:
continue
val = metrics[metric_name]
if best_val is None or is_lhs_better(val, best_val):
best_val = val
best_val_step = step
if step - best_val_step >= max_steps_without_improvement: #<<<<<
tf_logging.info(
'No %s in metric "%s" for %s steps, which is greater than or equal '
'to max steps (%s) configured for early stopping.',
increase_or_decrease, metric_name, step - best_val_step,
max_steps_without_improvement)
return True
return False
代码的作用是加载评估结果(使用您的 EvalSpec
参数生成)并提取评估结果和 global_step
(或您用来计数的任何其他自定义步骤)具体评价记录
这是文档training steps
部分的来源:提前停止不是根据非改进评估的数量触发的,而是根据某个步骤中非改进评估的数量触发的范围(恕我直言,这有点违反直觉)。
所以,回顾一下:是,提前停止钩子使用评估结果来决定什么时候停止训练,但是 您需要输入要监控的训练步骤数,并记住在该步骤数中将发生多少次评估。
带有数字的例子希望能澄清更多
假设您无限期地训练,每 1k 步进行一次评估。评估如何运行的具体细节无关紧要,只要它每 1k 步运行一次即可生成我们要监控的指标。
如果您将挂钩设置为 hook = tf.contrib.estimator.stop_if_no_decrease_hook(my_estimator, 'my_metric_to_monitor', 10000)
,则挂钩将考虑在 10k 步范围内发生的评估。
由于您 运行 每 1k 步进行 1 次评估,如果连续 10 次评估没有任何改善,这归结为提前停止。
如果您决定每 2k 步重新运行一次 eval,则挂钩将只考虑 5 个连续 eval 的序列而没有改进。
保持最佳模型
首先,重要说明:这与提前停止无关,通过训练保留最佳模型副本的问题以及停止的问题一旦性能开始下降,训练就完全无关了。
在 EvalSpec
中定义 tf.estimator.BestExporter
可以很容易地保持最佳模型(摘自 link 的片段):
serving_input_receiver_fn = ... # define your serving_input_receiver_fn
exporter = tf.estimator.BestExporter(
name="best_exporter",
serving_input_receiver_fn=serving_input_receiver_fn,
exports_to_keep=5) # this will keep the 5 best checkpoints
eval_spec = [tf.estimator.EvalSpec(
input_fn=eval_input_fn,
steps=100,
exporters=exporter,
start_delay_secs=0,
throttle_secs=5)]
如果你不知道如何定义 serving_input_fn
have a look here
这允许您保留获得的 5 个最佳模型,存储为 SavedModel
s(这是目前存储模型的首选方式)。
假设您正在训练自定义 tf.estimator.Estimator
with tf.estimator.train_and_evaluate
using a validation dataset in a setup similar to that of
classifier = tf.estimator.Estimator(
model_fn=model_fn,
model_dir=model_dir,
params=params)
train_spec = tf.estimator.TrainSpec(
input_fn = training_data_input_fn,
)
eval_spec = tf.estimator.EvalSpec(
input_fn = validation_data_input_fn,
)
tf.estimator.train_and_evaluate(
classifier,
train_spec,
eval_spec
)
通常,当训练数据集的损失继续改善但验证数据集的损失没有改善时,人们通常使用验证数据集来切断训练以防止过度拟合。
目前 tf.estimator.EvalSpec
允许指定在多少 steps
(默认为 100)之后评估模型。
如何(如果可能不使用 tf.contrib
函数)指定在 n
次评估调用 (n * steps
) 后终止训练,其中评估损失没有改善,然后将 "best" 模型/检查点(由验证数据集确定)保存为唯一的文件名(例如 best_validation.checkpoint
)
我现在明白你的困惑了。 stop_if_no_decrease_hook
的文档指出(强调我的):
max_steps_without_decrease: int, maximum number of training steps with no decrease in the given metric.
eval_dir: If set, directory containing summary files with eval metrics. By default, estimator.eval_dir() will be used.
浏览 the code of the hook (version 1.11),您会发现:
def stop_if_no_metric_improvement_fn():
"""Returns `True` if metric does not improve within max steps."""
eval_results = read_eval_metrics(eval_dir) #<<<<<<<<<<<<<<<<<<<<<<<
best_val = None
best_val_step = None
for step, metrics in eval_results.items(): #<<<<<<<<<<<<<<<<<<<<<<<
if step < min_steps:
continue
val = metrics[metric_name]
if best_val is None or is_lhs_better(val, best_val):
best_val = val
best_val_step = step
if step - best_val_step >= max_steps_without_improvement: #<<<<<
tf_logging.info(
'No %s in metric "%s" for %s steps, which is greater than or equal '
'to max steps (%s) configured for early stopping.',
increase_or_decrease, metric_name, step - best_val_step,
max_steps_without_improvement)
return True
return False
代码的作用是加载评估结果(使用您的 EvalSpec
参数生成)并提取评估结果和 global_step
(或您用来计数的任何其他自定义步骤)具体评价记录
这是文档training steps
部分的来源:提前停止不是根据非改进评估的数量触发的,而是根据某个步骤中非改进评估的数量触发的范围(恕我直言,这有点违反直觉)。
所以,回顾一下:是,提前停止钩子使用评估结果来决定什么时候停止训练,但是 您需要输入要监控的训练步骤数,并记住在该步骤数中将发生多少次评估。
带有数字的例子希望能澄清更多
假设您无限期地训练,每 1k 步进行一次评估。评估如何运行的具体细节无关紧要,只要它每 1k 步运行一次即可生成我们要监控的指标。
如果您将挂钩设置为 hook = tf.contrib.estimator.stop_if_no_decrease_hook(my_estimator, 'my_metric_to_monitor', 10000)
,则挂钩将考虑在 10k 步范围内发生的评估。
由于您 运行 每 1k 步进行 1 次评估,如果连续 10 次评估没有任何改善,这归结为提前停止。 如果您决定每 2k 步重新运行一次 eval,则挂钩将只考虑 5 个连续 eval 的序列而没有改进。
保持最佳模型
首先,重要说明:这与提前停止无关,通过训练保留最佳模型副本的问题以及停止的问题一旦性能开始下降,训练就完全无关了。
在 EvalSpec
中定义 tf.estimator.BestExporter
可以很容易地保持最佳模型(摘自 link 的片段):
serving_input_receiver_fn = ... # define your serving_input_receiver_fn
exporter = tf.estimator.BestExporter(
name="best_exporter",
serving_input_receiver_fn=serving_input_receiver_fn,
exports_to_keep=5) # this will keep the 5 best checkpoints
eval_spec = [tf.estimator.EvalSpec(
input_fn=eval_input_fn,
steps=100,
exporters=exporter,
start_delay_secs=0,
throttle_secs=5)]
如果你不知道如何定义 serving_input_fn
have a look here
这允许您保留获得的 5 个最佳模型,存储为 SavedModel
s(这是目前存储模型的首选方式)。