【问题标题】:Tensorflow : how to insert custom input to existing graph?Tensorflow:如何将自定义输入插入现有图形?
【发布时间】:2016-12-01 19:38:24
【问题描述】:

我已经下载了一个实现 VGG16 ConvNet 的 tensorflow GraphDef,我用它来做这个:

Pl['images'] = tf.placeholder(tf.float32, 
                          [None, 448, 448, 3],
                          name="images") #batch x width x height x channels
with open("tensorflow-vgg16/vgg16.tfmodel", mode='rb') as f: 
    fileContent = f.read()

graph_def = tf.GraphDef()
graph_def.ParseFromString(fileContent)
tf.import_graph_def(graph_def, input_map={"images": Pl['images']})

此外,我的图像特征与"import/pool5/" 的输出是同质的。

如何告诉我的图表不想使用他的输入"images",而是使用张量"import/pool5/" 作为输入?

谢谢!

编辑

好吧,我意识到我不是很清楚。情况如下:

我正在尝试使用this implementation 的 ROI 池,使用预先训练的 VGG16,我有 GraphDef 格式。所以这就是我所做的:

首先,我加载模型:

tf.reset_default_graph()
with open("tensorflow-vgg16/vgg16.tfmodel",
          mode='rb') as f:
    fileContent = f.read()
graph_def = tf.GraphDef()
graph_def.ParseFromString(fileContent)
graph = tf.get_default_graph()

然后,我创建占位符

images = tf.placeholder(tf.float32, 
                              [None, 448, 448, 3],
                              name="images") #batch x width x height x channels
boxes = tf.placeholder(tf.float32, 
                             [None,5], # 5 = [batch_id,x1,y1,x2,y2]
                             name = "boxes")

我将图的第一部分的输出定义为 conv5_3/Relu

tf.import_graph_def(graph_def, 
                    input_map={'images':images})
out_tensor = graph.get_tensor_by_name("import/conv5_3/Relu:0")

所以,out_tensor 的形状是 [None,14,14,512]

然后,我进行 ROI 池化:

[out_pool,argmax] = module.roi_pool(out_tensor,
                                    boxes,
                                    7,7,1.0/1) 

使用out_pool.shape = N_Boxes_in_batch x 7 x 7 x 512,与pool5 同构。然后我想将out_pool 作为输入到紧跟在pool5 之后的操作,所以它看起来像

tf.import_graph_def(graph.as_graph_def(),
                    input_map={'import/pool5':out_pool})

但它不起作用,我有这个错误:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-89-527398d7344b> in <module>()
      5 
      6 tf.import_graph_def(graph.as_graph_def(),
----> 7                     input_map={'import/pool5':out_pool})
      8 
      9 final_out = graph.get_tensor_by_name("import/Relu_1:0")

/usr/local/lib/python3.4/dist-packages/tensorflow/python/framework/importer.py in import_graph_def(graph_def, input_map, return_elements, name, op_dict)
    333       # NOTE(mrry): If the graph contains a cycle, the full shape information
    334       # may not be available for this op's inputs.
--> 335       ops.set_shapes_for_outputs(op)
    336 
    337       # Apply device functions for this op.

/usr/local/lib/python3.4/dist-packages/tensorflow/python/framework/ops.py in set_shapes_for_outputs(op)
   1610       raise RuntimeError("No shape function registered for standard op: %s"
   1611                          % op.type)
-> 1612   shapes = shape_func(op)
   1613   if len(op.outputs) != len(shapes):
   1614     raise RuntimeError(

/home/hbenyounes/vqa/roi_pooling_op_grad.py in _roi_pool_shape(op)
     13   channels = dims_data[3]
     14   print(op.inputs[1].name, op.inputs[1].get_shape())
---> 15   dims_rois = op.inputs[1].get_shape().as_list()
     16   num_rois = dims_rois[0]
     17 

/usr/local/lib/python3.4/dist-packages/tensorflow/python/framework/tensor_shape.py in as_list(self)
    745       A list of integers or None for each dimension.
    746     """
--> 747     return [dim.value for dim in self._dims]
    748 
    749   def as_proto(self):

TypeError: 'NoneType' object is not iterable

有什么线索吗?

【问题讨论】:

  • input_map 可以在图中任意输入名称。我会打印出 graph_def 以找出池输出的确切名称
  • 如果我理解你的问题,你有一个操作,例如: y=tf.mul(x,W) 并且你想将其输入 x 修改为来自另一个网络的另一个张量 xprime ?跨度>

标签: graph tensorflow subgraph


【解决方案1】:

通常使用tf.train.export_meta_graph来存储整个MetaGraph非常方便。然后,在恢复时,您可以使用tf.train.import_meta_graph因为事实证明,它将所有附加参数传递给具有input_map 参数的底层import_scoped_meta_graph,并在它自己的时候使用它调用import_graph_def

它没有记录在案,我花了太多时间才找到它,但它确实有效!

【讨论】:

    【解决方案2】:

    我会做的是沿着这些思路:

    -首先检索表示 VGG16 中 pool5 之后的 3 个全连接层的权重和偏差的张量名称。
    为此,我会检查[n.name for n in graph.as_graph_def().node]。 (它们可能看起来像 import/locali/weight:0、import/locali/bias:0 等)

    -将它们放在python列表中:

    weights_names=["import/local1/weight:0" ,"import/local2/weight:0" ,"import/local3/weight:0"]
    biases_names=["import/local1/bias:0" ,"import/local2/bias:0" ,"import/local3/bias:0"]
    

    - 定义一个看起来像这样的函数:

    def pool5_tofcX(input_tensor, layer_number=3):
      flatten=tf.reshape(input_tensor,(-1,7*7*512))
      tmp=flatten
      for i in xrange(layer_number):
        tmp=tf.matmul(tmp, graph.get_tensor_by_name(weights_name[i]))
        tmp=tf.nn.bias_add(tmp, graph.get_tensor_by_name(biases_name[i]))
        tmp=tf.nn.relu(tmp)
      return tmp
    

    然后使用函数定义张量:

    wanted_output=pool5_tofcX(out_pool) 
    

    那么你就完成了!

    【讨论】:

    • 好像可以了,谢谢!我只是将 14*14 更改为 7*7(因为它是在最大池化之后),我在bias_add 之后添加了 ReLu。
    • 是的,忘了 RELU 会做出改变!
    【解决方案3】:

    Jonan Georgiev 在这里提供了一个很好的答案。同样的方法在这个 git 问题的结尾也被描述得很少:https://github.com/tensorflow/tensorflow/issues/3389

    下面是一个复制/粘贴的可运行示例,使用这种方法来切换出tf.data.Dataset get_next 张量的占位符。

    import tensorflow as tf
    
    
    my_placeholder = tf.placeholder(dtype=tf.float32, shape=1, name='my_placeholder')
    my_op = tf.square(my_placeholder, name='my_op')
    
    # Save the graph to memory
    graph_def = tf.get_default_graph().as_graph_def()
    
    print('----- my_op before any remapping -----')
    print([n for n in graph_def.node if n.name == 'my_op'])
    
    tf.reset_default_graph()
    
    ds = tf.data.Dataset.from_tensors(1.0)
    next_tensor = tf.data.make_one_shot_iterator(ds).get_next(name='my_next_tensor')
    
    # Restore the graph with a custom input mapping
    tf.graph_util.import_graph_def(graph_def, input_map={'my_placeholder': next_tensor}, name='')
    
    print('----- my_op after remapping -----')
    print([n for n in tf.get_default_graph().as_graph_def().node if n.name == 'my_op'])
    

    输出,这里我们可以清楚地看到平方运算的输入发生了变化。

    ----- my_op before any remapping -----
    [name: "my_op"
    op: "Square"
    input: "my_placeholder"
    attr {
      key: "T"
      value {
        type: DT_FLOAT
      }
    }
    ]
    
    ----- my_op after remapping -----
    [name: "my_op"
    op: "Square"
    input: "my_next_tensor"
    attr {
      key: "T"
      value {
        type: DT_FLOAT
      }
    }
    ]
    

    【讨论】:

      猜你喜欢
      • 2020-11-25
      • 2018-04-18
      • 2020-02-11
      • 1970-01-01
      • 1970-01-01
      • 2018-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多