【问题标题】:How to run multiple graphs in a Session - Tensorflow API如何在一个会话中运行多个图 - Tensorflow API
【发布时间】:2018-03-18 23:08:30
【问题描述】:

Tensorflow API 提供了很少的预训练模型,并允许我们使用任何数据集训练它们。

我想知道如何在一个 tensorflow 会话中初始化和使用多个图。我想在两个图中导入两个经过训练的模型并将它们用于对象检测,但是我在尝试在一个会话中运行多个图时迷失了方向。

是否有任何特定方法可以在一个会话中处理多个图表?

另一个问题是,即使我为 2 个不同的图表创建两个不同的会话并尝试使用它们,我最终会在第二个会话中得到与第一个实例化会话类似的结果。

【问题讨论】:

    标签: python session tensorflow models object-detection


    【解决方案1】:

    每个Session 只能有一个Graph。话虽如此,根据您的具体目标,您有多种选择。

    第一个选项是创建两个单独的会话并将一个图表加载到每个会话中。您提到您使用这种方法在每次会话中都得到了出乎意料的相似结果,但是如果没有更多细节,很难弄清楚您的具体情况是什么问题。我怀疑每个会话都加载了相同的图表,或者当您尝试单独运行每个会话时,同一会话会运行两次,但如果没有更多细节,很难说。

    第二个选项是将两个图加载为主会话图的子图。您可以在图表中创建两个范围,并为要在该范围内加载的每个图表构建图表。然后您可以将它们视为独立图,因为它们之间没有连接。运行普通图形全局函数时,您需要指定这些函数适用于哪个范围。例如,当使用优化器对其中一个子图执行更新时,您只需使用 this answer 中所示的内容获取该子图范围内的可训练变量。

    除非您明确需要这两个图能够在 TensorFlow 图中以某种方式进行交互,否则我会推荐第一种方法,这样您就不需要跳过具有子图所需的额外环节(例如需要过滤您在任何给定时刻使用的范围,以及在两者之间共享图形全局事物的可能性。

    【讨论】:

    • 感谢您的回复。我不知道第二个选项的性能,但是创建两个会话可能会对 CPU/GPU 产生很大的负载,然后我们可能无法实时使用它们。您认为选择第二个选项会对 CPU 产生类似或较小的影响吗?我会尽快为您提供有关创建不同会话问题的更多详细信息。
    • @SaiKishorKothakota:除非两个加载的图表共享变量,否则我认为拥有两个会话不会导致比将它们都加载到单个会话中更大的 CPU/GPU 使用率。与图形元素本身的内存使用相比(在大多数情况下),会话的开销应该很小。
    • 请在此处找到代码:pastebin.com/VnN8f8FC。如果可以的话,试着给你的cmets。谢谢,
    • @SaiKishorKothakota:我不确定您在代码的其他部分中还可以对这些图表做什么,但看起来您只加载了GraphDef。它通常只包含图结构,而不包含训练的权重。如果您使用的是预训练模型,则还需要从检查点文件中加载权重。如果您正在训练模型,请确保您没有在每个训练步骤中使用这些函数之一重新创建图表。
    • 我也在加载图表权重,这就是这里的做法:github.com/tensorflow/models/blob/master/research/…。类似的我只是使用函数,我发现我修改了函数之间的函数调用,第二个调用函数的输出与第一个相似,而不管我在调用中提供的会话信息。如果权重没有加载,显然我不会得到结果。
    【解决方案2】:

    我面临同样的挑战,经过几个月的研究,我终于能够解决这个问题。我用tf.graph_util.import_graph_def 做了。根据documentation

    name:(可选。)将添加到名称前面的前缀 图定义。请注意,这不适用于导入的函数名称。 默认为“导入”。

    因此通过添加此前缀,可以区分不同的会话。

    例如:

    first_graph_def = tf.compat.v1.GraphDef()
    second_graph_def = tf.compat.v1.GraphDef()
    
    # Import the TF graph : first
    first_file = tf.io.gfile.GFile(first_MODEL_FILENAME, 'rb')
    first_graph_def.ParseFromString(first_file.read())
    first_graph = tf.import_graph_def(first_graph_def, name='first')
    
    # Import the TF graph : second
    second_file = tf.io.gfile.GFile(second_MODEL_FILENAME, 'rb')
    second_graph_def.ParseFromString(second_file.read())
    second_graph = tf.import_graph_def(second_graph_def, name='second')
    
    # These names are part of the model and cannot be changed.
    first_output_layer = 'first/loss:0'
    first_input_node = 'first/Placeholder:0'
    
    second_output_layer = 'second/loss:0'
    second_input_node = 'second/Placeholder:0'
    
    # initialize probability tensor
    first_sess = tf.compat.v1.Session(graph=first_graph)
    first_prob_tensor = first_sess.graph.get_tensor_by_name(first_output_layer)
    
    second_sess = tf.compat.v1.Session(graph=second_graph)
    second_prob_tensor = second_sess.graph.get_tensor_by_name(second_output_layer)
    
    first_predictions, = first_sess.run(
            first_prob_tensor, {first_input_node: [adapted_image]})
        first_highest_probability_index = np.argmax(first_predictions)
    
    second_predictions, = second_sess.run(
            second_prob_tensor, {second_input_node: [adapted_image]})
        second_highest_probability_index = np.argmax(second_predictions)
    

    如您所见,您现在可以在一个 TensorFlow 会话中初始化和使用多个图。

    希望这会有所帮助

    【讨论】:

      【解决方案3】:

      一个会话中的图 arg 应该是 None 或图的一个实例。

      这里是source code

      class BaseSession(SessionInterface):
        """A class for interacting with a TensorFlow computation.
        The BaseSession enables incremental graph building with inline
        execution of Operations and evaluation of Tensors.
        """
      
        def __init__(self, target='', graph=None, config=None):
          """Constructs a new TensorFlow session.
          Args:
            target: (Optional) The TensorFlow execution engine to connect to.
            graph: (Optional) The graph to be used. If this argument is None,
              the default graph will be used.
            config: (Optional) ConfigProto proto used to configure the session.
          Raises:
            tf.errors.OpError: Or one of its subclasses if an error occurs while
              creating the TensorFlow session.
            TypeError: If one of the arguments has the wrong type.
          """
          if graph is None:
            self._graph = ops.get_default_graph()
          else:
            if not isinstance(graph, ops.Graph):
              raise TypeError('graph must be a tf.Graph, but got %s' % type(graph))
      

      我们可以从下面的 sn-p 看出它不能是一个列表。

      if graph is None:
        self._graph = ops.get_default_graph()
      else:
        if not isinstance(graph, ops.Graph):
          raise TypeError('graph must be a tf.Graph, but got %s' % type(graph))
      

      并且从ops.Graph(find by help(ops.Graph)) 对象中可以看出,它不可能是多个图。

      对于more的看法和图:

      If no `graph` argument is specified when constructing the session,
      the default graph will be launched in the session. If you are
      using more than one graph (created with `tf.Graph()` in the same
      process, you will have to use different sessions for each graph,
      but each graph can be used in multiple sessions. In this case, it
      is often clearer to pass the graph to be launched explicitly to
      the session constructor.
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-08-02
        • 2018-11-21
        • 2020-06-15
        • 2019-06-08
        • 2020-01-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多