我有这个问题,我想要导入我之前冻结的TensorFlow图。
错误:
graph_def is invalid at node 'block1/conv2d/kernel/Assign': Input tensor 'block1/conv2d/kernel:0' Cannot convert a tensor of type float32 to an input of type float32_ref.
我已经构建了一个自定义模型,主要用于在我的应用程序中进行概念验证。我正在为conv2d和batch_norm使用tf.layers包装器。
自定义型号代码:
...
@staticmethod
def conv_batch_relu(inputs, filters, kernel_size, is_training):
cv = tf.layers.conv2d(inputs=inputs, filters=filters, kernel_size=kernel_size, use_bias=True, activation=None)
bn = tf.layers.batch_normalization(inputs=cv, training=is_training, fused=True)
return tf.nn.relu(bn)
def build_network(self):
x = tf.placeholder(tf.float32, [None] + self.dataset['input_dims'], name='input')
y = tf.placeholder(tf.float32, [None] + [self.dataset['output_dims']], name='labels')
is_training = tf.placeholder(tf.bool, name='is_training')
with tf.variable_scope('block1'):
conv1 = CNN.conv_batch_relu(inputs=self.x, filters=64, kernel_size=3, is_training=self.is_training)
conv2 = CNN.conv_batch_relu(inputs=conv1, filters=64, kernel_size=3, is_training=self.is_training)
pool1 = tf.layers.max_pooling2d(inputs=conv2, pool_size=2, strides=2)
with tf.variable_scope('block2'):
conv3 = CNN.conv_batch_relu(inputs=pool1, filters=128, kernel_size=3, is_training=self.is_training)
conv4 = CNN.conv_batch_relu(inputs=conv3, filters=128, kernel_size=3, is_training=self.is_training)
pool2 = tf.layers.max_pooling2d(inputs=conv4, pool_size=2, strides=2)
next_shape = int(pool2.shape[1] * pool2.shape[2] * pool2.shape[3])
next_output = (next_shape // 4)
with tf.name_scope('fc1'):
flat_fc1 = tf.layers.flatten(inputs=pool2)
fc1 = tf.layers.dense(inputs=flat_fc1, units=next_output, activation=tf.nn.relu)
with tf.name_scope('dropout'):
fc1_drop = tf.layers.dropout(inputs=fc1)
with tf.name_scope('logits'):
self.yhat = tf.layers.dense(inputs=fc1_drop, units=self.dataset['output_dims'], activation=None, name='yhat')
with tf.name_scope('loss'):
self.cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=self.y, logits=self.yhat), name='cross_entropy')
self.optimizer = tf.train.AdamOptimizer(self.hyperparams['learning_rate']['user'], name='optimizer').minimize(self.cross_entropy)
外部函数负责冻结图形以进行推理。我找到了一篇博客文章(https://blog.metaflow.fr/tensorflow-how-to-freeze-a-model-and-serve-it-with-a-python-api-d4f3596b3adc),然后关注它以冻结图表。
负责冻结图表的代码:
absolute_model_dir = '{0}/frozen_model.pb'.format('.')
with tf.Session(graph=tf.Graph()) as sess:
saver = tf.train.import_meta_graph(input_checkpoint + '.meta', clear_devices=True)
saver.restore(sess, input_checkpoint)
node_names = [n.name for n in tf.get_default_graph().as_graph_def().node]
output_graph_def = tf.graph_util.convert_variables_to_constants(sess, tf.get_default_graph().as_graph_def(), node_names)
with tf.gfile.GFile(absolute_model_dir, 'wb') as outfile:
outfile.write(output_graph_def.SerializeToString())
另一个函数负责加载冻结图以进行推理。
负责加载图表的代码:
with tf.gfile.GFile('{0}/frozen_model.pb'.format(path), 'rb') as infile:
graph_def = tf.GraphDef()
graph_def.ParseFromString(infile.read())
# fix nodes for batch_norm
# based on https://github.com/tensorflow/tensorflow/issues/3628
for node in graph_def.node:
if node.op == 'RefSwitch':
node.op = 'Switch'
for index in range(len(node.input)):
if 'moving_' in node.input[index]:
node.input[index] = node.input[index] + '/read'
elif node.op == 'AssignSub':
node.op = 'Sub'
if 'use_locking' in node.attr: del node.attr['use_locking']
elif node.op == 'Assign':
if 'use_locking' in node.attr: del node.attr['use_locking']
graph = tf.import_graph_def(graph_def) # <---- This is the line that breaks !
我的TensorFlow版本是1.7(tensorflow-gpu 1.7),我之前尝试过1.6,导致同样的错误。我目前在virtualenv中使用Python 3.6.3。
查看github问题的讨论(上面其中一条评论中的链接)我知道' block1 / conv2d / kernel / Assign <中的' Assign '关键字/ em>'似乎是错误来源的一个很好的候选者,但我真的不确定它是如何在tensorflow中使用的,以及它为什么会导致错误。这对我来说现在感觉有点过于“黑魔法”了。
你们有没有偶然发现类似的事情并找到了解决问题的原因?
任何帮助表示感谢,谢谢!