如何将前置模型数据适配到最后一个模型?代码fit报错求助
问题:仅训练串联结构中最后一个模型时fit方法报错
我正在构建包含约40个模型的复杂链式结构,当前最后一个模型的fit方法无法运行。需求是仅训练最后一个模型cModel,它接收前置a、b模型的输出及额外输入s_in,生成3维输出匹配c_out,后续要构建数十个此类实例链式串联。
原代码
#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)
模型摘要
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)
错误信息
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>]
解决方案
错误原因
- cModel输入定义错误:原代码中
cModel = keras.Model(inputs=combine, outputs=cModel, name="c")将拼接后的张量combine作为输入,导致模型只期望接收1个3维张量,但fit时传入了3个不同形状的输入。 - 未固定前置模型权重:若要仅训练cModel,需将aModel和bModel设置为不可训练,避免其权重被更新。
修改后的代码
import numpy as np import tensorflow as tf from tensorflow import keras #Input a_in=np.array([[3,4,5],[2,3,4],[1,2,3],[4,6,8]], dtype=np.float64) b_in=np.array([[9,5,3],[1,0,2],[7,3,1],[6,6,6]], dtype=np.float64) s_in = np.array([[5],[7],[9],[0]], dtype=np.float64) #Output c_out = np.array([[6,2,3],[0,2,7],[9,6,1],[8,6,5]], dtype=np.float64) # 定义并构建a模型 a = keras.Input(shape=(3,), dtype=tf.float64) a_x = keras.layers.Dense(10, activation='sigmoid')(a) a_x = keras.layers.Dense(1, activation='sigmoid')(a_x) aModel = keras.Model(inputs=a, outputs=a_x, name="a") # 固定a模型权重,不可训练 aModel.trainable = False # 定义并构建b模型 b = keras.Input(shape=(3,), dtype=tf.float64) b_x = keras.layers.Dense(10, activation='sigmoid')(b) b_x = keras.layers.Dense(1, activation='sigmoid')(b_x) bModel = keras.Model(inputs=b, outputs=b_x, name="b") # 固定b模型权重,不可训练 bModel.trainable = False # 定义额外输入s s = keras.Input(shape=(1,), dtype=tf.float64) # 获取a、b模型的输出,拼接s输入 a_out = aModel(a) b_out = bModel(b) combine = keras.layers.concatenate([a_out, b_out, s], dtype=tf.float64) # 构建c模型,输入为a、b、s的原始输入,输出为最终预测 c_x = keras.layers.Dense(10, activation='sigmoid')(combine) c_x = keras.layers.Dense(3, activation='sigmoid')(c_x) cModel = keras.Model(inputs=[a, b, s], outputs=c_x, name="c") # 编译c模型 cModel.compile(optimizer='adam', loss='mean_absolute_error', metrics=['accuracy']) # 查看模型结构 aModel.summary() bModel.summary() cModel.summary() # 训练c模型,传入三个输入 cModel.fit([a_in, b_in, s_in], c_out, epochs=1, shuffle=False, verbose=1)
关键修改点说明
- 固定前置模型权重:通过
aModel.trainable = False和bModel.trainable = False锁定a、b模型的参数,训练时仅更新cModel的权重。 - 正确定义cModel输入:将cModel的输入设置为
[a, b, s](三个原始输入张量),而非拼接后的combine,这样fit时传入[a_in, b_in, s_in]就能匹配模型输入要求。 - 统一数据类型:确保输入数据的 dtype 与模型输入定义的
tf.float64一致,避免类型不匹配问题。
内容的提问来源于stack exchange,提问作者Majoris
相关产品推荐
相关产品推荐

