用 tf.estimator 提前停止,怎么样?
Early stopping with tf.estimator, how?
我在 TensorFlow 1.4 中使用 tf.estimator
,tf.estimator.train_and_evaluate
很棒,但我需要提前停止。添加它的首选方式是什么?
我想有一些 tf.train.SessionRunHook
可以解决这个问题。我看到有一个带有 ValidationMonitor
的旧 contrib 包似乎已经提前停止,但它似乎不再存在于 1.4 中。或者将来首选的方式是依赖 tf.keras
(提前停止真的很容易)而不是 tf.estimator/tf.layers/tf.data
,也许?
This hook requests stop after either a number of steps have been executed or a last step has been reached. Only one of the two options can be specified.
你也可以扩展它,根据步骤结果实现你自己的停止策略。
class MyHook(session_run_hook.SessionRunHook):
...
def after_run(self, run_context, run_values):
if condition:
run_context.request_stop()
另一个不使用挂钩的选项是创建一个 tf.contrib.learn.Experiment
(即使在 contrib 中,它似乎也支持新的 tf.estimator.Estimator
)。
然后通过(显然是实验性的)方法 continuous_train_and_eval
进行训练并适当定制 continuous_eval_predicate_fn
。
根据 tensorflow 文档,continuous_eval_predicate_fn
是
A predicate function determining whether to continue eval after each iteration.
并使用上次评估 运行 的 eval_results
调用。对于提前停止,使用自定义函数保持当前最佳结果和计数器的状态,并在达到提前停止条件时 returns False
。
已添加注意事项:此方法将使用带有 tensorflow 1.7 的已弃用方法(所有 tf.contrib.learn 从该版本开始已弃用:https://www.tensorflow.org/api_docs/python/tf/contrib/learn)
首先,您必须命名损失以使其可用于提前停止调用。如果您的损失变量在估算器中命名为 "loss",则行
copyloss = tf.identity(loss, name="loss")
就在它下面可以使用。
然后,使用这段代码创建一个挂钩。
class EarlyStopping(tf.train.SessionRunHook):
def __init__(self,smoothing=.997,tolerance=.03):
self.lowestloss=float("inf")
self.currentsmoothedloss=-1
self.tolerance=tolerance
self.smoothing=smoothing
def before_run(self, run_context):
graph = ops.get_default_graph()
#print(graph)
self.lossop=graph.get_operation_by_name("loss")
#print(self.lossop)
#print(self.lossop.outputs)
self.element = self.lossop.outputs[0]
#print(self.element)
return tf.train.SessionRunArgs([self.element])
def after_run(self, run_context, run_values):
loss=run_values.results[0]
#print("loss "+str(loss))
#print("running average "+str(self.currentsmoothedloss))
#print("")
if(self.currentsmoothedloss<0):
self.currentsmoothedloss=loss*1.5
self.currentsmoothedloss=self.currentsmoothedloss*self.smoothing+loss*(1-self.smoothing)
if(self.currentsmoothedloss<self.lowestloss):
self.lowestloss=self.currentsmoothedloss
if(self.currentsmoothedloss>self.lowestloss+self.tolerance):
run_context.request_stop()
print("REQUESTED_STOP")
raise ValueError('Model Stopping because loss is increasing from EarlyStopping hook')
这会将指数平滑损失验证与其最低值进行比较,如果它高于公差,则停止训练。如果它停止得太早,提高公差和平滑度会使它更晚停止。保持平滑低于 1,否则它永远不会停止。
如果你想根据不同的条件停止,你可以用其他东西替换 after_run 中的逻辑。
现在,将此挂钩添加到评估规范中。您的代码应如下所示:
eval_spec=tf.estimator.EvalSpec(input_fn=lambda:eval_input_fn(batchsize),steps=100,hooks=[EarlyStopping()])#
重要说明:函数 run_context.request_stop() 在 train_and_evaluate 调用中被破坏,并且不会停止训练。所以,我提出了一个价值错误来停止训练。所以你必须像这样在 try catch 块中包装 train_and_evaluate 调用:
try:
tf.estimator.train_and_evaluate(classifier,train_spec,eval_spec)
except ValueError as e:
print("training stopped")
如果不这样做,代码将在训练停止时崩溃并报错。
好消息! tf.estimator
现在对 master 有提前停止支持,看起来会在 1.10 中。
estimator = tf.estimator.Estimator(model_fn, model_dir)
os.makedirs(estimator.eval_dir()) # TODO This should not be expected IMO.
early_stopping = tf.contrib.estimator.stop_if_no_decrease_hook(
estimator,
metric_name='loss',
max_steps_without_decrease=1000,
min_steps=100)
tf.estimator.train_and_evaluate(
estimator,
train_spec=tf.estimator.TrainSpec(train_input_fn, hooks=[early_stopping]),
eval_spec=tf.estimator.EvalSpec(eval_input_fn))
我在 TensorFlow 1.4 中使用 tf.estimator
,tf.estimator.train_and_evaluate
很棒,但我需要提前停止。添加它的首选方式是什么?
我想有一些 tf.train.SessionRunHook
可以解决这个问题。我看到有一个带有 ValidationMonitor
的旧 contrib 包似乎已经提前停止,但它似乎不再存在于 1.4 中。或者将来首选的方式是依赖 tf.keras
(提前停止真的很容易)而不是 tf.estimator/tf.layers/tf.data
,也许?
This hook requests stop after either a number of steps have been executed or a last step has been reached. Only one of the two options can be specified.
你也可以扩展它,根据步骤结果实现你自己的停止策略。
class MyHook(session_run_hook.SessionRunHook):
...
def after_run(self, run_context, run_values):
if condition:
run_context.request_stop()
另一个不使用挂钩的选项是创建一个 tf.contrib.learn.Experiment
(即使在 contrib 中,它似乎也支持新的 tf.estimator.Estimator
)。
然后通过(显然是实验性的)方法 continuous_train_and_eval
进行训练并适当定制 continuous_eval_predicate_fn
。
根据 tensorflow 文档,continuous_eval_predicate_fn
是
A predicate function determining whether to continue eval after each iteration.
并使用上次评估 运行 的 eval_results
调用。对于提前停止,使用自定义函数保持当前最佳结果和计数器的状态,并在达到提前停止条件时 returns False
。
已添加注意事项:此方法将使用带有 tensorflow 1.7 的已弃用方法(所有 tf.contrib.learn 从该版本开始已弃用:https://www.tensorflow.org/api_docs/python/tf/contrib/learn)
首先,您必须命名损失以使其可用于提前停止调用。如果您的损失变量在估算器中命名为 "loss",则行
copyloss = tf.identity(loss, name="loss")
就在它下面可以使用。
然后,使用这段代码创建一个挂钩。
class EarlyStopping(tf.train.SessionRunHook):
def __init__(self,smoothing=.997,tolerance=.03):
self.lowestloss=float("inf")
self.currentsmoothedloss=-1
self.tolerance=tolerance
self.smoothing=smoothing
def before_run(self, run_context):
graph = ops.get_default_graph()
#print(graph)
self.lossop=graph.get_operation_by_name("loss")
#print(self.lossop)
#print(self.lossop.outputs)
self.element = self.lossop.outputs[0]
#print(self.element)
return tf.train.SessionRunArgs([self.element])
def after_run(self, run_context, run_values):
loss=run_values.results[0]
#print("loss "+str(loss))
#print("running average "+str(self.currentsmoothedloss))
#print("")
if(self.currentsmoothedloss<0):
self.currentsmoothedloss=loss*1.5
self.currentsmoothedloss=self.currentsmoothedloss*self.smoothing+loss*(1-self.smoothing)
if(self.currentsmoothedloss<self.lowestloss):
self.lowestloss=self.currentsmoothedloss
if(self.currentsmoothedloss>self.lowestloss+self.tolerance):
run_context.request_stop()
print("REQUESTED_STOP")
raise ValueError('Model Stopping because loss is increasing from EarlyStopping hook')
这会将指数平滑损失验证与其最低值进行比较,如果它高于公差,则停止训练。如果它停止得太早,提高公差和平滑度会使它更晚停止。保持平滑低于 1,否则它永远不会停止。
如果你想根据不同的条件停止,你可以用其他东西替换 after_run 中的逻辑。
现在,将此挂钩添加到评估规范中。您的代码应如下所示:
eval_spec=tf.estimator.EvalSpec(input_fn=lambda:eval_input_fn(batchsize),steps=100,hooks=[EarlyStopping()])#
重要说明:函数 run_context.request_stop() 在 train_and_evaluate 调用中被破坏,并且不会停止训练。所以,我提出了一个价值错误来停止训练。所以你必须像这样在 try catch 块中包装 train_and_evaluate 调用:
try:
tf.estimator.train_and_evaluate(classifier,train_spec,eval_spec)
except ValueError as e:
print("training stopped")
如果不这样做,代码将在训练停止时崩溃并报错。
好消息! tf.estimator
现在对 master 有提前停止支持,看起来会在 1.10 中。
estimator = tf.estimator.Estimator(model_fn, model_dir)
os.makedirs(estimator.eval_dir()) # TODO This should not be expected IMO.
early_stopping = tf.contrib.estimator.stop_if_no_decrease_hook(
estimator,
metric_name='loss',
max_steps_without_decrease=1000,
min_steps=100)
tf.estimator.train_and_evaluate(
estimator,
train_spec=tf.estimator.TrainSpec(train_input_fn, hooks=[early_stopping]),
eval_spec=tf.estimator.EvalSpec(eval_input_fn))