训练TensorFlow编解码器模型时遇ValueError:输入张量数量不匹配
你训练TensorFlow编解码器模型时,调用model.fit的第一个epoch就触发ValueError,错误信息如下:
Exception has occurred: ValueError
Layer "functional" expects 2 input(s), but it received 1 input tensors. Inputs received: [<tf.Tensor 'data:0' shape=(None, 128) dtype=float32>]
File "D:\workspace\Machine Learning 545\PSU_classes\cs445_group_project\code\Keras Music Genres Classification\encoder_decoder_feature_extractor.py", line 177, in train_encoder_decoder_model
model.fit(x = X_train,
File "D:\workspace\Machine Learning 545\PSU_classes\cs445_group_project\code\Keras Music Genres Classification\encoder_decoder_feature_extractor.py", line 217, in
trained_model = train_encoder_decoder_model(encoder_decoder_model, X_train, y_train, X_test, y_test)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: Layer "functional" expects 2 input(s), but it received 1 input tensors. Inputs received: [<tf.Tensor 'data:0' shape=(None, 128) dtype=float32>]
模型定义代码
def define_encoder_decoder_model(num_features): # Define the encoder encoder_inputs = Input(shape=(None, num_features)) encoder_hidden1 = Dense(100, activation='relu')(encoder_inputs) encoder_hidden2 = Dense(50, activation='relu')(encoder_hidden1) encoder_lstm = LSTM(25, return_state=True) encoder_outputs, state_h, state_c = encoder_lstm(encoder_hidden2) encoder_states = [state_h, state_c] # Define the decoder decoder_inputs = Input(shape=(None, 25)) decoder_hidden1 = Dense(50, activation='relu')(decoder_inputs) decoder_hidden2 = Dense(100, activation='relu')(decoder_hidden1) decoder_lstm = LSTM(num_features, return_sequences=True, return_state=True) decoder_outputs, _, _ = decoder_lstm(decoder_hidden2, initial_state=encoder_states) decoder_dense = Dense(num_features, activation='softmax') decoder_outputs = decoder_dense(decoder_outputs) # Define the model that will turn encoder_inputs and decoder_inputs into decoder_outputs model = Model([encoder_inputs, decoder_inputs], decoder_outputs) # Compile the model model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy', 'precision', 'recall', 'f1_score']) # Summary of the model model.summary() return model
训练调用代码
def train_encoder_decoder_model(model, X_train, y_train, X_test, y_test): """ Trains an encoder-decoder model using the provided data. Args: model: The encoder-decoder model to train. X_train: The input training data. y_train: The target training data. X_test: The input test data. y_test: The target test data. Returns: The trained encoder-decoder model. """ print("shapes: X_train:", np.shape(X_train)," y_train: ", np.shape(y_train)," X_test: ", np.shape(X_test)," y_test: ", np.shape(y_test)) # Train the model # append to a file the training log for each epoch file_logger = FileLogger('training.log') y_train_T = tf.convert_to_tensor(np.array([y_train]).T) y_test_T = tf.convert_to_tensor(np.array([y_test]).T) #x_train = tf.convert_to_tensor(X_train) y_train = X_train y_test = X_test model.fit(x = X_train, y= y_train, batch_size=100, epochs=100, verbose=2, validation_data=(X_test, y_test), callbacks=[file_logger]) return model
补充信息:这是一个编解码器模型,X_train与y_train相同,X_test与y_test相同。训练集形状为(799,128),测试集形状为(299,128),特征为float64类型。
错误原因
- 输入数量不匹配:模型通过
Model([encoder_inputs, decoder_inputs], decoder_outputs)定义,明确要求接收两个输入张量(编码器输入和解码器输入),但调用model.fit时只传入了单个X_train,导致输入数量不符合模型预期。 - 数据维度不匹配:模型中的LSTM层要求输入为三维张量
(样本数, 时间步, 特征数),但当前训练数据是二维数组(799,128),缺少时间步维度,同时解码器输入的shape=(None,25)也未对应到合理的输入数据。
解决步骤
步骤1:调整输入数据维度
为LSTM层补充时间步维度,假设每个样本的时间步为1(若128为特征数),同时构造符合解码器输入形状的张量:
# 调整编码器输入维度:(样本数, 时间步, 特征数) X_train_enc = np.expand_dims(X_train, axis=1) # 形状变为(799, 1, 128) X_test_enc = np.expand_dims(X_test, axis=1) # 形状变为(299, 1, 128) # 构造解码器输入,匹配shape=(None,25),示例用全零张量(可根据任务逻辑替换为合理输入) X_train_dec = np.zeros((X_train.shape[0], 1, 25)) # 形状(799,1,25) X_test_dec = np.zeros((X_test.shape[0], 1, 25)) # 形状(299,1,25) # 调整目标输出维度,匹配解码器输出的三维结构 y_train_target = np.expand_dims(X_train, axis=1) y_test_target = np.expand_dims(X_test, axis=1)
步骤2:修改model.fit的输入参数
将两个输入以列表形式传入x参数,验证数据也同步调整:
def train_encoder_decoder_model(model, X_train, y_train, X_test, y_test): print("shapes: X_train:", np.shape(X_train)," y_train: ", np.shape(y_train)," X_test: ", np.shape(X_test)," y_test: ", np.shape(y_test)) file_logger = FileLogger('training.log') # 调整输入和目标维度 X_train_enc = np.expand_dims(X_train, axis=1) X_train_dec = np.zeros((X_train.shape[0], 1, 25)) X_test_enc = np.expand_dims(X_test, axis=1) X_test_dec = np.zeros((X_test.shape[0], 1, 25)) y_train_target = np.expand_dims(X_train, axis=1) y_test_target = np.expand_dims(X_test, axis=1) model.fit(x=[X_train_enc, X_train_dec], y=y_train_target, batch_size=100, epochs=100, verbose=2, validation_data=([X_test_enc, X_test_dec], y_test_target), callbacks=[file_logger]) return model
步骤3:优化任务逻辑(可选)
如果是自编码任务,当前解码器输入shape=(None,25)的设计可能不够合理,建议调整解码器输入层形状与编码器输入一致(shape=(None, num_features)),并修改后续Dense层参数,让模型逻辑更自洽,避免使用全零输入这类临时方案。
内容的提问来源于stack exchange,提问作者elbilo

