python – 在创建Estimator之后更改Keras状态RNN模型,图层和方法的状态

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

我们来看一个这个例子吧.我有一个Keras RNN,这是一个有状态的模型.这意味着当实时数据进入预测时,我需要执行以下步骤:

>重置模型状态
>设置此用户上次预测的状态(如果这是旧用户)
>运行预测(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])

编辑
Estimator Layers《python – 在创建Estimator之后更改Keras状态RNN模型,图层和方法的状态》

最佳答案 关于tf.Estimator的好处几点

What is the benefit of using tf.keras.estimator.model_to_estimator over a stand-alone keras model? For example, when we wish to serve the model in real time?

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

>

You can run Estimator-based models on a local host or on a distributed multi-server environment without changing your model. Furthermore, you can run Estimator-based models on CPUs, GPUs, or TPUs without recoding your model.

好吧,Keras模型也可以在CPU和GPU上运行“无需重新编码”.有关分布式培训的真相,如果您需要,可能值得与tf.Estimator麻烦一起去.此外,作为Tensorflow 2.0 is coming,我不会非常依赖这个高级API.方向相当清晰,Tensorflow将变得更加面向Keras和PyTorch(当涉及第二个框架时,它的tf.Eager高级API),tf.Estimator并不真正符合它的功能导向设计.

>

Estimators simplify sharing implementations between model developers.

我能说什么,他们没有,只是看看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)

哦,不要忘记这个文档不会告诉你如何加载这个模型并在之后使用它(你可以加载到当前会话中,例如,如果你知道输入和输出节点的名称,那么很容易分享这些模型,爱它).

>

You can develop a state of the art model with high-level intuitive code. In short, it is generally much easier to create models with Estimators than with the low-level TensorFlow APIs.

这一点已经涵盖,实际上,估计.比直觉比Tensorflow更直观,但我怀疑它在tf.keras面前是否有任何成功.仍然,通过三种不同的模式,它是毫无意义的功能导向设计(导出的所有乐趣),会让我说它是一个中级API(总是很好有多个API)

>

Estimators are themselves built on tf.keras.layers, which simplifies customization.

好吧,那就是1.9或1.8中的tf.layers,但这已经被弃用了,所以当谈到Tensorflow长期的良好实践时.

总而言之:我不是很喜欢服务(不能浪费我的时间在下一个非直观的代码上,如tf.estimator.export.build_raw_serving_input_receiver_fn这样的名字),但如果可能的话,你最好避免使用它,因为它很差设计.

也许可以用Keras模型进行预测,这可以节省你一些时间,但这只是我的意见.

访问各个图层

首先:tf.Estimator不像Keras模特!

How can I access individual layers and how can I access the .reset_states() method?

好吧,这就是乐趣的开始.您必须在当前会话中获取模型(例如,加载导出的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)用于输入,而预测/ Softmax:0用于输出(如果它是多类分类).您的输出名称将根据导出的型号规格,精确层等而有所不同.

我希望这篇文章能帮助你至少一点点

PS.我认为你能做的最好的事情就是单独留下tf.Estimator,根据我的知识它是无法使用的,看起来就像一堆肮脏的黑客在代码方面被抛在一起.

点赞