Skip to main content
 首页 » 编程设计

python之Tensorflow负载模型错误

2024年10月01日2698°冷暖

我正在尝试加载以前保存的 TENSOFLOW 模型(图形和变量)。

这是我在训练期间导出模型的方式

tf.global_variables_initializer().run() 
y = tf.matmul(x, W) + b 
 
cross_entropy = tf.reduce_mean( 
    tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y)) 
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy) 
 
for batch_index in range(batch_size): 
    batch_xs, batch_ys = sample_dataframe(train_df, N=batch_size) 
    #print(batch_xs.shape) 
    #print(batch_ys.shape) 
    sess.run(train_step, feed_dict = {x: batch_xs, y_:batch_ys}) 
 
    if batch_index % 100 == 0: 
        print("Batch "+str(batch_index)) 
        correct_predictions = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1)) 
        accuracy = tf.reduce_mean(tf.cast(correct_predictions, tf.float32)) 
        print("Accuracy: "+str(sess.run(accuracy, 
                                                  feed_dict = {x: batch_xs, y_: batch_ys}))) 
        #print("Predictions "+str(y)) 
        #print("Training accuracy: %.1f%%" %accuracy()) 
    if batch_index + 1 == batch_size: 
        #Save the trained model 
        print("Exporting trained model") 
        builder = saved_model_builder.SavedModelBuilder(EXPORT_DIR) 
        builder.add_meta_graph_and_variables(sess, ['simple-MNIST']) 
        builder.save(as_text=True) 

请忽略模型的定义方式(这只是一个玩具示例),只检查调用保存方法的最后几行。一切顺利,模型正确保存在 FS 中。

当我尝试加载导出的模型时,我总是会收到以下错误:

TypeError: Can not convert a MetaGraphDef into a Tensor or Operation.

这是我加载模型的方式:

with tf.Session() as sess: 
  print(tf.saved_model.loader.maybe_saved_model_directory(export_dir)) 
  saved_model = tf.saved_model.loader.load(sess, ['simple-MNIST'], export_dir) 
 
  sess.run(saved_model) 

知道怎么解决吗?似乎模型以错误的格式导出,但我不知道如何更改它。

这是一个用于加载模型并对其评分的简单脚本。

with tf.device("/cpu:0"): 
  x = tf.placeholder(tf.float32, shape =(batch_size, 784)) 
  W = tf.Variable(tf.truncated_normal(shape=(784, 10), stddev=0.1)) 
  b = tf.Variable(tf.zeros([10])) 
  y_ = tf.placeholder(tf.float32, shape=(batch_size, 10)) 
 
with tf.Session() as sess: 
  tf.global_variables_initializer().run() 
 
  print(tf.saved_model.loader.maybe_saved_model_directory(export_dir)) 
  saved_model = tf.saved_model.loader.load(sess, ['simple-MNIST'], export_dir) 
 
  batch_xs, batch_ys = sample_dataframe(train_df, N=batch_size) 
  y = tf.matmul(x, W) + b 
  correct_predictions = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1)) 
  accuracy = tf.reduce_mean(tf.cast(correct_predictions, tf.float32))     
 
 print("Test Accuracy: "+ str(sess.run(accuracy, feed_dict = {x: batch_xs, y_: batch_ys}))) 

在全新的 PYTHON 上下文中运行此脚本,将以非常低的准确性对模型进行评分(似乎加载模型方法未正确设置图形变量)

谢谢!

请您参考如下方法:

我认为问题在于您无法将 saved_model 传递到 sess.run 中。来自 saved_model.loader.load 的文档:

Returns: The MetaGraphDef protocol buffer loaded in the provided session. This can be used to further extract signature-defs, collection-defs, etc.

那么,当 saved_model 是 MetaGraphDef 时,您对 sess.run(saved_model) 到底有什么期望?如果我正确理解了 load 的机制,那么图表以及相关变量将在您传递给 load(..) 的 session 中恢复,因此您的一旦 load(..) 完成,模型就可以使用了。因此,您应该能够像往常一样通过(默认)图形访问变量、操作和张量,并且无需进一步处理返回的 MetaGraphDef 对象。

这里是关于什么是 MetaGraphDef 的更多信息:What is the TensorFlow checkpoint meta file? .由此应该清楚,将它与 sess.run() 一起使用是没有意义的。

编辑

跟进您的编辑:函数 tf.saved_model.loader.load 在内部调用 tf.import_meta_graph,然后调用 saver.restore,也就是说,它恢复了图 和 图中存在的变量的值。因此,您不必在添加的代码片段的开头自行重新定义变量。事实上,它可能会导致未定义的行为,因为某些节点可能会在默认图中出现两次。查看此 stackoverflow 帖子以获取更多信息:Restoring Tensorflow model and viewing variable value .所以我想这里发生的事情是:推理步骤使用您手动创建的未训练变量 W 而不是您通过 saved_model.loader 加载的预训练变量,这是为什么你会看到低准确度。

所以,我的猜测是,如果您省略 x、W、b 和 y_ 的定义在开始并从恢复的图中检索它们,例如通过调用 tf.get_default_graph().get_tensor_by_name('variable_name')) 它应该可以正常工作。

PS:如果您正在恢复模型,则无需运行初始化程序(即使我认为它也不会造成任何伤害)。

PPS:在您的脚本中,您正在“手动”计算准确度,但我假设该操作已经存在于模型中,因为它很可能在训练期间也需要,不是吗?因此,您无需再次手动计算准确度,只需从图中获取相应的节点并使用它即可。