Tensorflow:如何将自定义输入插入现有图形?
Tensorflow : how to insert custom input to existing graph?
我下载了一个实现 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
有什么线索吗?
我会做的是这些方面的事情:
-首先检索表示 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)
完成!
通常使用tf.train.export_meta_graph
来存储整个MetaGraph是非常方便的。然后,在恢复时,您可以使用 tf.train.import_meta_graph
、 因为 事实证明它将所有其他参数传递给具有 input_map
参数的基础 import_scoped_meta_graph
并在它自己调用 import_graph_def
时使用它。
它没有记录在案,我花了太多时间才找到它,但它确实有效!
Jonan Georgiev 在这里提供了一个很好的答案。在这个 git 问题的末尾也描述了同样的方法,但没有大张旗鼓:https://github.com/tensorflow/tensorflow/issues/3389
下面是一个 copy/paste 可运行示例,使用此方法为 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
}
}
]
我下载了一个实现 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
有什么线索吗?
我会做的是这些方面的事情:
-首先检索表示 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)
完成!
通常使用tf.train.export_meta_graph
来存储整个MetaGraph是非常方便的。然后,在恢复时,您可以使用 tf.train.import_meta_graph
、 因为 事实证明它将所有其他参数传递给具有 input_map
参数的基础 import_scoped_meta_graph
并在它自己调用 import_graph_def
时使用它。
它没有记录在案,我花了太多时间才找到它,但它确实有效!
Jonan Georgiev 在这里提供了一个很好的答案。在这个 git 问题的末尾也描述了同样的方法,但没有大张旗鼓:https://github.com/tensorflow/tensorflow/issues/3389
下面是一个 copy/paste 可运行示例,使用此方法为 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
}
}
]