基于Keras/TensorFlow的多维多变量时间序列预测数据格式疑问
多城市多特征时间序列预测:Keras/TensorFlow数据塑形指南
我太懂这种迷茫了——翻了一堆博客、教程,大多都是单变量单序列的简单示例,真碰到多城市、多特征的日度数据,瞬间就不知道该怎么把数据掰成模型要的形状了。咱们一步步来拆解,帮你理清思路:
先明确核心维度要求
Keras里的时间序列模型(比如LSTM、GRU)最常用的输入形状是 (样本数, 时间步长, 特征数):
- 样本数:指你能生成的「输入窗口-目标值」对的总数
- 时间步长:比如用过去7天的数据预测第8天,时间步长就是7
- 特征数:每个时间点上的特征数量(温度、车流量、湿度,再加上城市标识的话也算)
针对你的多城市场景,有两种主流处理思路,选哪种取决于你希望模型学习的目标:
思路1:把城市当作额外特征(适合城市间共性强的场景)
如果不同城市的规律比较相似,你希望模型学习通用模式,可以把城市转换成编码特征(比如one-hot编码),和温度、车流量等放在一起作为特征组。
操作步骤:
- 先对原始数据按「城市+日期」排序,确保每个城市的时间序列是连续的
- 给每个城市生成one-hot编码(比如城市A是[1,0,0],城市B是[0,1,0])
- 把one-hot编码和原有特征(温度、车流量、湿度)合并
- 用Keras的工具函数生成时间序列数据集
代码示例:
import pandas as pd import numpy as np from tensorflow.keras.utils import timeseries_dataset_from_array from sklearn.preprocessing import StandardScaler # 假设你的原始数据已加载到df,包含列:city, date, temperature, traffic, humidity df = df.sort_values(['city', 'date']) # 1. 特征标准化(非常重要,时间序列模型对尺度敏感) scaler = StandardScaler() feature_cols = ['temperature', 'traffic', 'humidity'] df[feature_cols] = scaler.fit_transform(df[feature_cols]) # 2. 生成城市one-hot编码 city_one_hot = pd.get_dummies(df['city'], prefix='city') df = pd.concat([df, city_one_hot], axis=1) # 3. 定义时间步长和目标列 time_steps = 7 # 用过去7天预测第8天 target_col = 'traffic' # 假设要预测车流量 # 4. 提取特征和目标 all_features = df.drop(['city', 'date', target_col], axis=1).values all_targets = df[target_col].values # 5. 生成时间序列数据集 dataset = timeseries_dataset_from_array( data=all_features, targets=all_targets[time_steps:], # 目标是每个窗口之后的第一个值 sequence_length=time_steps, batch_size=32, # 批次大小根据你的显存调整 shuffle=True # 训练时打乱数据 ) # 查看批次形状:(32, 7, 特征数),完全符合LSTM输入要求 for batch in dataset.take(1): inputs, targets = batch print(f"输入形状: {inputs.shape}") print(f"目标形状: {targets.shape}")
思路2:每个城市作为独立序列(适合城市间差异大的场景)
如果不同城市的规律差异很大,你希望模型针对每个城市的特性学习,可以把每个城市的时间序列单独处理,再合并成数据集。这种方式可以保留城市的独立性,甚至可以用共享权重的模型分别训练。
操作步骤:
- 按城市分组,每个城市单独处理时间序列
- 对每个城市生成「输入窗口-目标值」对
- 把所有城市的数据集合并
代码示例:
import pandas as pd import tensorflow as tf from tensorflow.keras.utils import timeseries_dataset_from_array from sklearn.preprocessing import StandardScaler df = df.sort_values(['city', 'date']) scaler = StandardScaler() feature_cols = ['temperature', 'traffic', 'humidity'] df[feature_cols] = scaler.fit_transform(df[feature_cols]) time_steps = 7 target_col = 'traffic' # 定义单个城市的数据集生成函数 def create_city_dataset(city_df): features = city_df.drop(['city', 'date', target_col], axis=1).values targets = city_df[target_col].values return timeseries_dataset_from_array( data=features, targets=targets[time_steps:], sequence_length=time_steps, batch_size=32 ) # 遍历所有城市,生成数据集并合并 city_datasets = [] for city_name in df['city'].unique(): city_df = df[df['city'] == city_name] city_ds = create_city_dataset(city_df) city_datasets.append(city_ds) # 合并所有城市的数据集 combined_dataset = tf.data.Dataset.concatenate(*city_datasets) combined_dataset = combined_dataset.shuffle(buffer_size=1000)
模型适配示例
不管用哪种思路,生成的数据集都直接可以喂给LSTM模型:
from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense # 获取特征数(从第一个批次里提取) for batch in combined_dataset.take(1): inputs, _ = batch num_features = inputs.shape[-1] model = Sequential([ LSTM(64, input_shape=(time_steps, num_features)), # 输入形状匹配时间步长和特征数 Dense(32, activation='relu'), Dense(1) # 单输出(预测车流量),如果是多输出改成对应数量即可 ]) model.compile(optimizer='adam', loss='mse') model.fit(combined_dataset, epochs=10)
避坑提醒
- 缺失值处理:每个城市的时间序列必须连续,有缺失值的话用插值、均值填充等方式补全
- 标准化注意:如果是按城市单独处理,建议每个城市单独拟合标准化器;如果是全局处理,要确保不同城市的特征尺度不会互相干扰
- 多输出预测:如果要同时预测温度、车流量、湿度,只需要把目标改成多列数组,最后一层Dense改成
Dense(3)即可
内容的提问来源于stack exchange,提问作者Bastien
相关产品推荐
相关产品推荐

