【问题标题】:reading a protobuf created with TF2 using TF1使用 TF1 读取使用 TF2 创建的 protobuf
【发布时间】:2020-08-18 00:55:16
【问题描述】:

我有一个存储为 hdf5 的模型,我使用 saved_model.save 将其导出到 protobuf (PB) 文件,如下所示:

from tensorflow import keras
import tensorflow as tf
model = keras.models.load_model("model.hdf5")
tf.saved_model.save(model, './output_dir/')

这工作正常,结果是一个 saved_model.pb 文件,我以后可以用其他软件查看,没有问题。

但是,当我尝试使用 TensorFlow1 导入此 PB 文件时,我的代码失败了。由于 PB 应该是一种通用格式,这让我感到困惑。

我用来读取PB文件的代码是这样的:

import tensorflow as tf
curr_graph = tf.Graph()
curr_sess = tf.InteractiveSession(graph=curr_graph)
f = tf.gfile.GFile('model.hdf5','rb')
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
f.close()

这是我得到的例外:

Traceback(最近一次调用最后一次):文件“read_pb.py”,第 14 行,在 graph_def.ParseFromString(f.read()) google.protobuf.message.DecodeError: 解析消息出错​​p>

我有一个不同的模型存储为 PB 文件,读取代码可以正常工作。

发生了什么事?

***** 编辑 1 *****

在下面使用 Andrea Angeli 的代码时,我遇到了以下错误:

遇到错误:NodeDef 未提及 attr 'exponential_avg_factor' 在 Op y:T、batch_mean:U、batch_variance:U、 保留空间_1:U,保留空间_2:U,保留空间_3:U; attr=T:type,allowed=[DT_HALF, DT_BFLOAT16, DT_FLOAT]; attr=U:type,allowed=[DT_FLOAT]; attr=epsilon:float,default=0.0001; attr=data_format:string,default="NHWC",allowed=["NHWC", "NCHW"]; attr=is_training:bool,default=true>;节点定义:{节点 u-mobilenetv2/bn_Conv1/FusedBatchNormV3}。 (检查您的 GraphDef 解释二进制文件是最新的 GraphDef 生成二进制文件。)。

有解决办法吗?

【问题讨论】:

    标签: python tensorflow tensorflow2.0


    【解决方案1】:

    您正在尝试读取 hdf5 文件,而不是您使用 tf.saved_model.save(..) 保存的 protobuf 文件。另请注意,TF2 导出的 protobuf 与 TF 1 的冻结图不同,因为它只包含计算图。

    编辑 1: 如果要从 TF 2 模型中导出 TF 1 样式的冻结图,可以使用以下代码 sn-p 完成:

    from tensorflow.python.framework import convert_to_constants
    
    def export_to_frozen_pb(model: tf.keras.models.Model, path: str) -> None:
        """
        Creates a frozen graph from a keras model.
    
        Turns the weights of a model into constants and saves the resulting graph into a protobuf file.
    
        Args:
            model: tf.keras.Model to convert into a frozen graph
            path: Path to save the profobuf file
        """
        inference_func = tf.function(lambda input: model(input))
    
        concrete_func = inference_func.get_concrete_function(tf.TensorSpec(model.inputs[0].shape, model.inputs[0].dtype))
        output_func = convert_to_constants.convert_variables_to_constants_v2(concrete_func)
    
        graph_def = output_func.graph.as_graph_def()
        graph_def.node[-1].name = 'output'
    
        with open(os.path.join(path, 'saved_model.pb'), 'wb') as freezed_pb:
            freezed_pb.write(graph_def.SerializeToString())
    

    这将在您在 path 参数中指定的位置生成一个 protobuf 文件 (saved_model.pb)。您的图形的输入节点将具有名称“input:0”(这是由 lambda 实现的)和输出节点“output:0”。

    【讨论】:

    • 感谢收看这个。我知道 TF2 导出的 protobuf 和 TF1 的冻结图之间存在差异。我想要的是只导出冻结的图形,但从 TF2 导出。有没有办法做到这一点?
    • 更新了我对您的用例的回答。但是我不建议从 tensorflow 2 导出冻结图,官方不支持。如您所见,这是通过使用 tensorflow 的私有 API 完成的。
    • 您的代码可以运行,但存在导入错误。我将编辑我的问题以获取更多信息
    • 这不是导入错误,而是兼容性问题。 TF 2 图中有一个节点,TF 1 无法识别。正如我所说,不建议完全出于这个原因在 TF 1 中使用 TF 2 冻结图。它已不推荐使用,并且 TF 2 可以包含 TF 1 中没有的功能。如果您需要 TF 1 功能,请使用 TF 1 创建模型。
    猜你喜欢
    • 2020-12-18
    • 2022-01-11
    • 2020-08-21
    • 2020-02-03
    • 2020-03-25
    • 2020-02-03
    • 1970-01-01
    • 1970-01-01
    • 2012-06-12
    相关资源
    最近更新 更多