
文章目录1. 课前导读1.1 本节课学习目标1.2 知识重难点1.3 学习前置条件1.4 学完可掌握能力1.5 行业应用场景2. 核心理论精讲2.1 时序预测问题定义2.2 滑动窗口数据构造2.3 时序预测的评估指标2.4 模型选择LSTM vs GRU2.5 特征工程技巧3. 环境搭建与工具配置4. 代码实战教学4.1 滑动窗口函数实现4.2 单变量单步预测示例随机数据5. 案例实操演练5.1 案例一零售销量预测单变量多步预测5.1.1 加载与探索数据5.1.2 加入时间特征星期几进行多变量预测5.2 案例二天气时序预测多变量多步5.2.1 加载数据模拟或真实5.2.2 构建GRU多步预测模型5.2.3 对比基线模型持久性预测6. 常见坑点与排错总结6.1 数据预处理坑点6.2 模型训练坑点6.3 评估坑点6.4 特征工程坑点7. 知识点总结 课后作业7.1 核心知识点梳理7.2 基础作业7.3 进阶实操作业7.4 思考拓展题《TensorFlow2.x: 深度学习入门到高阶实战教程》系列课程导航1. 课前导读1.1 本节课学习目标理解时序预测任务的基本类型单步预测预测下一个时间点、多步预测预测未来多个时间点、多变量预测多个输入特征。掌握时序数据的预处理方法滑动窗口构造有监督化、训练/验证/测试集划分保持时间顺序、归一化/标准化。学会使用TensorFlow搭建LSTM/GRU模型进行时序预测包括单向和双向结构。能够评估时序预测模型MAE、RMSE、MAPE并可视化预测结果。通过两个实战项目销量预测、天气预测掌握完整流程。1.2 知识重难点类别内容重点滑动窗口构造原理与代码实现多变量多步预测的输入输出形状设计LSTM/GRU在时序预测中的参数设置难点多步预测的策略直接多步、递归多步、混合策略时间序列的交叉验证方法防止未来信息泄露易混淆点单步预测的标签定义下一个时间步多步预测中输出维度与时间步的关系训练时shuffle需谨慎时序数据不应打乱顺序1.3 学习前置条件已掌握LSTM/GRU原理第27课。能够使用TensorFlow搭建序列模型。熟悉Pandas和NumPy的基本操作第2课。1.4 学完可掌握能力独立为任何单变量/多变量时序数据构建预测模型。处理真实场景中的销量、流量、天气等预测问题。选择合适的预测步长和评估指标。避免时序预测中的常见陷阱数据泄露、不恰当的评估。1.5 行业应用场景零售销量预测预测未来几天/几周的销量优化库存管理。能源负载预测预测电力或天然气需求。金融价格预测股票、汇率等需谨慎风险高。气象预报温度、降水量预测。网络流量预测CDN带宽、服务器负载。2. 核心理论精讲2.1 时序预测问题定义给定历史观测序列 ( y_1, y_2, \dots, y_t )可能包含外生特征 ( X_1, \dots, X_t )预测未来 ( H ) 步的值 ( y_{t1}, \dots, y_{tH} )。单变量预测仅使用目标变量本身的历史值。多变量预测使用多个相关特征如销量促销活动节假日。单步预测( H1 )。多步预测( H1 )。递归多步预测将前一步的预测作为输入逐步预测下一步误差会累积。直接多步预测模型直接输出 ( H ) 个值输出维度为 ( H )误差独立。混合策略结合两者。2.2 滑动窗口数据构造将时序数据转换为有监督学习样本选择窗口长度 ( W )look_back用前 ( W ) 个时间步预测下一个时间步或未来 ( H ) 步。对于多变量窗口内包含多个特征。构造后数据集形状单变量单步输入(样本数, W, 1)输出(样本数, 1)多变量单步输入(样本数, W, n_features)输出(样本数, n_targets)多变量多步直接法输出(样本数, H, n_targets)注意时序数据不能随机打乱时间顺序应保持但每个epoch可保持相同顺序验证集和测试集必须严格在训练集之后避免未来信息泄露。2.3 时序预测的评估指标MAE平均绝对误差直观单位同原始数据。RMSE均方根误差对大误差惩罚更大。MAPE平均绝对百分比误差相对误差适合比较不同尺度的序列。[\text{MAPE} \frac{100%}{n} \sum_{i1}^{n} \left| \frac{y_i - \hat{y}_i}{y_i} \right|]需注意真实值不能为零。2.4 模型选择LSTM vs GRU对于大多数时序预测GRU因参数量少、训练快而表现良好LSTM在极长序列上可能略优。本课将使用GRU作为主力但LSTM同样适用。2.5 特征工程技巧时间特征星期几、月份、是否节假日等作为额外输入特征。滞后特征除窗口外可加入特定滞后如昨天、上周同一天作为新特征。差分将原始序列差分一阶差分使序列平稳预测差值后再还原。3. 环境搭建与工具配置沿用第27课环境额外安装pandas若未安装。conda activate tf213 pipinstallpandas导入importtensorflowastfimportnumpyasnpimportpandasaspdimportmatplotlib.pyplotaspltfromsklearn.preprocessingimportMinMaxScaler,StandardScalerfromsklearn.metricsimportmean_absolute_error,mean_squared_errorimportdatetime4. 代码实战教学4.1 滑动窗口函数实现defcreate_sequences(data,look_back,look_forward1,target_col_index-1): data: numpy数组或DataFrame形状 (samples, features) look_back: 窗口大小 look_forward: 预测未来步数 target_col_index: 目标列索引默认最后一列 返回 X: (num_samples, look_back, n_features), y: (num_samples, look_forward) 或 (num_samples,) X,y[],[]n_featuresdata.shape[1]foriinrange(len(data)-look_back-look_forward1):X.append(data[i:ilook_back,:])y.append(data[ilook_back:ilook_backlook_forward,target_col_index])returnnp.array(X),np.array(y)4.2 单变量单步预测示例随机数据# 生成模拟时序tnp.arange(0,1000)y100.5*t5*np.sin(t/50)np.random.randn(1000)*2plt.plot(t,y)plt.title(Simulated Time Series)plt.show()# 归一化scalerMinMaxScaler()y_scaledscaler.fit_transform(y.reshape(-1,1))# 构造窗口look_back20X,y_seqcreate_sequences(y_scaled,look_back,look_forward1,target_col_index0)print(fX shape:{X.shape}, y shape:{y_seq.shape})# 划分训练集/验证集/测试集按顺序train_sizeint(len(X)*0.7)val_sizeint(len(X)*0.15)X_train,X_val,X_testX[:train_size],X[train_size:train_sizeval_size],X[train_sizeval_size:]y_train,y_val,y_testy_seq[:train_size],y_seq[train_size:train_sizeval_size],y_seq[train_sizeval_size:]# 构建GRU模型modeltf.keras.Sequential([tf.keras.layers.GRU(64,input_shape(look_back,1)),tf.keras.layers.Dense(1)])model.compile(optimizeradam,lossmse)historymodel.fit(X_train,y_train,epochs30,batch_size32,validation_data(X_val,y_val),verbose0)# 预测并反归一化y_predmodel.predict(X_test)y_pred_origscaler.inverse_transform(y_pred)y_test_origscaler.inverse_transform(y_test)maemean_absolute_error(y_test_orig,y_pred_orig)print(fTest MAE:{mae:.4f})5. 案例实操演练5.1 案例一零售销量预测单变量多步预测5.1.1 加载与探索数据使用内置模拟数据集或真实公开数据如Kaggle超市销量。为便于演示生成模拟日销量数据含季节性、趋势、噪声。# 生成模拟销量数据3年日数据datespd.date_range(2020-01-01,periods1000,freqD)sales1000.05*np.arange(1000)# 趋势sales20*np.sin(2*np.pi*np.arange(1000)/365)# 年周期salesnp.random.normal(0,10,1000)# 噪声dfpd.DataFrame({date:dates,sales:sales})df.set_index(date,inplaceTrue)df.plot(titleDaily Sales)plt.show()# 单变量预测未来7天销量多步直接输出7个值look_back60look_forward7datadf[sales].values.reshape(-1,1)scalerMinMaxScaler()data_scaledscaler.fit_transform(data)X,ycreate_sequences(data_scaled,look_back,look_forward,target_col_index0)# y形状 (样本数, 7)# 划分train_endint(len(X)*0.7)val_endint(len(X)*0.85)X_train,y_trainX[:train_end],y[:train_end]X_val,y_valX[train_end:val_end],y[train_end:val_end]X_test,y_testX[val_end:],y[val_end:]# 构建模型输出7个值model_salestf.keras.Sequential([tf.keras.layers.LSTM(64,return_sequencesTrue,input_shape(look_back,1)),tf.keras.layers.LSTM(32),tf.keras.layers.Dense(7)# 直接输出7步])model_sales.compile(optimizeradam,lossmse)history_salesmodel_sales.fit(X_train,y_train,epochs50,batch_size32,validation_data(X_val,y_val),callbacks[tf.keras.callbacks.EarlyStopping(patience5)],verbose0)# 评估y_predmodel_sales.predict(X_test)y_pred_invscaler.inverse_transform(y_pred)y_test_invscaler.inverse_transform(y_test)maemean_absolute_error(y_test_inv.flatten(),y_pred_inv.flatten())rmsenp.sqrt(mean_squared_error(y_test_inv.flatten(),y_pred_inv.flatten()))print(fTest MAE:{mae:.2f}, RMSE:{rmse:.2f})# 可视化最后几个样本的预测与真实7天窗口plt.figure(figsize(12,5))foriinrange(min(4,len(X_test))):plt.subplot(2,2,i1)plt.plot(y_test_inv[i],labelTrue)plt.plot(y_pred_inv[i],labelPred)plt.legend()plt.title(fSample{i1})plt.tight_layout()plt.show()5.1.2 加入时间特征星期几进行多变量预测# 加入星期几特征0-6df[weekday]df.index.dayofweek# 归一化特征scaler_XMinMaxScaler()featuresdf[[sales,weekday]].values features_scaledscaler_X.fit_transform(features)X_multi,y_multicreate_sequences(features_scaled,look_back,look_forward,target_col_index0)# 划分同上X_train_m,X_val_m,X_test_m,y_train_m,y_val_m,y_test_m...# 输入形状 (batch, look_back, 2)model_multitf.keras.Sequential([tf.keras.layers.GRU(64,input_shape(look_back,2)),tf.keras.layers.Dense(7)])model_multi.compile(optimizeradam,lossmse)model_multi.fit(...)# 评估对比5.2 案例二天气时序预测多变量多步使用公开的天气数据集如Jena气候数据集预测未来24小时温度。5.2.1 加载数据模拟或真实# 由于真实数据较大我们生成模拟多变量时序温度、湿度、气压np.random.seed(42)n_steps5000tnp.arange(n_steps)temp1510*np.sin(2*np.pi*t/200)np.random.randn(n_steps)*2humidity6020*np.sin(2*np.pi*t/150)np.random.randn(n_steps)*5pressure10135*np.sin(2*np.pi*t/300)np.random.randn(n_steps)*3data_weathernp.column_stack([temp,humidity,pressure])# 形状 (n_steps, 3)target_col0# 预测温度# 归一化scaler_weatherMinMaxScaler()data_scaledscaler_weather.fit_transform(data_weather)# 构造窗口预测未来24步24小时look_back168# 过去7天24*7look_forward24X_weather,y_weathercreate_sequences(data_scaled,look_back,look_forward,target_col_indextarget_col)# y_weather形状 (样本数, 24)# 划分train_szint(len(X_weather)*0.7)val_szint(len(X_weather)*0.15)X_train_w,y_train_wX_weather[:train_sz],y_weather[:train_sz]X_val_w,y_val_wX_weather[train_sz:train_szval_sz],y_weather[train_sz:train_szval_sz]X_test_w,y_test_wX_weather[train_szval_sz:],y_weather[train_szval_sz:]5.2.2 构建GRU多步预测模型model_weathertf.keras.Sequential([tf.keras.layers.GRU(128,return_sequencesTrue,input_shape(look_back,3)),tf.keras.layers.GRU(64),tf.keras.layers.Dense(24)])model_weather.compile(optimizertf.keras.optimizers.Adam(0.001),lossmse,metrics[mae])callbacks[tf.keras.callbacks.EarlyStopping(patience10,restore_best_weightsTrue),tf.keras.callbacks.ReduceLROnPlateau(factor0.5,patience5)]historymodel_weather.fit(X_train_w,y_train_w,epochs100,batch_size64,validation_data(X_val_w,y_val_w),callbackscallbacks,verbose1)# 评估测试集y_pred_wmodel_weather.predict(X_test_w)# 反归一化只反归一化温度列definverse_scale_for_target(y_scaled,target_idx0,scalerscaler_weather):# 因为scaler是对整体特征归一化的反归一化需构造虚拟数组dummynp.zeros((len(y_scaled),data_scaled.shape[1]))dummy[:,target_idx]y_scaled dummy_invscaler.inverse_transform(dummy)returndummy_inv[:,target_idx]y_test_invinverse_scale_for_target(y_test_w.flatten(),target_col,scaler_weather)y_pred_invinverse_scale_for_target(y_pred_w.flatten(),target_col,scaler_weather)y_test_invy_test_inv.reshape(-1,24)y_pred_invy_pred_inv.reshape(-1,24)# 整体MAEmae_weathermean_absolute_error(y_test_inv.flatten(),y_pred_inv.flatten())print(fMulti-step weather forecast MAE:{mae_weather:.2f}°C)# 可视化第一个测试样本的24小时预测plt.plot(y_test_inv[0],labelTrue)plt.plot(y_pred_inv[0],labelPredicted)plt.xlabel(Hour ahead)plt.ylabel(Temperature (°C))plt.legend()plt.title(24-hour Temperature Forecast)plt.show()5.2.3 对比基线模型持久性预测# 持久性预测未来温度等于最后一个观测值last_obsX_test_w[:,-1,target_col]# 每个样本窗口的最后一个温度值归一化last_obs_invinverse_scale_for_target(last_obs,target_col,scaler_weather)# 对于每个样本预测未来24小时都是该值persistence_prednp.tile(last_obs_inv.reshape(-1,1),(1,24))persistence_maemean_absolute_error(y_test_inv.flatten(),persistence_pred.flatten())print(fPersistence MAE:{persistence_mae:.2f}°C)print(fGRU improvement:{persistence_mae-mae_weather:.2f}°C)6. 常见坑点与排错总结6.1 数据预处理坑点坑1划分训练/测试集时随机打乱导致未来信息泄露模型看到未来数据。解决必须按时间顺序划分使用切片索引。坑2归一化时对整个序列一起fit导致测试集信息泄露。解决仅用训练集fit归一化器再transform训练、验证、测试集。坑3创建滑动窗口时未考虑预测步长导致样本重叠但这不是错误只是增加样本数量。6.2 模型训练坑点坑4多步输出直接使用MSE损失但不同时间步的误差可能差异大。可加权MSE。坑5LSTM/GRU的return_sequences设置错误导致维度不匹配。坑6忘记在Dense(7)层后使用合适的激活函数回归任务一般不用激活。6.3 评估坑点坑7使用MAPE时目标值有零或接近零导致无穷大。解决过滤零值或使用sMAPE。坑8多步预测评估时对每个样本的24步独立计算MAE但业务上可能更关心平均绝对百分比误差。6.4 特征工程坑点坑9加入时间特征如星期几但未周期性编码用sin/cos导致模型难以理解循环性质。改进使用sin(2π*day/7),cos(2π*day/7)。坑10未处理节假日等特殊事件模型预测精度受限。7. 知识点总结 课后作业7.1 核心知识点梳理时序预测类型单/多变量单/多步。滑动窗口构造create_sequences函数注意时间顺序。模型搭建LSTM/GRU Dense输出多步。评估MAE、RMSE、MAPE与基线模型对比。特征工程时间特征、滞后特征、差分。7.2 基础作业使用create_sequences函数对单变量序列长度500构造窗口大小30预测步长5输出X和y的形状。在销量预测案例中将GRU层数改为2层return_sequencesTrue对比参数量和性能。计算天气预测案例中每个测试样本的24步预测的MAE绘制直方图。7.3 进阶实操作业任务多变量多步预测的编码器-解码器结构使用编码器-解码器Encoder-Decoder架构编码器将输入窗口编码为上下文向量解码器逐步生成未来多步预测。要求编码器使用LSTM(return_sequencesFalse)。解码器使用RepeatVector重复上下文向量然后LSTM(return_sequencesTrue)最后TimeDistributed(Dense(1))。在天气数据集上训练对比直接多步输出模型的性能。7.4 思考拓展题在递归多步预测中预测误差会累积。请设计一个混合策略结合直接多步和递归预测并分析其优劣。如果时间序列具有强周期性如每周、每年如何在LSTM/GRU中显式注入周期信息除了添加时间特征还可以使用哪些网络结构在实际生产环境中模型需要经常重新训练以适应最新数据。如何设计一个增量学习在线学习的机制使得模型能够在不完全重新训练的情况下更新下一课预告自然语言处理基础——我们将介绍文本数据的分词、词向量表示、Tokenization等NLP核心概念为后续文本分类和序列模型应用打下基础。《TensorFlow2.x: 深度学习入门到高阶实战教程》系列课程导航去订阅第一部分基础入门1-10 课第二部分神经网络核心11-25 课第三部分进阶网络与框架高阶26-40 课第四部分企业实战与项目落地41-50 课 感谢您耐心阅读到这里 如果本文对您有所启发欢迎 点赞 收藏 分享给更多需要的伙伴。️ 期待在评论区看到您的想法, 共同进步。 关注我持续获取更多干货内容 我们下篇文章见