“ InvalidArgumentError:您必须为占位符张量输入一个值...”的简单演示

时间:2018-09-26 09:28:56

标签: tensorflow keras

所以,我遇到了一个臭名昭著的错误(使用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)调用来访问共享模型(已使用两次的层/子模型)的中间层的激活,但是找不到解决方案从人们对错误的大量相关经验中进行工作。

  • 背景(和最终目标): 实际项目将两个图像馈入一个网络,共享一个卷积子网,并关联其密集的编码输出。我的目标是检查和可视化卷积滤波器的激活,以查看每个图像的处理方式并改进模型(当然,不是下面的最小示例)。不幸的是,我似乎找不到一种向主模型输入两个输入图像并访问子模型中间层的特定实例的激活的方法。就是子模型的conv2d层只有一个输出,那么如何根据主网络中子模型的第一次或第二次使用来访问子模型的中间激活?

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

以下是演示此问题的完整的最小脚本:

#!/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"]()]]

1 个答案:

答案 0 :(得分:0)

为什么不将额外的输出添加到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)