【问题标题】:Freezing graph to pb in Tensorflow2在 Tensorflow2 中将图形冻结为 pb
【发布时间】:2020-01-26 20:54:58
【问题描述】:

我们从 TF1 部署了很多模型,通过图形冻结来保存它们:

tf.train.write_graph(self.session.graph_def, some_path)

# get graph definitions with weights
output_graph_def = tf.graph_util.convert_variables_to_constants(
        self.session,  # The session is used to retrieve the weights
        self.session.graph.as_graph_def(),  # The graph_def is used to retrieve the nodes
        output_nodes,  # The output node names are used to select the usefull nodes
)

# optimize graph
if optimize:
    output_graph_def = optimize_for_inference_lib.optimize_for_inference(
            output_graph_def, input_nodes, output_nodes, tf.float32.as_datatype_enum
    )

with open(path, "wb") as f:
    f.write(output_graph_def.SerializeToString())

然后通过加载它们:

with tf.Graph().as_default() as graph:
    with graph.device("/" + args[name].processing_unit):
        tf.import_graph_def(graph_def, name="")
            for key, value in inputs.items():
                self.input[key] = graph.get_tensor_by_name(value + ":0")

我们希望以类似的方式保存 TF2 模型。一个包含图形和权重的 protobuf 文件。我怎样才能做到这一点?

我知道有一些保存方法:

  • keras.experimental.export_saved_model(model, 'path_to_saved_model')

    这是实验性的,会创建多个文件 :(.

  • model.save('path_to_my_model.h5')

    哪个保存h5格式:(.

  • tf.saved_model.save(self.model, "test_x_model")

    这又保存了多个文件:(。

【问题讨论】:

    标签: python tensorflow machine-learning tensorflow2.0


    【解决方案1】:

    我目前的做法是 TF2 -> SavedModel(通过keras.experimental.export_saved_model)-> frozen_graph.pb(通过freeze_graph 工具,可以将SavedModel 作为输入)。我不知道这是否是“推荐”的方式。

    另外,我仍然不知道如何加载冻结的模型并“以 TF2 方式”运行推理(也就是没有图表、会话等)。

    你也可以看看keras.save_model('path', save_format='tf'),它似乎会生成检查点文件(不过你仍然需要冻结它们,所以我个人认为保存的模型路径更好)

    【讨论】:

      【解决方案2】:

      我使用 TF2 转换模型如下:

      1. 在训练时将keras.callbacks.ModelCheckpoint(save_weights_only=True) 传递给model.fit 并保存checkpoint
      2. 训练后,self.model.load_weights(self.checkpoint_path)加载checkpoint,并转换为h5self.model.save(h5_path, overwrite=True, include_optimizer=False)
      3. h5转换为pb
      import logging
      import tensorflow as tf
      from tensorflow.compat.v1 import graph_util
      from tensorflow.python.keras import backend as K
      from tensorflow import keras
      
      # necessary !!!
      tf.compat.v1.disable_eager_execution()
      
      h5_path = '/path/to/model.h5'
      model = keras.models.load_model(h5_path)
      model.summary()
      # save pb
      with K.get_session() as sess:
          output_names = [out.op.name for out in model.outputs]
          input_graph_def = sess.graph.as_graph_def()
          for node in input_graph_def.node:
              node.device = ""
          graph = graph_util.remove_training_nodes(input_graph_def)
          graph_frozen = graph_util.convert_variables_to_constants(sess, graph, output_names)
          tf.io.write_graph(graph_frozen, '/path/to/pb/model.pb', as_text=False)
      logging.info("save pb successfully!")
      

      【讨论】:

      • 感谢此代码 sn-p!稍微更正:write_graph 需要文件名和目录名。否则似乎还不错
      • 这可行,但似乎关闭了会话,在我的用例中,我们无法每隔 n epochs(通过使用 on_epoch_end_callback)保存模型并将其导出到 .pb,有什么建议吗?
      • 更新:解决了这个问题,不使用 K.get_session() 作为 sess,而是使用 session = tf.compat.v1.keras.backend.get_session() 存储默认的 keras 会话
      【解决方案3】:

      上面的代码有点老了。转换vgg16可以成功,但是转换resnet_v2_50模型失败。我的 tf 版本是 tf 2.2.0 最后,我找到了一个有用的代码sn -p:

      import tensorflow as tf
      from tensorflow import keras
      from tensorflow.python.framework.convert_to_constants import     convert_variables_to_constants_v2
      import numpy as np
      
      
      #set resnet50_v2 as a example
      model = tf.keras.applications.ResNet50V2()
       
      full_model = tf.function(lambda x: model(x))
      full_model = full_model.get_concrete_function(
          tf.TensorSpec(model.inputs[0].shape, model.inputs[0].dtype))
      
      # Get frozen ConcreteFunction
      frozen_func = convert_variables_to_constants_v2(full_model)
      frozen_func.graph.as_graph_def()
       
      layers = [op.name for op in frozen_func.graph.get_operations()]
      print("-" * 50)
      print("Frozen model layers: ")
      for layer in layers:
          print(layer)
       
      print("-" * 50)
      print("Frozen model inputs: ")
      print(frozen_func.inputs)
      print("Frozen model outputs: ")
      print(frozen_func.outputs)
       
      # Save frozen graph from frozen ConcreteFunction to hard drive
      tf.io.write_graph(graph_or_graph_def=frozen_func.graph,
                        logdir="./frozen_models",
                        name="frozen_graph.pb",
                        as_text=False)
      

      参考:https://github.com/leimao/Frozen_Graph_TensorFlow/tree/master/TensorFlow_v2(更新)

      【讨论】:

      • 您分享的参考链接似乎已过期。可以再分享一下吗?
      • 抱歉回复太晚了。过期链接已更新,请查看
      【解决方案4】:

      我遇到了类似的问题,并在下面找到了解决方案,即

      from tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2
      from tensorflow.python.tools import optimize_for_inference_lib
      
      loaded = tf.saved_model.load('models/mnist_test')
      infer = loaded.signatures['serving_default']
      f = tf.function(infer).get_concrete_function(
                                  flatten_input=tf.TensorSpec(shape=[None, 28, 28, 1], 
                                                              dtype=tf.float32)) # change this line for your own inputs
      f2 = convert_variables_to_constants_v2(f)
      graph_def = f2.graph.as_graph_def()
      if optimize :
          # Remove NoOp nodes
          for i in reversed(range(len(graph_def.node))):
              if graph_def.node[i].op == 'NoOp':
                  del graph_def.node[i]
          for node in graph_def.node:
              for i in reversed(range(len(node.input))):
                  if node.input[i][0] == '^':
                      del node.input[i]
          # Parse graph's inputs/outputs
          graph_inputs = [x.name.rsplit(':')[0] for x in frozen_func.inputs]
          graph_outputs = [x.name.rsplit(':')[0] for x in frozen_func.outputs]
          graph_def = optimize_for_inference_lib.optimize_for_inference(graph_def,
                                                                        graph_inputs,
                                                                        graph_outputs,
                                                                        tf.float32.as_datatype_enum)
      # Export frozen graph
      with tf.io.gfile.GFile('optimized_graph.pb', 'wb') as f:
          f.write(graph_def.SerializeToString())

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-01-08
        • 1970-01-01
        • 2019-01-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多