基于Keras/TensorFlow的多维多变量时间序列预测数据塑形问题
我完全明白这种摸不着头脑的感觉——大多数教程都是单变量单实体的简单例子,碰到多城市、多指标的真实场景时,确实会一下子懵住。咱们把这个问题拆解开,一步步搞清楚Keras/TensorFlow需要的数据格式,再结合你的场景给出具体操作。
核心概念先理清
Keras中循环神经网络(LSTM/GRU等)处理时间序列的标准输入格式是:(样本数, 时间步长, 特征数)
- 样本数:你用滑动窗口生成的训练样本总数
- 时间步长:每个输入序列包含的历史数据步数(比如用过去7天的数据,时间步长就是7)
- 特征数:每个时间步包含的变量数量(比如你的温度、车流量、湿度,就是3个特征)
而目标序列(y)的格式取决于你的预测需求:
- 预测单步单指标:
(样本数, 1) - 预测单步多指标:
(样本数, 目标特征数) - 预测多步多指标:
(样本数, 预测步数, 目标特征数)
针对你的多城市多指标场景的具体步骤
你的数据集是「多个城市的日度多指标数据」,核心是先把每个城市的时间序列独立整理,再转化为模型能接受的样本格式,分两步走:
1. 拆分并整理每个城市的时间序列
首先把原始数据按城市分组,确保每个城市的日期是严格按时间顺序排列的。每个城市会得到一个二维表格:(总天数, 特征数),比如某城市有730天数据(两年),3个特征,那就是(730, 3)的结构。
2. 用滑动窗口生成训练样本
时间序列预测本质是监督学习,需要用「过去T步的所有特征」来预测「未来K步的目标指标」。你需要定义:
time_steps:用多少天的历史数据(比如7天)target_steps:要预测未来多少天(比如1天)target_cols:要预测的指标(比如只预测车流量,或者同时预测温度+车流量)
通过滑动窗口,每个城市的(天数, 特征数)数据会转化为:
- 输入X:
(样本数, time_steps, 特征数) - 目标y:
(样本数, target_steps, 目标特征数)
最后把所有城市的样本合并,就得到全局的训练数据集。
代码示例(结合你的场景)
假设你的原始数据是Pandas DataFrame,结构如下:
| 城市ID | 日期 | 温度 | 车流量 | 湿度 |
|---|---|---|---|---|
| 0 | 2022-01-01 | 10 | 500 | 60 |
| 0 | 2022-01-02 | 12 | 550 | 58 |
| 1 | 2022-01-01 | 8 | 400 | 65 |
以下是完整的数据处理和模型构建代码:
import pandas as pd import numpy as np from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense from sklearn.preprocessing import StandardScaler # ---------------------- # 1. 数据预处理:分组+标准化 # ---------------------- # 假设df是你的原始数据 df = pd.read_csv("your_data.csv") # 按城市分组 grouped = df.groupby('城市ID') # 特征标准化:每个特征单独做标准化(非常重要!) scalers = {} feature_cols = ['温度', '车流量', '湿度'] for col in feature_cols: scalers[col] = StandardScaler() df[col] = scalers[col].fit_transform(df[[col]]) # ---------------------- # 2. 滑动窗口生成样本函数 # ---------------------- def create_sequences(data, time_steps=7, target_steps=1, target_cols=['车流量']): X, y = [], [] # 提取特征值数组 data_values = data[feature_cols].values # 获取目标特征的索引 target_indices = [feature_cols.index(col) for col in target_cols] # 滑动窗口生成样本 for i in range(len(data_values) - time_steps - target_steps + 1): # 输入序列:过去time_steps天的所有特征 seq_x = data_values[i:i+time_steps] # 目标序列:未来target_steps天的目标特征 seq_y = data_values[i+time_steps:i+time_steps+target_steps, target_indices] X.append(seq_x) y.append(seq_y) return np.array(X), np.array(y) # ---------------------- # 3. 处理所有城市的样本 # ---------------------- time_steps = 7 # 用过去7天数据 target_steps = 1 # 预测未来1天 target_cols = ['车流量'] # 可改为多指标如['温度', '车流量'] all_X, all_y = [], [] for city_id, group in grouped: # 确保日期按顺序排列 group = group.sort_values('日期') X_city, y_city = create_sequences(group, time_steps, target_steps, target_cols) all_X.append(X_city) all_y.append(y_city) # 合并所有城市的样本 X = np.concatenate(all_X, axis=0) y = np.concatenate(all_y, axis=0) # 如果是单步预测,可压缩y的维度(比如从(N,1,1)变成(N,1)) y = np.squeeze(y) # ---------------------- # 4. 构建并训练模型 # ---------------------- model = Sequential() # LSTM层输入形状:(time_steps, 特征数) model.add(LSTM(64, input_shape=(time_steps, len(feature_cols)))) # 输出层单元数等于目标特征数 model.add(Dense(len(target_cols))) model.compile(optimizer='adam', loss='mse') # 训练模型 history = model.fit(X, y, epochs=20, batch_size=32, validation_split=0.2)
常见避坑点
- 维度不要搞反:一定要记住输入格式是
(样本数, 时间步长, 特征数),很多人会不小心写成(样本数, 特征数, 时间步长),导致模型报错。 - 特征必须标准化:不同指标的量纲差异极大(比如温度是0-30,车流量是几百上千),不标准化会让模型偏向数值大的特征,严重影响效果。
- 多城市的进阶处理:如果需要考虑城市间的关联(比如用城市A的数据辅助预测城市B),可以把城市ID转化为嵌入特征,加入到输入序列中,此时输入形状会变成
(样本数, time_steps, 特征数 + 嵌入维度)。 - 多步预测的调整:如果要预测未来多天,目标y的形状是
(样本数, target_steps, 目标特征数),此时模型可以用return_sequences=True的LSTM层,或者用序列到序列(Seq2Seq)结构。
内容的提问来源于stack exchange,提问作者Bastien
相关产品推荐
相关产品推荐

