首页 > 解决方案 > “InvalidArgumentError: You must feed a value for placeholder tensor ...”的简单演示

问题描述

所以,我遇到了臭名昭著的错误(使用 Keras 和 Tensorflow 作为后端):

tensorflow.python.framework.errors_impl.InvalidArgumentError: You must feed a value for placeholder tensor 'conv_in' with dtype float and shape [?,4,4,1]
         [[Node: conv_in = Placeholder[dtype=DT_FLOAT, shape=[?,4,4,1], _device="/job:localhost/replica:0/task:0/device:GPU:0"]()]]
         [[Node: conv2d_1/BiasAdd/_47 = _Recv[client_terminated=false, recv_device="/job:localhost/replica:0/task:0/device:CPU:0", send_device="/job:localhost/replica:0/task:0/device:GPU:0", send_device_incarnation=1, tensor_name="edge_19_conv2d_1/BiasAdd", tensor_type=DT_FLOAT, _device="/job:localhost/replica:0/task:0/device:CPU:0"]()]]

我正在尝试使用 Keras 后端(tensorflow)调用来访问共享模型的中间层(使用两次的层/子模型)的激活,但找不到让它工作的解决方案人们对错误的许多相关经验。

无论如何,由于错误,我似乎根本无法访问激活,因此要解决的第一个问题......

这是一个演示该问题的完整最小脚本:

#!/usr/bin/env python3
from keras.models import Model
from keras.layers import Dense, Reshape, Flatten, Conv2D, MaxPooling2D, \
                         Input, Activation, Dropout, AveragePooling2D
from keras.layers.merge import concatenate
from keras.optimizers import Adam, SGD
import keras
from keras import backend as K
import numpy as np
import ipdb as pdb

def mod_pairs(indim=(None,None), channels=None, lrate=0.01):
    x1 = inp1 = Input(shape=(indim[0], indim[1], channels), name='in1')
    x2 = inp2 = Input(shape=(indim[0], indim[1], channels), name='in2')
    feat = mod_conv(indim=(indim[0], indim[1]), channels=channels)
    x1 = feat(x1)
    x2 = feat(x2)
    x = concatenate([x1,x2], axis=1, name='paired')
    x = Dense(128, name='d_postjoin_1')(x)
    y1 = Dense(1, name='densey1')(x)
    y2 = Dense(1, name='densey2')(x)
    model = Model(inputs=[inp1, inp2], outputs=[y1, y2])
    adam=Adam(lr=lrate, beta_1=0.9, beta_2=0.999, epsilon=1e-08)
    model.compile(loss='mae', optimizer=adam)
    # print(model.summary())
    return model

def mod_conv(indim=(None,None), channels=None):
    x=inputs=Input(shape=(indim[0], indim[1], channels), name="conv_in")
    x = Conv2D(1, (2,2))(x)
    x = Flatten()(x)
    x = Dense(5)(x)
    feats = x
    model = Model(inputs=[inputs], outputs=[feats])
    # print("Sub-Model: ConvNet")
    # print(model.summary())
    return model

def main():
    dim=4; ch=1
    mod = mod_pairs(indim=(dim,dim), channels=ch)
    inx1 = np.random.rand(1, dim, dim, ch)
    inx2 = np.random.rand(1, dim, dim, ch)
    y = mod.predict([inx1, inx2])
    print(y)
    cnn = mod.layers[2] # [2] is the mod_conv Model layer
    # print(cnn)  # <keras.engine.training.Model object ...>
    out = mod.layers[2].layers[1]
    # print(out)  # <keras.layers.convolutional.Conv2D object ...>

    # mod.layers[2].layers[1].get_output_at(1)
    # The above results in:
    #  *** ValueError: Asked to get output at node 1, but the layer has only 1 inbound nodes.

    fun = K.function(
        [mod.input[0], mod.input[1], K.learning_phase()],
        [mod.layers[2].layers[1].output])
    #pdb.set_trace()
    # It's about to fail...
    print(fun([inx1, inx2, 0.0]))
    # Errors here ^^^
    # Attempt assuming graph prunes itself without all outputs
    # fails with same error:
    # fun = K.function(
    #   [mod.inputs[0], mod.inputs[1], K.learning_phase()],
    #   [mod.layers[2].layers[1].output] + mod.output)
    # print(fun([inx1, inx2, 0.0]))

main()

# Error output:
#
# Traceback (most recent call last):
#   File "./sharedsubnet.py", line 68, in <module>
#     main()
#   File "./sharedsubnet.py", line 55, in main
#     print(fun([inx1, inx2, 0.0]))
#   File "path.../keras/backend/tensorflow_backend.py", line 2666, in __call__
#     return self._call(inputs)
#   File "path.../keras/backend/tensorflow_backend.py", line 2636, in _call
#     fetched = self._callable_fn(*array_vals)
#   File "path.../tensorflow/python/client/session.py", line 1382, in __call__
#     run_metadata_ptr)
#   File "path.../tensorflow/python/framework/errors_impl.py", line 519, in __exit__
#     c_api.TF_GetCode(self.status.status))
# tensorflow.python.framework.errors_impl.InvalidArgumentError: You must feed a value for placeholder tensor 'conv_in' with dtype float and shape [?,4,4,1]
#          [[Node: conv_in = Placeholder[dtype=DT_FLOAT, shape=[?,4,4,1], _device="/job:localhost/replica:0/task:0/device:GPU:0"]()]]

标签: tensorflowkeras

解决方案


为什么不向您的 mod_conv() 模型添加一个额外的输出,那么您将更容易访问您的特定激活。

def mod_conv(indim=(None,None), channels=None):
    x=inputs=Input(shape=(indim[0], indim[1], channels), name="conv_in")
    xconv = Conv2D(1, (2,2))(x)
    x = Flatten()(xconv)
    x = Dense(5)(x)
    feats = x
    model = Model(inputs=[inputs], outputs=[feats,xconv])
    # print("Sub-Model: ConvNet")
    # print(model.summary())
    return model

现在您的 cnn 模型有两个输出,希望您可以在您的 K.function() 中使用它们(对不起,我不明白那部分)

cnn.get_output_at(0)
cnn.get_output_at(1)

推荐阅读