m_margegaj
m_margegaj

Reputation: 23

how to fit different inputs into different models?

I have 2 numpy arrays of images with same shape but different content:
array1 and array2. The following are two different functions:

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

After the following lines:

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])

how do i make sure that array1 is being fited in cmodel and array2 in gmodel?

Upvotes: 1

Views: 109

Answers (3)

sebrockm
sebrockm

Reputation: 6002

If I understand your question correctly, the way you are doing it already guarantees what you want. As already stated in the other answers, the order of the list elements determines which input numpy array will be fed into which input layer and which output layer will be compared against which output numpy array.

If you add a third input in the model constructor, e.g. m = Model(inputs=[shape1, shape2, shape3], ...), you will also need a third input numpy array: m.fit(x=[array1, array2, array3], ...), otherwise you will get an error.

If you add a third output in the model constructor, e.g. m = Model(outputs=[cmodel, gmodel, amodel], ...), you will also need a third output numpy array: m.fit(y=[output1, output2, output3], ...), otherwise you will get an error.

Note that there is no technical reason to have the same number of input and output layers. Only the two lists passed for inputs and x and the two lists passed for outputs and y must have the same size.

If, for whatever reason, you don't want to rely on this "matching by list item position", you have the alternative of passing dictionaries to m.fit that map the names of the input and output layers to the input and output numpy arrays:

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})

A few side notes: I recommend to name your variables differently. Your variables shape1 and shape2 are no shapes. They are input layers (that happen to have a certain shape), so I would rather call them input1 and input2 or input_layer1 and input_layer2. Similarly, your variables cmodel and gmodel are no models. They are output layers of a model. Instead, m is your model.

As already mentioned in another answer, your two "models" are completely isolated, so I don't see a reason to combine them into one model (unless, of course, there is some connection that you didn't further explain to keep the question short).

I also recommend to have a look at the Keras docs regarding multi-input and multi-output models.

Upvotes: 0

Daniel Möller
Daniel Möller

Reputation: 86600

It will be in the same order you defined. You defined [shape1, shape2], the order will be this one.

You passed [array1, array2], this will be the order.

You defined [cmodel, gmodel] this is the order. You passed [output1, output2] following the same order.

Upvotes: 1

nuric
nuric

Reputation: 11225

Your computation graph already ensures that is the case: you have 2 disjoint models c and g bound to an outer model with 2 inputs and 2 outputs. The only way array1 can affect output1 is through c model and similar for array2; therefore when you train, gradients with respect to outputs will only update the corresponding the model.

What you have is equivalent to:

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)

as far as the computation graph is concerned.

Upvotes: 1

Related Questions