【问题标题】:tf.keras custom layer requiring initialization fails to save with tf.contrib.saved_model.save_keras_model需要初始化的 tf.keras 自定义层无法使用 tf.contrib.saved_model.save_keras_model 保存
【发布时间】:2019-05-28 16:40:33
【问题描述】:

我正在尝试实现将字符串转换为ints 的自定义查找层。我需要以 tensorflow 服务格式保存模型。该模型需要一个需要初始化的查找表。在自定义层构建定义中,表使用tf.keras.backend.get_session() session 进行初始化。这可以很好地训练,但是使用 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.

以下代码重现了错误: 将 numpy 导入为 np 将张量流导入为 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})

如何获得到自定义tf.keras 层的正确会话?或者有更好的方法吗?

注意:我需要字符串 -> int 查找在图表中。我不能在单独的预处理步骤中使用它,因为我需要它来提供服务。

【问题讨论】:

  • 您是否尝试过不调用init? Keras 可能会处理这个问题。
  • 我尝试了这个并且得到了一个新的错误:tensorflow.python.framework.errors_impl.InternalError: Model and clone must use the same variables.

标签: python keras


【解决方案1】:

我能够使用 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())

注意:确保使用 legacy_init_op=tf.tables_initializer() 而不是 legacy_init_op=tf.saved_model.main_op.main_op() 就像How to keep lookup tables initialized for prediction (and not just training)? 中的答案所建议的那样。否则,似乎所有权重都会重置,并且您的模型对服务毫无用处。

这并不能解决我发这篇文章的问题(save_keras_model 不起作用),但它解决了我的用例。

【讨论】:

    猜你喜欢
    • 2020-08-14
    • 2017-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-03
    • 1970-01-01
    • 2016-08-25
    相关资源
    最近更新 更多