【问题标题】:How to combine two pretrained models in keras?如何在 keras 中组合两个预训练模型?
【发布时间】:2019-10-23 00:30:30
【问题描述】:

我想组合两个预训练模型(DenseNet169 和 InceptionV3),也可以是任意两个。按照以下链接中的步骤操作,但没有用。确实尝试了连接和连接,仍然出现错误。我可能在某个地方犯了一些错误。这是我的第一个 stackoverflow 问题,我们将不胜感激。 https://datascience.stackexchange.com/questions/39407/how-to-make-two-parallel-convolutional-neural-networks-in-keras 第一种情况:我尝试使用 NO pooling

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 轴除外。得到输入形状:[(None, 9, 9, 1664), (None, 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...

【问题讨论】:

    标签: keras deep-learning computer-vision


    【解决方案1】:

    第二种情况:由于您的模型需要两个输入,因此您的 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)
    

    第一种情况:由于模型 2 (8x8) 的输出空间大小与模型 1 输出 (9x9) 的空间大小不同(更小),因此您可以在连接之前对模型 2 输出应用零填充。

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

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

    【讨论】:

    • 感谢您的帮助。非常感激。我使用了 stanford.edu/~shervine/blog/… 的类 DataGenerator,仍然不太明白如何修复 'def __data_generation' 部分以到达 [X, X, y]。在训练过程中仍然出现同样的错误。请帮我解决这个问题。
    • __data_generation 方法中尝试使用return [X, X], keras.utils.to_categorical(y, num_classes=self.n_classes)。希望它会有所帮助。
    • 问题现已修复。谢谢,非常感谢。
    【解决方案2】:

    第二种情况结构为真,但考虑您连接两个模型,如果两个模型的输入相似,则每个模型都有自己的输入,只需通过重复输入来拟合模型,如下所示:

    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)
    

    【讨论】:

    • 感谢您的详细解释。非常感激。我试过你的方法。它适用于 fit,但 fit_generator 仍然出现相同的错误。有什么适用于 fit_generator 的吗?
    猜你喜欢
    • 1970-01-01
    • 2021-04-22
    • 2018-09-02
    • 2019-01-20
    • 2017-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多