如何使不同的输入适合不同的模型?

时间:2019-01-02 17:04:05

标签: python-3.x keras

我有2个numpy图片阵列,它们的形状相同但内容不同:
array1和array2。以下是两个不同的功能:

def c_model(input_shape, name):

    c_conv1a = Conv2D(64, kernel_size=(7, 7), activation='relu')(input_shape)
    c_conv1a = BatchNormalization(axis=-1)(c_conv1a)
    c_conv1a = MaxPooling2D(pool_size=(2, 2))(c_conv1a)

    flatten = Flatten()(c_conv1a)

    fc = Dense(128, activation='relu')(flatten)
    fc = Dropout(0.3)(fc)
    fc = Dense(256, activation='relu')(fc)
    fc = Dropout(0.3)(fc)
    c_fc = Dense(1, activation='sigmoid', name=name)(fc)

    return c_fc


def g_model(input_shape, name):

    g_conv1a = Conv2D(64, kernel_size=(5, 5), activation='relu')(input_shape)
    g_conv1a = BatchNormalization(axis=-1)(g_conv1a)
    g_conv1a = MaxPooling2D(pool_size=(2, 2))(g_conv1a)

    flatten = Flatten()(g_conv1a)

    fc = Dense(128, activation='relu')(flatten)
    fc = Dropout(0.3)(fc)
    fc = Dense(256, activation='relu')(fc)
    fc = Dropout(0.3)(fc)
    g_fc = Dense(1, activation='sigmoid', name=name)(fc)

    return g_fc

在以下几行之后:

shape1 = Input(shape=(64,64,3))  
shape2 = Input(shape=(64,64,3))
cmodel = c_model(shape1, "c")
gmodel = g_model(shape2, "g")
m = Model(inputs=[shape1, shape2], outputs=[cmodel, gmodel])
m.compile(...)
m.fit(x=[array1, array2], y=[output1, output2])

我如何确保将array1装入cmodel中,将array2装入gmodel中?

3 个答案:

答案 0 :(得分:1)

您的计算图已经确定是这种情况:您将2个不相交的模型cg绑定到具有2个输入和2个输出的外部模型。 array1会影响output1的唯一方法是通过c模型,而array2则类似;因此,在训练时,相对于输出的渐变只会更新相应的模型。

您拥有的等同于:

shape1 = Input(shape=(64,64,3))  
shape2 = Input(shape=(64,64,3))
cmodel_out = c_model(shape1, "c")
gmodel_out = g_model(shape2, "g")
cmodel = Model(shape1, cmodel_out)
gmodel = Model(shape2, gmodel_out)
# ... compile models
cmodel.fit(array1, output1)
gmodel.fit(array2, output2)

就计算图而言。

答案 1 :(得分:1)

它将按照您定义的顺序。您定义了[shape1, shape2],顺序就是这个。

您通过了[array1, array2],这就是命令。

您定义了[cmodel, gmodel],这就是订单。您以相同的顺序通过了[output1, output2]

答案 2 :(得分:0)

如果我正确理解您的问题,那么您所做的方式已经可以保证您想要的。如其他答案中所述,列表元素的顺序决定了哪个输入numpy数组将被馈送到哪个输入层,哪个输出层将与哪个输出numpy数组进行比较。

如果您在模型构造函数中添加第三个输入,例如m = Model(inputs=[shape1, shape2, shape3], ...),您还需要第三个输入numpy数组:m.fit(x=[array1, array2, array3], ...),否则会出现错误。

如果您在模型构造函数中添加第三个输出,例如m = Model(outputs=[cmodel, gmodel, amodel], ...),您还需要第三个输出numpy数组:m.fit(y=[output1, output2, output3], ...),否则会出现错误。

请注意,出于技术原因,输入和输出层数相同。只有为inputsx传递的两个列表以及为outputsy传递的两个列表的大小必须相同。

如果出于某种原因,您不想依靠此“按列表项位置进行匹配”,则可以选择将字典传递到m.fit来将输入和输出层的名称映射到输入和输出numpy数组:

shape1 = Input(shape=(64,64,3), name="input1")  
shape2 = Input(shape=(64,64,3), name="input2")
cmodel = c_model(shape1, "c")
gmodel = g_model(shape2, "g")
m = Model(inputs=[shape1, shape2], outputs=[cmodel, gmodel])
m.compile(...)
m.fit(x={"input2": array2, "input1": array1}, y={"c": output1, "g": output2})

一些注意事项:我建议使用不同的名称命名变量。您的变量shape1shape2没有形状。它们是输入层(碰巧具有某种形状),因此我宁愿称它们为input1input2input_layer1input_layer2 。 同样,变量cmodelgmodel都不是模型。它们是模型的输出层。相反,m是您的模型。

正如在另一个答案中已经提到的那样,您的两个“模型”是完全隔离的,因此我看不出将它们组合成一个模型的理由(当然,除非您没有进一步说明某些联系)让问题简短)。

我还建议您看看Keras docs regarding multi-input and multi-output models