Search code examples
pythontensorflowmachine-learningkeras

How do we fit previous models' data into the last model?


How do we fit previous models' data into the last model? The last fit in this code isn't working. I am trying to build a fairly complicated model, about 40 models. How do I fit data only to the last model that feeds to all previous models? I start with a_in b_in processed together, and add another single input s_in to create final output of 3; to be matched with c_out. I need to produce 40 something instances like this, and keep them chaining them.

#Input
a_in=np.array([[3,4,5],[2,3,4],[1,2,3],[4,6,8]])
b_in=np.array([[9,5,3],[1,0,2],[7,3,1],[6,6,6]])
s_in = np.array([[5],[7],[9],[0]])

#Output
c_out = np.array([[6,2,3],[0,2,7],[9,6,1],[8,6,5]])

a = keras.Input(shape=(3,), dtype=tf.float64)
aModel = keras.layers.Flatten()(a)

b = keras.Input(shape=(3,), dtype=tf.float64)
bModel = keras.layers.Flatten()(b)

s = keras.Input(shape=(1,), dtype=tf.float64)

aModel = keras.layers.Dense(10, activation='sigmoid')(a)
aModel = keras.layers.Dense(1, activation='sigmoid')(aModel)
aModel = keras.Model(inputs=a, outputs=aModel, name="a")

bModel = keras.layers.Dense(10, activation='sigmoid')(b)
bModel = keras.layers.Dense(1, activation='sigmoid')(bModel)
bModel = keras.Model(inputs=b, outputs=bModel, name="b")

combine = keras.layers.concatenate([aModel.output, bModel.output, s], dtype=tf.float64) #inject s in the middle stage

cModel = keras.layers.Dense(10, activation='sigmoid')(combine)
cModel = keras.layers.Dense(3, activation='sigmoid')(cModel)
cModel = keras.Model(inputs=combine, outputs=cModel, name="c")

cModel.compile(optimizer='adam', loss='mean_absolute_error', metrics='accuracy')

aModel.summary()
bModel.summary()
cModel.summary()

keras.utils.plot_model(cModel, "baby-architecture.png", show_shapes=True)


cModel.fit([a_in, b_in, s_in],[c_out],epochs=1, shuffle=False, verbose=1)

Summary:

Model: "a"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_1 (InputLayer)        [(None, 3)]               0         
                                                                 
 dense (Dense)               (None, 10)                40        
                                                                 
 dense_1 (Dense)             (None, 1)                 11        
                                                                 
=================================================================
Total params: 51 (204.00 Byte)
Trainable params: 51 (204.00 Byte)
Non-trainable params: 0 (0.00 Byte)
_________________________________________________________________
Model: "b"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_2 (InputLayer)        [(None, 3)]               0         
                                                                 
 dense_2 (Dense)             (None, 10)                40        
                                                                 
 dense_3 (Dense)             (None, 1)                 11        
                                                                 
=================================================================
Total params: 51 (204.00 Byte)
Trainable params: 51 (204.00 Byte)
Non-trainable params: 0 (0.00 Byte)
_________________________________________________________________
Model: "c"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_4 (InputLayer)        [(None, 3)]               0         
                                                                 
 dense_4 (Dense)             (None, 10)                40        
                                                                 
 dense_5 (Dense)             (None, 3)                 33        
                                                                 
=================================================================
Total params: 73 (292.00 Byte)
Trainable params: 73 (292.00 Byte)
Non-trainable params: 0 (0.00 Byte)

enter image description here

Error:

ValueError: Layer "c" expects 1 input(s), but it received 3 input tensors. 
    Inputs received: [<tf.Tensor 'IteratorGetNext:0' shape=(None, 3) dtype=int64>, 
    <tf.Tensor 'IteratorGetNext:1' shape=(None, 3) dtype=int64>, 
<tf.Tensor 'IteratorGetNext:2' shape=(None, 1) dtype=int64>]

Solution

  • From what I understand, cModel is the main model that combines the outputs from bModel and aModel, it also has its own input s_in. So, when you are fitting data into cModel, the input layer of cModel will be used to take inputs which will be passed further. If you review cModel's input layer, it expects the output of models aModel and bModel but in your fit function, you are passing the inputs of aModel, bModel and s_in. Based on this, I have modified your code a little bit which now looks like -

    #Input
    a_in=np.array([[3,4,5],[2,3,4],[1,2,3],[4,6,8]])
    b_in=np.array([[9,5,3],[1,0,2],[7,3,1],[6,6,6]])
    s_in = np.array([[5],[7],[9],[0]])
    
    #Output
    c_out = np.array([[6,2,3],[0,2,7],[9,6,1],[8,6,5]])
    
    a = keras.Input(shape=(3,), dtype=tf.float64, name="a")
    b = keras.Input(shape=(3,), dtype=tf.float64, name="b")
    s = keras.Input(shape=(1,), dtype=tf.float64, name="s")
    
    aModel = keras.layers.Flatten()(a)
    aModel = keras.layers.Dense(10, activation='sigmoid')(aModel)
    aModel = keras.layers.Dense(1, activation='sigmoid')(aModel)
    aModel = keras.Model(inputs=a, outputs=aModel)
    
    bModel = keras.layers.Flatten()(b)
    bModel = keras.layers.Dense(10, activation='sigmoid')(bModel)
    bModel = keras.layers.Dense(1, activation='sigmoid')(bModel)
    bModel = keras.Model(inputs=b, outputs=bModel, name="b")
    
    
    cModel = keras.layers.Concatenate()([aModel.output, bModel.output, s])
    cModel = keras.layers.Dense(10, activation='sigmoid')(cModel)
    cModel = keras.layers.Dense(3, activation='sigmoid')(cModel)
    
    # CHANGES HERE: the inputs to the model.
    cModel = keras.Model(inputs=[a,b,s], outputs=cModel, name="c")
    
    cModel.compile(optimizer='adam', loss='mean_absolute_error', metrics='accuracy')
    
    # aModel.summary()
    # bModel.summary()
    cModel.summary()
    
    keras.utils.plot_model(cModel, "baby-architecture.png", show_shapes=True)
    
    # CHANGES HERE: Your c_out is a numpy ndarry, which does not require any other typecasting.
    cModel.fit({"a": a_in, "b": b_in, "s": s_in}, c_out, epochs=1, shuffle=False, verbose=1)
    

    Your model now looks like this - Model Architecture