串联错误:添加的图层必须是类Layer的实例

时间:2018-08-30 11:21:06

标签: python tensorflow keras lstm sequential

我正在Keras的一个片段中工作,在这里我有两个顺序模型,需要将它们合并到第三个模型中,这是我的最终模型。该代码段是使用Keras版本构建的,允许使用Merge方法,因此现在我尝试用axis = 0的连接方法替换它,因此其行为与Merge()相同。尽管进行了所有这些修改,但我仍收到以下堆栈跟踪作为输出:

Traceback (most recent call last):
  File ".\CaptionGenerator.py", line 738, in <module>
    caption.BeamPredictor('image.PNG')
  File ".\CaptionGenerator.py", line 485, in BeamPredictor
    self.SetNeuralNetworksWithoutApi()
  File ".\CaptionGenerator.py", line 433, in SetNeuralNetworksWithoutApi
    Activation('softmax')
  File "D:\Anaconda\lib\site-packages\keras\engine\sequential.py", line 92, in __init__
    self.add(layer)
  File "D:\Anaconda\lib\site-packages\keras\engine\sequential.py", line 131, in add
    'Found: ' + str(layer))
TypeError: The added layer must be an instance of class Layer. Found: Tensor("concatenate_1/concat:0", shape=(?, 40, 300), dtype=float32)

代码段代码为:

def SetNeuralNetworksWithoutApi(self):

    embedding_size = 300

    image_model = Sequential([
    Dense(embedding_size, input_shape=(2048,), activation='relu'),
    RepeatVector(self.MaxCaptionLength)
    ])

    caption_model = Sequential([
    Embedding(self.numberOfWords, embedding_size, input_length=self.MaxCaptionLength),
    LSTM(256, return_sequences=True),
    TimeDistributed(Dense(300))
    ])

    image_in = Input(shape=(2048,))
    caption_in = Input(shape=(self.numberOfWords,))
    merged = concatenate([image_model(image_in), caption_model(caption_in)])
    latent = Bidirectional(LSTM(256, return_sequences=False))(merged)
    out = Dense(self.numberOfWords, activation='softmax')(latent)
    self.softmaxModel = Model([image_in, caption_in], out)

    self.softmaxModel.compile(loss='categorical_crossentropy', optimizer=RMSprop(), metrics=['accuracy'])
    self.softmaxModel.summary()

我不明白为什么我的concatenate()结果不应该是Layer类的实例的原因,考虑到从函数返回的对象中没有layer属性,根据文档,该对象是张量。有什么方法可以解决这个问题而无需切换到API?谢谢。

1 个答案:

答案 0 :(得分:1)

至少对于最终模型,您需要切换到functional API,因为Sequential被设计为具有单个输入,您将向其中强制输入2个张量。不上班。这是因为Sequential为其输入创建了一个占位符。类似于:

image_model = Sequential([
Dense(embedding_size, input_shape=(2048,), activation='relu'),
RepeatVector(self.MaxCaptionLength)
])

caption_model = Sequential([
Embedding(self.numberOfWords, embedding_size, input_length=self.MaxCaptionLength),
LSTM(256, return_sequences=True),
TimeDistributed(Dense(300))
])

image_in = Input(shape=(2048,))
caption_in = Input(shape=(MaxCaptionLength, numberOfWords))
merged = concatenate([image_model(image_in), caption_model(caption_in)], axis=0)
latent = Bidirectional(LSTM(256, return_sequences=False))(merged)
out = Dense(self.numberOfWords, activation='softmax')(latent)
final_model = Model([image_in, caption_in], out)

final_model.compile(loss='categorical_crossentropy', optimizer=RMSprop(), metrics=['accuracy'])
final_model.summary()

您仍然可以将图像模型和标题模型保持分开,但是即使有一种解决方法可以将Sequential与2个输入连接起来,我也不建议这样做,因为这不是该API的预期用途。