如何以Pythonic方式重塑多ID时序DataFrame适配Keras LSTM输入?
多ID时序DataFrame转换为LSTM输入格式方案
核心思路
针对每个ID下的时序数据,生成连续4条观测作为输入(形状(4,5)),对应下一条数据的部分特征作为目标(匹配模型最后一层Dense(2)),最终合并所有ID的样本得到(num_samples,4,5)的标准LSTM输入格式。
实现步骤(Pythonic写法)
1. 预处理:确保时序有序
首先对DataFrame按id和date排序,保证每个ID下的观测严格按时间先后排列:
import pandas as pd import numpy as np from numpy.lib.stride_tricks import sliding_window_view import tensorflow as tf # 假设你的数据已加载为df df = df.sort_values(by=['id', 'date'])
2. 按ID分组生成样本
定义函数处理单个ID的时序数据,用滑动窗口高效生成输入和目标:
def generate_lstm_data(group): # 提取当前ID的特征列,转为numpy数组(形状:[n,5],n为该ID的观测数) feat_data = group[['col1', 'col2', 'col3', 'col4', 'col5']].values # 过滤观测数不足5的ID(无法生成4个输入+1个目标) if len(feat_data) < 5: return None, None # 生成滑动窗口输入:形状自动转为[num_samples,4,5] X = sliding_window_view(feat_data, window_shape=4, axis=0) # 生成目标:取每个窗口后第1条数据的前2个特征(匹配Dense(2)输出) y = feat_data[4:, :2] return X, y
3. 合并所有ID的样本
遍历所有分组,收集有效样本并合并为最终训练数据:
all_X = [] all_y = [] for _, group in df.groupby('id'): X, y = generate_lstm_data(group) if X is not None: all_X.append(X) all_y.append(y) # 合并后得到符合要求的输入和目标 X_train = np.concatenate(all_X, axis=0) y_train = np.concatenate(all_y, axis=0) # 验证形状:X_train应为[num_samples,4,5],y_train为[num_samples,2] print(f"输入数据形状:{X_train.shape}") print(f"目标数据形状:{y_train.shape}")
4. 修正模型输入形状
原模型的input_shape=[None,4,5]写法冗余,LSTM层的input_shape只需指定单样本的形状(时间步+特征数),修正后模型定义如下:
model = tf.keras.Sequential() model.add(tf.keras.layers.LSTM(50, activation='relu', input_shape=(4,5))) model.add(tf.keras.layers.Dense(2)) model.compile(optimizer='adam', loss='mse')
关键说明
- 使用
sliding_window_view(numpy 1.20+支持)比手动循环生成窗口更高效,适合大规模数据集。 - 必须保证每个ID下的时序有序,否则生成的样本无实际预测意义。
- 自动过滤观测数不足5的ID,避免生成无效样本。
内容的提问来源于stack exchange,提问作者user1357015
相关产品推荐
相关产品推荐

