【问题标题】:Save and load Universal Sentence Encoder model on different machines在不同的机器上保存和加载 Universal Sentence Encoder 模型
【发布时间】:2021-12-25 04:26:13
【问题描述】:

我们如何在不同的机器上保存和加载通用句子编码器模型?

我使用 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 文件中,这样用户就不用担心使用问题了?

tensorflow 版本:2.4.1keras 版本:2.4.0

更新:根据WGierke 的建议,创建Google Colab 来演示该问题。

【问题讨论】:

  • 您能否确认您确实在运行load_model("/different/path/on/B/.../model.h5", ...)?您的错误消息输出 /path/on/machine/A/... does not exist 似乎很奇怪,即使它是在机器 B 上执行的。
  • 是的,我知道它是有线的,但我无法弄清楚。 model.h5 的路径是正确的。当我在机器 A 上运行 load_model("model.h5") 时,它可以工作。但是如果我在同一台机器上重命名为universal-sentence-encoder_4_renamedload_model("model.h5") 将停止使用OSError universal-sentence-encoder_4 does not exist
  • 这确实很奇怪。你能提供一个完整的独立脚本来在一台机器上重现它吗?您可以从 tfhub.dev 获取模型,将其存储,例如在 /tmp/A,将 /tmp/A 移动到 /tmp/B 并尝试从 /tmp/B 加载它。我认为这会大大简化我们的调试。
  • 如果我更改为 hub.KerasLayer("tfhub.dev/google/universal-sentence-encoder/4"),load_model("model.h5") 在机器 A 和 B 上都可以工作。这个问题只有在本地 USE 路径改变时才会发生。试图找到一个本地解决方案,因为我的代码位于公司防火墙后面,无法从 Internet 加载。您能否详细说明“提供完整的自包含脚本”?我能够用代码复制问题sn-p 在我的工作以及个人电脑上。
  • model.to_json() 显示"handle": "/path/on/machine/A/universal-sentence-encoder_4"。所以 USW 路径在模型中是硬编码的。

标签: tensorflow keras tensorflow-hub


【解决方案1】:

这里的问题与您观察到的 in this SO question as well 有关:保存 Keras 模型需要序列化模型中包含的所有内容。当您使用像 loaded_obj 这样的通用 Callable 初始化 hub.KerasLayer 时,它不能被序列化。相反,您必须传递一个字符串 handle,它指向 SavedModel 的路径(或 tfhub.dev URL)。保存 Keras 模型时,会调用 KerasLayer.get_config,它将该字符串存储在配置条目中,键为 handle

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-15
    • 2022-07-23
    • 2020-09-15
    • 2020-05-26
    • 2020-11-19
    • 2020-01-30
    • 1970-01-01
    相关资源
    最近更新 更多