创建估算器后,更改Keras状态RNN模型,图层和方法的状态

时间:2019-01-11 10:54:10

标签: python tensorflow keras tensorflow-estimator

与独立的Keras模型相比,使用tf.keras.estimator.model_to_estimator有什么好处?例如,当我们希望实时提供模型时?

让我们举一个例子。我有一个Keras RNN,它是stateful模型。这意味着当实时数据用于预测时,我需要执行以下步骤:

  1. 重置模型状态
  2. 根据该用户的最新预测设置状态(如果这是老用户)
  3. 运行predict(x=x)并保存输出的状态,以供该用户将来使用。

在Keras中,我使用以下步骤进行操作:

old_states = [state_h, state_c]
lstm_layer = model.get_layer('lstm')
lstm_layer.reset_states(states=old_states)
pred = model.predict(x=x)
new_states_to_save = [pred[1], pred[2]]

但是,如何使用估计器执行此过程?也就是说,在: tf.keras.estimator.model_to_estimator(model)个对象?

如何访问各个图层以及如何访问.reset_states()方法?

型号

num_input = tf.keras.layers.Input(shape=(None, no_of_features), name='num_input', batch_size=1)
lstm, state_h, state_c = tf.keras.layers.LSTM(units=320,
                                            return_sequences=True,
                                            return_state=True,
                                            stateful=True,
                                            name='lstm')(num_input)

dense = tf.keras.layers.Dense(1, activation='sigmoid', name='main_output')(lstm_3)

model = tf.keras.models.Model(num_input, [dense, state_h, state_c])

修改 估算层enter image description here

2 个答案:

答案 0 :(得分:4)

关于tf.Estimator

的好处
  

与独立的keras模型相比,使用tf.keras.estimator.model_to_estimator有什么好处?例如,当我们希望实时提供模型时?

好吧,我宁愿加两美分而不是复制文档:

  •   

    您可以在本地主机或分布式多服务器环境上运行基于Estimator的模型,而无需更改模型。此外,您可以在CPU,GPU或TPU上运行基于Estimator的模型,而无需重新编码模型。

好的,Keras模型也可以“无需重新编码”在CPU和GPU上运行。分布式培训是有道理的,如果您需要它,那么tf.Estimator的麻烦可能是值得的。此外,作为Tensorflow 2.0 is coming,我不会指望这个高级API。方向很明确, Tensorflow 将变得更加面向 Keras和PyTorch (在第二个框架中使用tf.Eager高级API), tf.Estimator面向功能的设计并不能真正满足要求。

  •   

    估计器简化了模型开发人员之间的共享实现。

我只能说SavedModel docs,但他们不能说。使用tf.SavedModel,导出通过tf.Estimator创建的模型更加有趣,只是为了让您看清楚它有多么“简单”:

feature_spec = {'foo': tf.FixedLenFeature(...),
                'bar': tf.VarLenFeature(...)}

def serving_input_receiver_fn():
  """An input receiver that expects a serialized tf.Example."""
  serialized_tf_example = tf.placeholder(dtype=tf.string,
                                         shape=[default_batch_size],
                                         name='input_example_tensor')
  receiver_tensors = {'examples': serialized_tf_example}
  features = tf.parse_example(serialized_tf_example, feature_spec)
  return tf.estimator.export.ServingInputReceiver(features, receiver_tensors)

哦,别忘了本文档不会告诉您如何加载此模型并在以后使用它(例如,您可以加载到当前会话中,前提是您知道输入的名称和输出节点,因此很容易共享这些模型,喜欢它。)

  •   

    您可以使用高级直观代码来开发最新模型。简而言之,与低级TensorFlow API相比,使用Estimators创建模型通常要容易得多。

这点已经涵盖了,确实是tf。Estimator比底层的Tensorflow更直观,但是我怀疑面对tf.keras能否成功。尽管如此,通过三种不同的模式,它是毫无意义的面向功能的设计(加上导出的所有乐趣),我还是会说这是一个中级API(总是有多个API)

  •   

    估算器本身建立在tf.keras.layers上,从而简化了自定义。

好吧,这是1.9或1.8中的tf.layers,但是已经过时了,所以从长远来看,这就是Tensorflow的良好实践。

总而言之::我不太愿意提供服务(不能将时间浪费在名称为tf.estimator.export.build_raw_serving_input_receiver_fn之类的下一个不直观的代码上),但是您会更好避免由于设计不佳而可能的情况。

也可以使用Keras模型进行预测,这可以为您节省一些时间,但这只是我的看法。

访问各个层

首先: tf.Estimator与Keras模型不同!

  

如何访问各个图层以及如何访问.reset_states()方法?

好吧,这就是乐趣的开始。您必须在当前会话中获取模型(例如,加载导出的tf.Estimator)并遍历图形中的操作。

示意性地看起来像这样:

with tf.Session() as session:
    # Of course, your tag can be different
    tf.saved_model.loader.load(session, 
                               tf.saved_model.tag_constants.SERVING, 
                               "/here/is/mymodel/exported/with/SavedModel")
    graph = tf.get_default_graph()
    # Here are all the layers of your tf.Estimator, sorted in the order they exist
    # At least they were two versions back
    operations = graph.get_operations()
    # https://www.tensorflow.org/api_docs/python/tf/contrib/framework/get_variables this should work...
    variables = tf.contrib.get_variables()

您可以使用这些操作做什么?那些名称具有可读性,也许您可​​以用这种方式进行修改(并重置rnn状态)。 获取操作和变量后检查here

这是一个长镜头,因为不幸的是我还没有看到这样的用例。我认为就“简化定制”而言就可以了。

预测

好一点(?),您只需在加载模型后在会话内提供图形,就像低级Tensorflow:

output_names = "your_output_operation"
input_names = "your_input_operation"

with tf.Session() as session:

    # Of course, your tag can be different
    tf.saved_model.loader.load(session, 
                               tf.saved_model.tag_constants.SERVING, 
                               "/here/is/mymodel/exported/with/SavedModel")
    x = obtain_your_example_as_numpy_array()
    results = session.run(output_names, feed_dict={input_names: x})

据我回忆,您可以指定多个输出名称,这个方向可能是一个可行的解决方案。要获取输入和输出名称,可以使用SavedModel CLI或打印操作并获取指定输入的名称。通常,它们的命名方式如下:input_1:0(用于命名约定的说明,您可以检查this)用于输入,predictions/Softmax:0用于输出(如果是多类分类)。输出的名称会根据导出的模型规格,确切的图层等而有所不同。

希望这篇文章至少对您有所帮助

PS。我认为您最好的办法就是让tf.Estimator独自一人,据我所知这是不可用的,并且看起来像是一堆脏乱的代码。

答案 1 :(得分:2)

  

如何访问各个图层以及如何访问.reset_states()方法?

估算器本身是建立在tf.keras.layers上的,这是您访问图层的方式。

Estimator API在底层Tensorflow API核心上提供了高层API。目的是向最终用户隐藏图表和会话的详细信息。


为什么tf.estimator存在?

  • 您可以在本地主机或分布式多服务器环境上运行基于Estimator的模型,而无需更改模型。此外,您可以在CPU,GPU或TPU上运行基于Estimator的模型,而无需重新编码模型。

  • 估计器简化了模型开发人员之间的共享实现。您可以使用高级直观代码来开发最新模型。简而言之,与低级TensorFlow API相比,使用Estimators创建模型通常要容易得多。

  • 估算器为您构建图形。

  • 估计器提供了一个安全的分布式训练循环,用于控制如何以及何时执行以下操作:

    • 构建图形

    • 初始化变量

    • 加载数据

    • 处理异常

    • 创建检查点文件并从故障中恢复

    • 为TensorBoard保存摘要


方便的the Estimator class详细信息。