在不同机器上保存和加载 Universal Sentence Encoder 模型

Save and load Universal Sentence Encoder model on different machines

我们如何在不同的机器上保存和加载 Universal Sentence Encoder 模型?

我用 USE 创建了一个 Keras 模型并保存在机器 A 上。

from tensorflow.keras.layers import Dense, Dropout, Input
from tensorflow.keras.models import Model, load_model
import tensorflow_hub as hub
import tensorflow as tf

module_url = "/path/on/machine/A/universal-sentence-encoder_4"
emb = hub.KerasLayer(module_url, input_shape=[], dtype=tf.string, trainable=True)

input1 = Input(shape=[], dtype=tf.string)
embedding_layer = emb(input1)
dense1 = Dense(units=512, activation="relu")(embedding_layer)
outputs = Dense(1, activation="sigmoid")(dense1)

model = Model(inputs=input1, outputs=outputs)
model.compile(optimizer="adam", loss="binary_crossentropy", metrics=["AUC"])
model.save("model.h5", include_optimizer=False)

现在我想在机器B上打开model.h5,预训练的USE保存在这里/different/path/on/machine/B/universal-sentence-encoder_4。这是我得到的错误。

model = load_model("model.h5", custom_objects={"KerasLayer": hub.KerasLayer})

~/anaconda3/envs/tensorflow/lib/python3.8/site-packages/tensorflow_hub/resolver.py in __call__(self, handle)
    494   def __call__(self, handle):
    495     if not tf.compat.v1.gfile.Exists(handle):
--> 496       raise IOError("%s does not exist." % handle)
    497     return handle
    498 

OSError: /path/on/machine/A/universal-sentence-encoder_4 does not exist.

我该如何解决这个问题?有没有一种方法可以将包括 universal-sentence-encoder_4 在内的所有内容都保存到一个 model.h5 文件中,以便用户无需担心 USE?

tensorflow 版本:2.4.1 keras 版本:2.4.0

更新:根据 WGierke's advice, created Google Colab 来演示问题。

此处的问题与您所观察到的有关 : saving a Keras model requires serializing everything that is contained in the model. When you initialize a hub.KerasLayer using a generic Callable like loaded_obj, it cannot be serialized. Instead, you have to pass a string handle that points to the path of the SavedModel (or the tfhub.dev URL). When the Keras model is saved, KerasLayer.get_config 被调用,它使用键 handle.

将该字符串存储在配置条目中

恢复 Keras 模型时,配置被反序列化,Keras 运行 hub.KerasLayer(config["handle"])。如您所见,如果存储在 handle 的模型不再可用,这将失败。

不幸的是,目前唯一的解决方法是确保引用的路径在机器 B 上也可用。