如何在keras中结合两个预训练模型?

时间:2019-10-23 00:30:30

标签: keras deep-learning computer-vision

我想结合两个预先训练的模型(DenseNet169和InceptionV3),也可以是两个模型。遵循了以下链接中的步骤,但是没有用。尝试同时连接和同时连接,仍然会出错。我可能在某个地方犯了一些错误。这是我的第一个stackoverflow问题,将不胜感激。 https://datascience.stackexchange.com/questions/39407/how-to-make-two-parallel-convolutional-neural-networks-in-keras 第一种情况:我尝试不合并

model1 = DenseNet169(weights='imagenet', include_top=False, input_shape=(300,300,3))
out1 = model1.output    

model2 = InceptionV3(weights='imagenet', include_top=False, input_shape=(300,300,3))
out2 = model2.output

from keras.layers import concatenate 
from keras.layers import Concatenate 

x = concatenate([out1, out2])  # merge the outputs of the two   models
out = Dense(10, activation='softmax')(x)  # final layer of the network

我收到此错误:

ValueError:Concatenate层需要输入(除了concat轴以外)具有匹配的形状。得到了输入形状:[(无,9,9,1664),(无,8,8,2048)]

第二种情况:尝试使用平均池,可以串联但在训练过程中出错

model1 = DenseNet169(weights='imagenet', include_top=False, pooling='avg', input_shape=(300,300,3))
out1 = model1.output   

model2 = InceptionV3(weights='imagenet', include_top=False, pooling='avg', input_shape=(300,300,3))
out2 = model2.output

x = concatenate([out1, out2])  # merge the outputs of the two models
out = Dense(10, activation='softmax')(x)  # final layer of the network

model = Model(inputs=[model1.input, model2.input], outputs=[out])

model.compile(optimizer=Adam(), loss='categorical_crossentropy',metrics=['accuracy'])
history = model.fit_generator(generator=data_generator_train,
                          validation_data=data_generator_val,
                          epochs=20,
                          verbose=1
                         )

第二种情况下的错误: ValueError:检查模型输入时出错:传递给模型的Numpy数组列表不是模型期望的大小。预计会看到2个数组,但获得了以下1个数组的列表:[array([[[[0.17074525,0.10469133,0.08226486]          [0.19852941、0.13124999、0.11642157],          [0.36528033、0.3213197、0.3085095],          ...,          [0.19082414、0.17801011、0.15840226 ...

2 个答案:

答案 0 :(得分:0)

第二种情况::由于您的模型需要两个输入,因此您的data_generator_traindata_generator_val应该为对应的模型和输出返回/产生两个输入的列表。您可以通过更新__data_generation方法

的返回值来实现
def __data_generation(...):
    ...
    # consider X as input image and y as the label of your model
    return [X, X], keras.utils.to_categorical(y, num_classes=self.n_classes)

第一种情况::由于model2 (8x8)输出的空间大小与model1输出(9x9)不同(较小),因此您可以先对model2输出应用零填充串联。

out1 = model1.output
out2 = model2.output
out2 = ZeroPadding2D(((0,1), (0,1)))(out2)
x = concatenate([out1, out2])

对于第一种情况,您也需要像第二种情况一样修改数据生成器。

答案 1 :(得分:0)

第二个案例结构为True,但是请考虑将两个模型连接起来,并且如果两个模型的输入相似,则每个模型都有自己的输入,只需通过重复输入即可使模型适合:

model.fit([X_train,X_train], y_train)

我本人可以解决您的问题,并且效果很好。

model1 = DenseNet169(weights='imagenet', include_top=False)
model2 = InceptionV3(weights='imagenet', include_top=False)

model1_out = model1.output
model1_out=GlobalAveragePooling2D()(model1_out)

model2_out = model2.output
model2_out=GlobalAveragePooling2D()(model2_out)

x = concatenate([model1_out, model2_out])

x = Dense(10, activation='softmax')(x) 

model=Model(inputs=[model1.input,model2.input],outputs=x)

model.fit([X_train,X_train], y_train)