首页 > 解决方案 > 具有不同通道数的多个输入的 Keras 模型

问题描述

我正在尝试使用 Keras 制作卷积神经网络。我想要两个采用不同输入但共享相同架构和权重的模型 - 所需的架构如下所示。我将如何使用 Keras 定义这样的模型?

分类器 1 只接受输入 a,而分类器 2 接受 a 和 b 输入。 所以它们可以连接起来以增加深度

我尝试按如下方式实现:

from keras.layers import Input,Conv2D,Activation,Flatten,Concatenate, MaxPooling2D, Dense
from keras.models import Model

def combined_model():

    a = Input(shape=(100,100,None))   ## should not change this
    fe = Conv2D(3, (1,1), strides=(2,2), padding='same', kernel_initializer=initl)(a) 
    fe = MaxPooling2D()(fe)
    fe = Flatten()(fe)
    fe = Dense(3)(fe)
    class1 = Activation('sigmoid')(fe)
    c_model = Model(a, class1, name = "c_model")
    c_model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    fe = Dense(1)(fe)
    class2 = Activation('sigmoid')(fe)
    d_model = Model(a, class2, name = "d_model")
    d_model.compile(loss= 'binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    return c_model, d_model

c,d = combined_model()

但是,它会导致错误:

ValueError: The channel dimension of the inputs should be defined. Found `None`

标签: pythonkeras

解决方案


简单的答案: 只需如下定义输入形状并明确设置通道形状:

a = Input(shape=(100, 100, 3))

如果您想拥有多个输入(具有不同的通道形状),那么您可以简单地创建多个输入:

a = Input(shape=(100, 100, 3))
b = Input(shape=(100, 100, 3)) # or Input(shape=(100, 100, 1))

同样在您的示例中,您错误地将一个密集层的输出连接到另一个。但是根据提供的模型架构图,您希望将 flatten 层的输出连接到每个密集层(您可以在下面查看实现细节)。

执行:

在下面的代码中,我正确设置了输入形状,并且我将 flatten 层的输出传递给了每个密集(3 和 1)层(你错误地将一个密集层的输出传递给了另一个)。

重要提示:您希望将两个输入图像传递给“分类器 2”但是您不能将两个图像直接传递给 CNN 层,而是可以为每个输入使用单独的 CNN,然后将它们的结果连接起来,如下面的代码所示:

from keras.layers import Input,Conv2D,Activation,Flatten,Concatenate, MaxPooling2D, Dense, concatenate
from keras.models import Model

def combined_model():
    a = Input(shape=(100, 100, 3))
    b = Input(shape=(100, 100, 3))
    fe = Conv2D(3, (1,1), strides=(2,2), padding='same', kernel_initializer=initl)(a) 
    fe = MaxPooling2D()(fe)
    flattened1 = Flatten()(fe)

    fe = Conv2D(3, (1,1), strides=(2,2), padding='same')(b) 
    fe = MaxPooling2D()(fe)
    flattened2 = Flatten()(fe)

    fe = Dense(3)(flattened1)
    class1 = Activation('sigmoid')(fe)
    c_model = Model(a, class1, name = "c_model")
    c_model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

    fe = Dense(1)(concatenate([flattened1, flattened2]))
    class2 = Activation('sigmoid')(fe)
    d_model = Model([a, b], class2, name = "d_model")
    d_model.compile(loss= 'binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    return c_model, d_model

c,d = combined_model()
from keras.utils import plot_model
plot_model(c, 'c.png')
plot_model(d, 'd.png')

模型架构(我一起展示了两个模型,因为它们具有共享层): 在此处输入图像描述


推荐阅读