简体   繁体   English

需要初始化的tf.keras自定义层无法使用tf.contrib.saved_model.save_keras_model保存

[英]tf.keras custom layer requiring initialization fails to save with tf.contrib.saved_model.save_keras_model

I'm trying to implement a custom lookup layer which converts strings to ints . 我正在尝试实现一个自定义查找层,该层将字符串转换为ints I need to save the model in a tensorflow serving format. 我需要将模型保存为张量流服务格式。 The model requires a lookup table which needs to be initialized. 该模型需要一个需要初始化的查找表。 In the custom layer build definition the table is initialized using the tf.keras.backend.get_session() session . 在自定义层构建定义中,使用tf.keras.backend.get_session() session初始化表。 This trains fine, but when saving with tf.contrib.saved_model.save_keras_model it throws the following error: 训练得很好,但是使用tf.contrib.saved_model.save_keras_model保存时,它将引发以下错误:

ValueError: Cannot use the given session to execute operation: the operation's graph is different from the session's graph.

The following code reproduces the error: import numpy as np import tensorflow as tf 以下代码重现该错误:numpy作为np导入tensorflow作为tf

class LookupLayer(tf.keras.layers.Layer):
  def __init__(self, mapping=[''], num_oov_buckets=0, default_value=-1, **kwargs):
    self.mapping=mapping
    self.num_oov_buckets=num_oov_buckets
    self.default_value=default_value
    super(LookupLayer, self).__init__(**kwargs)

  def build(self, input_shape):
    self.index_table = tf.contrib.lookup.index_table_from_tensor(
                    mapping=self.mapping,
                    num_oov_buckets=self.num_oov_buckets,
                    default_value=self.default_value,
                )
    self.index_table.init.run(session=tf.keras.backend.get_session())
    super(LookupLayer, self).build(input_shape)

  def call(self, input):
    return self.index_table.lookup(input)

  def compute_output_shape(self, input_shape):
    return input_shape

input = tf.keras.layers.Input(shape=(1,), dtype="string")
lookup_output = LookupLayer(mapping=['test'], num_oov_buckets=1)(input)
emb_layer = tf.keras.layers.Embedding(2, 1)(lookup_output)
x = tf.keras.layers.Flatten()(emb_layer)
x = tf.keras.layers.Dense(100, activation='relu')(x)
out = tf.keras.layers.Dense(1, activation='sigmoid')(x)
model = tf.keras.models.Model(inputs=input, outputs=out)
model.compile(optimizer=tf.train.AdamOptimizer(),
              loss='binary_crossentropy')

X={'input_1':np.array(['test', 'oov'])}
y=[0,1]
model.fit(X,y)

tf.contrib.saved_model.save_keras_model(model, './saved_model_test/', custom_objects={'LookupLayer': LookupLayer})

How do I get the right session to the custom tf.keras layer? 如何获得与自定义tf.keras层正确的会话? Or is there a better way to do this? 还是有更好的方法来做到这一点?

note: I need the string -> int lookup to be in the graph. 注意:我需要字符串-> int查找在图中。 I can't have it in a separate preprocessing step because I need it to be there for serving. 我无法在单独的预处理步骤中使用它,因为我需要它在那儿进行服务。

I was able to save the model to a pb file for serving by using simple_save instead of save_keras_model: 我能够通过使用simple_save而不是save_keras_model将模型保存到pb文件中以进行服务:

tf.saved_model.simple_save( keras.backend.get_session(), './simple_save/', inputs={t.name.split(':')[0]:t for t in model.input}, outputs={t.name.split(':')[0]:t for t in model.outputs}, legacy_init_op=tf.tables_initializer())

Note: make sure to use legacy_init_op=tf.tables_initializer() and NOT legacy_init_op=tf.saved_model.main_op.main_op() like the answer in How to keep lookup tables initialized for prediction (and not just training)? 注意:请确保使用legacy_init_op = tf.tables_initializer()而不是legacy_init_op = tf.saved_model.main_op.main_op(),如如何保持查找表初始化以进行预测(而不仅仅是训练)中的答案 suggests. 提示。 Otherwise it seems all weights get reset and your model is useless for serving. 否则,似乎所有权重都会重置,并且您的模型无法投放。

This does not fix the problem I made this post for (save_keras_model not working), but it solves my use case. 这不能解决我为之发表这篇文章的问题(save_keras_model不起作用),但可以解决我的用例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM