CNN-LSTM回归模型的TFRecord数据输入方法求助
问题描述
我拥有2000年、2010年、2020年三个年份的图像数据集,分别存储为combined_2000.tfrecord、combined_2010.tfrecord和combined_2020.tfrecord文件,图像尺寸为40×40×7,每个文件包含图像与标签。计划采用CNN-LSTM架构构建回归模型,已完成数据集拆分,但不清楚如何将三年的图像输入到定义好的模型中。
已完成的数据集拆分代码:
train_size = int(0.7 * 2000) val_size = int(0.15 * 2000) test_size = 2000 - train_size - val_size train_tf_2000 = combined_dataset_2000.take(train_size) remaining_tf_2000 = combined_dataset_2000.skip(train_size) val_tf_2000 = remaining_tf_2000.take(val_size) test_tf_2000 = remaining_tf_2000.skip(val_size) train_tf_2010 = combined_dataset_2010.take(train_size) remaining_tf_2010 = combined_dataset_2010.skip(train_size) val_tf_2010 = remaining_tf_2010.take(val_size) test_tf_2010 = remaining_tf_2010.skip(val_size) train_tf_2020 = combined_dataset_2020.take(train_size) remaining_tf_2020 = combined_dataset_2020.skip(train_size) val_tf_2020 = remaining_tf_2020.take(val_size) test_tf_2020 = remaining_tf_2020.skip(val_size)
已定义的CNN-LSTM模型:
from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, TimeDistributed, LSTM, Dense, Dropout # Assuming your image dimensions are (image_height, image_width, num_channels) input_shape = (40, 40, 7) # Adjust num_channels if needed num_years = 3 # Define CNN model cnn = Sequential() cnn.add(Conv2D(32, (3, 3), activation='relu', input_shape=input_shape)) cnn.add(MaxPooling2D((2, 2))) cnn.add(Flatten()) # Define LSTM model model = Sequential() model.add(TimeDistributed(cnn, input_shape=(num_years, *input_shape))) model.add(LSTM(64, return_sequences=True)) model.add(LSTM(64)) model.add(Dense(64, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(1)) # Single output unit for regression model.compile(optimizer='adam', loss='mean_squared_error', metrics=['mae'])
解决方案
你的模型输入要求是形状为(num_years, 40, 40, 7)的时间序列样本,即每个输入样本由同组的2000、2010、2020三年的图像按时间顺序组成。需要通过以下步骤将拆分后的数据集适配模型输入:
1. 确保样本顺序对齐
首先要保证combined_dataset_2000、combined_dataset_2010、combined_dataset_2020中的样本是一一对应的(第i个样本属于同一组,对应三年的观测数据),这是合并的前提。
2. 合并同组三年样本
使用tf.data.Dataset.zip将三年的数据集按样本索引配对,再通过map操作把三年的图像拼接成时间序列,同时提取对应标签(这里以2020年的标签作为回归目标为例,可根据需求调整):
import tensorflow as tf # 合并三年样本为模型输入格式 def combine_year_samples(img_2000, label_2000, img_2010, label_2010, img_2020, label_2020): # 将三年图像拼接成(3, 40, 40, 7)的时间序列 sequence_imgs = tf.stack([img_2000, img_2010, img_2020], axis=0) # 自定义回归目标,这里取2020年标签,可替换为三年标签的均值等逻辑 target_label = label_2020 return sequence_imgs, target_label # 合并训练集 train_dataset = tf.data.Dataset.zip((train_tf_2000, train_tf_2010, train_tf_2020)) train_dataset = train_dataset.map(lambda x, y, z: combine_year_samples(x[0], x[1], y[0], y[1], z[0], z[1])) # 合并验证集 val_dataset = tf.data.Dataset.zip((val_tf_2000, val_tf_2010, val_tf_2020)) val_dataset = val_dataset.map(lambda x, y, z: combine_year_samples(x[0], x[1], y[0], y[1], z[0], z[1])) # 合并测试集 test_dataset = tf.data.Dataset.zip((test_tf_2000, test_tf_2010, test_tf_2020)) test_dataset = test_dataset.map(lambda x, y, z: combine_year_samples(x[0], x[1], y[0], y[1], z[0], z[1]))
3. 数据集优化(可选但推荐)
添加批处理、预取操作提升训练效率:
batch_size = 32 train_dataset = train_dataset.batch(batch_size).prefetch(tf.data.AUTOTUNE) val_dataset = val_dataset.batch(batch_size).prefetch(tf.data.AUTOTUNE) test_dataset = test_dataset.batch(batch_size).prefetch(tf.data.AUTOTUNE)
4. 模型训练
直接使用合并后的数据集训练模型:
history = model.fit( train_dataset, validation_data=val_dataset, epochs=20, verbose=1 ) # 测试模型 test_loss, test_mae = model.evaluate(test_dataset, verbose=1) print(f"Test Loss: {test_loss}, Test MAE: {test_mae}")
关键说明
- 如果回归目标是三年序列对应的综合值,只需修改
combine_year_samples函数中的target_label计算逻辑(比如取三年标签的平均值)。 - 确保读取TFRecord的函数输出为
(image, label)格式的元组,否则需要调整combine_year_samples的参数解析逻辑。
内容的提问来源于stack exchange,提问作者riskiem
相关产品推荐
相关产品推荐

