You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

TensorFlow复杂模型恢复中Placeholder的feed_dict传递问题排查

解决TensorFlow恢复模型时feed_dict传递失败的问题

咱们来一步步拆解你遇到的两个错误,然后给出正确的处理方式:

为什么两种方法都会报错?

方法1的错误原因

你用tf.get_default_graph().get_operations()拿到的是Operation对象(比如Placeholder这个操作本身),但feed_dict需要的是这个操作产生的Tensor对象(也就是Placeholder的输出张量)。把Operation直接传给feed_dict,TensorFlow自然无法识别,所以会抛出TypeError: Cannot interpret feed_dict key as Tensor

方法2的错误原因

你重新定义了同名的Placeholder,但此时计算图里存在两个完全独立的同名节点:一个是从元图里导入的原始Placeholder,另一个是你新定义的。当你运行session.run('fin_m:0')时,这个输出张量依赖的是导入的原始Placeholder,但你在feed_dict里传递的是新定义的那个,导致原始Placeholder始终没有被喂值,所以会报错InvalidArgumentError: You must feed a value for placeholder tensor 'cnn_in'

正确的处理方式

核心原则是:从导入的元图中直接获取已有的Placeholder张量,不要重新定义,也不要用Operation对象代替Tensor

方案1:通过张量名称获取(最常用)

导入元图后,使用get_tensor_by_name()方法,通过"占位符名称:0"的格式获取对应的张量(:0表示该节点的第一个输出张量,Placeholder只有一个输出):

input_dir = "parallel_win_10_40_conv_3l_rnn"
input_file = "parallel_win_10_40_conv_3l_rnn"
# 导入元图
saver = tf.train.import_meta_graph("./result/cnn_rnn_parallel/tune_rnn_layer/"+input_dir+"/model_"+input_file+".meta")

# 从导入的图中获取已有的Placeholder张量
graph = tf.get_default_graph()
cnn_in = graph.get_tensor_by_name('cnn_in:0')
rnn_in = graph.get_tensor_by_name('rnn_in:0')
Y = graph.get_tensor_by_name('Y:0')
keep_prob = graph.get_tensor_by_name('keep_prob:0')
phase_train = graph.get_tensor_by_name('phase_train:0')

with tf.Session() as session:
    saver.restore(session, "./result/cnn_rnn_parallel/tune_rnn_layer/"+input_dir+"/model_"+input_file)
    # 准备测试数据(你的原有代码不变)
    test_cnn_batch = np.zeros(shape=[accuracy_batch_size], dtype=float)
    test_rnn_batch = np.zeros(shape=[accuracy_batch_size], dtype=float)
    offset = (accuracy_batch_size) % (test_y.shape[0] - accuracy_batch_size)
    test_cnn_batch = cnn_test_x[offset:(offset + accuracy_batch_size), :, :, :, :]
    test_cnn_batch = test_cnn_batch.reshape(len(test_cnn_batch) * window_size, input_height, input_width, 1)
    test_rnn_batch = rnn_test_x[offset:(offset + accuracy_batch_size), :, :]
    test_batch_y = test_y[offset:(offset + accuracy_batch_size), :]
    # 用获取到的张量作为feed_dict的key
    print(session.run('fin_m:0', feed_dict={cnn_in: test_cnn_batch, rnn_in: test_rnn_batch, Y: test_batch_y, keep_prob: 1.0, phase_train: False}))

方案2:导入元图时直接指定返回元素(更简洁)

使用tf.train.import_meta_graph()return_elements参数,一次性获取你需要的所有张量,省去手动查找的步骤:

input_dir = "parallel_win_10_40_conv_3l_rnn"
input_file = "parallel_win_10_40_conv_3l_rnn"
# 导入元图并直接获取需要的张量
saver, [cnn_in, rnn_in, Y, keep_prob, phase_train, fin_m] = tf.train.import_meta_graph(
    "./result/cnn_rnn_parallel/tune_rnn_layer/"+input_dir+"/model_"+input_file+".meta",
    return_elements=['cnn_in:0', 'rnn_in:0', 'Y:0', 'keep_prob:0', 'phase_train:0', 'fin_m:0']
)

with tf.Session() as session:
    saver.restore(session, "./result/cnn_rnn_parallel/tune_rnn_layer/"+input_dir+"/model_"+input_file)
    # 准备测试数据(你的原有代码不变)
    test_cnn_batch = np.zeros(shape=[accuracy_batch_size], dtype=float)
    test_rnn_batch = np.zeros(shape=[accuracy_batch_size], dtype=float)
    offset = (accuracy_batch_size) % (test_y.shape[0] - accuracy_batch_size)
    test_cnn_batch = cnn_test_x[offset:(offset + accuracy_batch_size), :, :, :, :]
    test_cnn_batch = test_cnn_batch.reshape(len(test_cnn_batch) * window_size, input_height, input_width, 1)
    test_rnn_batch = rnn_test_x[offset:(offset + accuracy_batch_size), :, :]
    test_batch_y = test_y[offset:(offset + accuracy_batch_size), :]
    # 直接使用获取到的fin_m张量
    print(session.run(fin_m, feed_dict={cnn_in: test_cnn_batch, rnn_in: test_rnn_batch, Y: test_batch_y, keep_prob: 1.0, phase_train: False}))

关键总结

  1. 恢复模型时,不要重新定义Placeholder,必须复用元图中已有的节点。
  2. feed_dict的key必须是Tensor对象,不能是Operation对象。
  3. 张量的名称格式为节点名称:0(Placeholder节点只有一个输出张量,所以后缀固定为:0)。

内容的提问来源于stack exchange,提问作者freerdan

火山引擎 最新活动