Tensorflow v1.10 +为什么在没有检查点的情况下需要输入服务接收器功能?

SumNeuron:

我正在根据TensorFlow的估算器API调整我的模型。

我最近问了一个关于基于验证数据的提前停止的问题,除了早停止,还应该导出此时的最佳模型。

似乎我对模型导出是什么以及检查点是什么的理解还不完整。

检查点是自动进行的。根据我的理解,检查点足以使估算器开始“热身”-使用如此训练的权重或错误之前的权重(例如,如果您遇到断电)。

关于检查点的好处是,除了自定义估算器(即input_fnmodel_fn所需的代码外,我不必编写任何代码

虽然给定了一个初始化的估计量,但人们只能调用其train方法来训练模型,但实际上,这种方法相当乏味。人们常常想做几件事:

  1. 定期将网络与验证数据集进行比较,以确保您不会过度拟合
  2. 如果发生过度拟合,请尽早停止训练
  3. 只要网络结束(通过达到指定数量的训练步骤或按照早期停止标准),就可以保存最佳模型。

对于“高级”估计器API的新手来说,似乎需要大量的低级专业知识(例如input_fn),因为如何才能使估计器做到这一点并非直截了当。

通过一些轻代码,可以通过使用来实现#1的重做tf.estimator.TrainSpectf.estimator.EvalSpectf.estimator.train_and_evaluate

在上一个问题中,用户@GPhilo阐明了如何使用来自的半直观函数来实现#2tf.contrib

tf.contrib.estimator.stop_if_no_decrease_hook(my_estimator,'my_metric_to_monitor', 10000)

(不直观,因为“提早停止不是根据未改进评估的次数来触发,而是根据一定步长范围内未改进评估的次数来触发”)。

@GPhilo-注意到它与#2不相关-还回答了如何做#3(按照原始帖子的要求)。但是,我不了解input_serving_fn它是什么,为什么需要它或如何制作它。

这进一步使我感到困惑,因为不需要这样的功能来创建检查点,也不需要估计器从检查点开始“热身”。

所以我的问题是:

  • 检查点和导出的最佳模型之间有什么区别?
  • 服务输入接收器功能究竟是什么?如何编写?(我花了一些时间阅读tensorflow文档,并发现不足以理解我应该如何编写一个,以及为什么我必须这样做)。
  • 如何训练估算器,保存最佳模型,然后再加载它。

为了帮助回答我的问题,我提供了此Colab文档。

这个自包含的笔记本会生成一些虚拟数据,将其保存在TF记录中,并通过一个非常简单的自定义估算器,model_fninput_fn使用TF记录文件训练该模型因此,对于某人来说,向我解释为输入服务接收器功能我需要做哪些占位符以及如何完成#3应该足够了

更新资料

@GPhilo首先,对于您帮助我(并希望其他人)理解此事的深思熟虑和关心,我不能低估我的感谢。

我的“目标”(促使我提出这个问题)是尝试建立一个可重用的培训网络框架,这样我就可以通过一个不同的方案build_fn而去(再加上具有导出模型的生活质量,提早停止等)。

可以在此处找到更新的(基于您的答案)Colab

在对您的答案进行多次阅读之后,我发现现在更加混乱了:

1。

您向推理模型提供输入的方式与您用于训练的方式不同

为什么?据我了解,数据输入管道不是:

load raw —> process —> feed to model

反而:

Load raw —> pre process —> store (perhaps as tf records)
# data processing has nothing to do with feeding data to the model?
Load processed —> feed to model

换句话说,据我的理解(可能是错误的),tf Example/的意义SequenceExample是要存储一个随时可用的完整奇异基准实体-除了从TFRecord文件中读取以外,不需要其他处理


因此,训练/评估input_fn与推论之间可能会有差异(例如,从文件读取与内存中的急切/交互式评估),但是数据格式是相同的(推论除外,您可能只想提供一个示例比一批…)

我同意“ 输入管道不是模型本身的一部分 ”。但是,在我看来,我的思维方式显然是错误的,使用估计器,我应该能够为它提供一批训练用的样本和一个单独的示例(或批处理)以进行推理。

旁白:“ 评估时,您不需要渐变,而需要其他输入函数。”,唯一的区别(至少就我而言)是您读取的文件?

  1. 我熟悉该《 TF指南》,但我没有发现它有用,因为我不清楚我需要添加哪些占位符以及需要添加哪些其他操作来转换数据。

如果我用记录训练我的模型并且只想推断密集的张量怎么办?

切线地,在给定的tf记录界面要求用户多次定义如何在不同上下文中从tf记录文件写入特征或从中提取特征的情况下,我可以在链接的指南子表中找到该示例此外,鉴于TF团队已明确表示他们对记录tf记录兴趣不大,因此对我而言,基于tf记录构建的任何文档也同样具有启发性。

  1. 关于tf.estimator.export.build_raw_serving_input_receiver_fn占位符叫什么?输入?您是否可以tf.estimator.export.build_raw_serving_input_receiver_fn写出等价物来显示类似物serving_input_receiver_fn

  2. 关于serving_input_receiver_fn带有输入图像的示例您如何知道将特征称为“图像”,将接收器张量称为“ input_data”?那是(后者)标准吗?

  3. 如何用命名出口signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY

吉罗:

检查点和导出的最佳模型之间有什么区别?

检查点至少是一个文件,其中包含特定时间点获取的特定图的所有变量通过特定的图,我的意思是当加载您的检查点时,TensorFlow的作用是循环遍历图中定义的所有变量(session您正在运行的变量)并在检查点文件搜索与以下名称相同的变量图中的一个对于继续训练,这是理想的选择,因为您的图形在每次重新启动之间始终看起来相同。

导出的模型有不同的用途。导出模型的想法是,完成训练后,您希望获得一些可以用于推理的内容,其中不包含所有特定于训练的(繁重)部分(一些示例:梯度计算,全局步骤变量,输入管道,...)。此外,他的要点是关键,通常,您向推理模型提供输入的方式与您在训练中使用的方式不同。为了进行培训,您有一个输入管道,可将数据加载,预处理并将数据馈送到网络。此输入管道不是模型本身的一部分,可能需要更改以进行推断。这是使用Estimators进行操作时的关键点

为什么需要服务输入接收器功能?

为了回答这个问题,我将首先退后一步。为什么我们在所有广告中都需要输入函数,它们是什么?TF Estimator虽然可能不如其他模型网络直观,但它具有很大的优势:它们通过输入函数和模型函数清楚地将模型逻辑和输入处理逻辑分开

模型分为三个不同阶段:训练,评估和推理。对于最常见的用例(或者至少我目前能想到的所有用例),在TF中运行在所有这些阶段中都会有所不同。该图是输入预处理,模型以及在当前阶段运行模型所需的所有机械的组合。

希望有一些示例可以进一步阐明:训练时,您需要渐变以更新权重,运行训练步骤的优化器,监视事情进展的各种指标,从训练集中获取数据的输入管道,等等。 。评估时,您不需要渐变,而需要其他输入函数。当进行推理时,您只需要模型部,输入函数也将有所不同(没有任何tf.data.*东西,但通常只是一个占位符)。

Estimators中的每个阶段都有其自己的输入功能。您熟悉培训和评估的内容,推论只是您的serving input receiver功能。在TF术语中,“服务”是打包训练后的模型并将其用于推理的过程(有一个完整的TensorFlow服务系统可用于大规模操作,但这超出了这个问题,您很可能根本就不需要它)。

是时候引用有关该主题TF指南了

在训练期间,input_fn()会摄取数据并准备供模型使用。同样,在服务时,a serving_input_receiver_fn()接受推理请求并为模型做好准备。此功能具有以下目的:

  • 要将占位符添加到服务系统将随推理请求一起提供的图上。
  • 添加将数据从输入格式转换为模型所需的特征张量所需的任何其他操作。

现在,服务输入功能规范取决于您计划将输入发送到图形的方式。

如果要将数据打包到(序列化的)tf.Example(类似于TFRecord文件中的记录之一)中,则您的服务输入函数将具有字符串占位符(用于示例中的序列化字节),并且需要有关如何解释示例的规范,以便提取其数据。如果这是您想要的方式,我邀请您看一下上面链接的指南中的示例,它实质上显示了如何设置如何解释示例并解析示例以获取输入数据的规范。

相反,如果你在规划直接将输入到网络的第一层,你需要定义一个服务输入功能,但这次将只包含将被直接插入到网络的占位符。TF提供的不只是一个函数:tf.estimator.export.build_raw_serving_input_receiver_fn

那么,您实际上是否需要编写自己的输入函数?如果您需要的是占位符,否。只需使用build_raw_serving_input_receiver_fn适当的参数即可。如果您需要更高级的预处理,那么可以,您可能需要编写自己的预处理程序。在这种情况下,它将看起来像这样:

def serving_input_receiver_fn():
  """For the sake of the example, let's assume your input to the network will be a 28x28 grayscale image that you'll then preprocess as needed"""
  input_images = tf.placeholder(dtype=tf.uint8,
                                         shape=[None, 28, 28, 1],
                                         name='input_images')
  # here you do all the operations you need on the images before they can be fed to the net (e.g., normalizing, reshaping, etc). Let's assume "images" is the resulting tensor.

  features = {'input_data' : images} # this is the dict that is then passed as "features" parameter to your model_fn
  receiver_tensors = {'input_data': input_images} # As far as I understand this is needed to map the input to a name you can retrieve later
  return tf.estimator.export.ServingInputReceiver(features, receiver_tensors)

如何训练估算器,保存最佳模型,然后再加载?

model_fn采用mode参数以便您有条件地构建模型。例如,在您的合作实验室中,您总是有一个优化器。这是错误的,因为它只应存在mode == tf.estimator.ModeKeys.TRAIN

其次,您build_fn的“输出”参数毫无意义。该函数应该表示您的推理图,仅将您将在推理中馈入的张量作为输入,并返回logit /预测。因此,我假设outputs参数不存在,因为build_fn签名应该存在def build_fn(inputs, params)

此外,您可以在定义model_fn采取features的张量。尽管可以做到这一点,但它既限制了您只能输入一个内容,又使serving_fn的事情变得复杂(您不能使用罐头,build_raw_...而需要编写自己的内容并返回一个TensorServingInputReceiver)。我将选择更通用的解决方案,并假设您的model_fn情况如下(为简洁起见,我省略了变量范围,请根据需要添加):

def model_fn(features, labels, mode, params): 
  my_input = features["input_data"]
  my_input.set_shape(I_SHAPE(params['batch_size']))

  # output of the network
  onet = build_fn(features, params)
  predicted_labels = tf.nn.sigmoid(onet)
  predictions = {'labels': predicted_labels, 'logits': onet}
  export_outputs = { # see EstimatorSpec's docs to understand what this is and why it's necessary.
       'labels': tf.estimator.export.PredictOutput(predicted_labels),
       'logits': tf.estimator.export.PredictOutput(onet) 
  } 
  # NOTE: export_outputs can also be used to save models as "SavedModel"s during evaluation.

  # HERE is where the common part of the graph between training, inference and evaluation stops.
  if mode == tf.estimator.ModeKeys.PREDICT:
    # return early and avoid adding the rest of the graph that has nothing to do with inference.
    return  tf.estimator.EstimatorSpec(mode=mode, 
                                       predictions=predictions, 
                                       export_outputs=export_outputs)

  labels.set_shape(O_SHAPE(params['batch_size']))      

  # calculate loss 
  loss = loss_fn(onet, labels)

  # add optimizer only if we're training
  if mode == tf.estimator.ModeKeys.TRAIN:
    optimizer = tf.train.AdagradOptimizer(learning_rate=params['learning_rate'])
  # some metrics used both in training and eval
  mae = tf.metrics.mean_absolute_error(labels=labels, predictions=predicted_labels, name='mea_op')
  mse = tf.metrics.mean_squared_error(labels=labels, predictions=predicted_labels, name='mse_op')
  metrics = {'mae': mae, 'mse': mse}
  tf.summary.scalar('mae', mae[1])
  tf.summary.scalar('mse', mse[1])

  if mode == tf.estimator.ModeKeys.EVAL:
    return tf.estimator.EstimatorSpec(mode, loss=loss, eval_metric_ops=metrics, predictions=predictions, export_outputs=export_outputs)

  if mode == tf.estimator.ModeKeys.TRAIN:
    train_op = optimizer.minimize(loss, global_step=tf.train.get_global_step())
    return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op, eval_metric_ops=metrics, predictions=predictions, export_outputs=export_outputs)

现在,在调用train_and_evaluate完成后,要设置导出部分

1)定义您的服务输入功能:

serving_fn = tf.estimator.export.build_raw_serving_input_receiver_fn(
                                       {'input_data':tf.placeholder(tf.float32, [None,#YOUR_INPUT_SHAPE_HERE (without batch size)#])})

2)将模型导出到某个文件夹

est.export_savedmodel('my_directory_for_saved_models', serving_fn)

这会将估算器当前状态保存到您指定的任何位置。如果需要特定的检查点,请在调用之前加载它export_savedmodel这将在“ my_directory_for_saved_models”中保存一个预测图,其中包含调用导出函数时估算器具有的训练参数。

最后,您可能不希望冻结图形(查找freeze_graph.py)并对其进行优化以进行推理(查找optimize_for_inference.py和/或transform_graph),以获得冻结的*.pb文件,然后可以根据需要加载并用于推理。


编辑:在更新中为新问题添加答案

边注:

我的“目标”(促使我提出这个问题)是尝试建立一个可重用的培训网络框架,以便我可以通过一个不同的build_fn然后走(加上具有导出模型的生活质量,提早停止等)。 。

如果可以的话,请务必将其发布在GitHub上的某个地方,并将其链接至我。我一直在尝试使同一件事开始并运行一段时间,结果并不像我希望的那样好。

问题1:

换句话说,我的理解(可能是错误的)是,tf Example / SequenceExample的要点是存储一个随时可用的完整奇异数据实体-除了从TFRecord文件读取以外,不需要其他处理。

实际上,通常不是这种情况(尽管从理论上讲,您的方法也完全可以)。您可以将TFRecords视为一种(详细记录的方式)以紧凑的方式存储数据集。例如,对于图像数据集,记录通常包含压缩的图像数据(如组成jpeg / png文件的字节),其标签和一些元信息。然后,输入管道读取一条记录,对其进行解码,根据需要对其进行预处理,然后将其馈送到网络。当然,您可以在生成TFRecord数据集之前移动解码和预处理,并在示例中存储随时可提供的数据,但是数据集的规模将非常庞大。

特定的预处理管线是一个在阶段之间进行更改的示例(例如,您可以在训练管线中进行数据扩充,而在其他管线中则没有)。当然,在某些情况下,这些管道是相同的,但通常情况并非如此。

关于一旁:

“评估时,您不需要渐变,而需要其他输入函数。”,唯一的区别(至少就我而言)是您读取的文件?

在您的情况下可能是这样。但是,再次假设您使用的是数据增强:您需要在eval期间将其禁用(或者更好的是完全不使用它),这会改变您的管道。

问题2:如果我用记录训练模型并只想推断密集的张量怎么办?

这就是为什么将管道与模型分开的原因。该模型将张量作为输入并对其进行操作。张量是占位符,还是将子图从Example转换为张量的子图的输出,这是属于框架的细节,而不是模型本身。

分割点是模型输入。该模型期望张量(或更普遍的情况下是name:tensor项目的决定)作为输入,并使用它来构建其计算图。输入的来源由输入函数决定,但是只要所有输入函数的输出具有相同的接口,就可以根据需要交换输入,并且该模型将简单地获取并使用它。

因此,回顾一下,假设您使用“示例”进行训练/评估并使用密集的张量进行预测,那么您的“训练”和“评估”输入函数将建立一个管道,该管道从某处读取示例,将其解码为张量,然后将其返回给模型以用作输入。另一方面,您的预测输入函数只是为模型的每个输入设置一个占位符,然后将它们返回给模型,因为它假定您将把准备好要馈送到网络的数据放入占位符中。

问题3:

您将占位符作为的参数传递build_raw_serving_input_receiver_fn,因此选择其名称:

tf.estimator.export.build_raw_serving_input_receiver_fn(                                               
    {'images':tf.placeholder(tf.float32, [None,28,28,1], name='input_images')})

问题4:

代码中有一个错误(我混淆了两行),字典的键应该是input_data(我修改了上面的代码)。在字典的关键必须是您用来检索从张的关键features在你的model_fnmodel_fn第一行是:

my_input = features["input_data"]

因此关键是'input_data'根据输入的内容receiver_tensor,我仍然不确定自己所扮演的角色,所以我的建议是尝试设置与输入不同的名称,features然后检查该名称何处显示。

问题5:

我不确定自己是否了解,我将在澄清后对其进行编辑

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

AttributeError:模块“ tensorflow.compat”没有属性“ v1” Tensorflow v:1.10.0

在TensorFlow v1中隐式启用TensorFlow v2行为

无法使用更新代码在 tensorflow V2 中加载 Tensorflow v1 模型?

Tensorflow Faster R-CNN with Resnet-50 (v1) Object Detection API 结果每个图像上只有一个边界框

TensorFlow v1和v2中Keras的ZeroPadding2D的区别?

为什么陈述“ vector <int>(v1);” 失败

Tensorflow v1 名称“features:0”指的是一个不存在的 Tensor

_api / v1 / hard /和python / hard之间的tensorflow / hard utils模块混淆

如何在TensorFlow v1中使用freeze_graph.py工具

使用tf.control_dependencies(tensorflow v1)的意外(随机)执行顺序

ssd mobilenet v1:更改功能图布局

Firebase功能v1配置未检索配置

带有Google Colab的FastAI库v1

带有Gradle的Android Google Maps API v1

什么是TensorFlow检查点元文件?

AttributeError:模块“ tensorflow._api.v1.compat.v1”没有属性“ pywrap_tensorflow”

Tensorflow:仅在训练期间将错误最小化的情况下,如何才能保存检查点?

tensorflow.python.pywrap_tensorflow_internal没有模块Windows 10 tensorflow gpu

Git 协议 v1 和 v0,v2 有什么区别?

重新训练MobileNet SSD V1 COCO后,Tensorflow的pb和pbtxt文件无法与OpenCV一起使用

Flutter Android Embedding V1和V2有什么区别

条纹API:什么是我的账户ID?如何默认情况下它在GET / V1 /帐号/?

kubectl没有与版本apps / v1中的同类服务匹配的项

将所有对/ api / v1 / **的请求传递到旧的api服务器

你能从 tensorflow object detection api v2 导出早期的检查点吗?

将V2检查点用于TFLearn(TensorFlow)r0.12.1

如何保存使用来自Tensorflow 1.xx的.meta检查点模型的Tensorflow 2.0模型?

如何检查我的AzureAD版本是V1还是V2?

为什么VirtualBox或VMware无法在Windows 10上启用Hyper-V的情况下运行