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