最强总结!融合Prophet、LSTM与XGBoost,时间序列预测 !!
哈喽我是cos大壮~昨天, 又有一位会员提出此问题: 若讲, 将融合、LSTM以及, 把时间序列预测做得稳固、做得准确、做得精细这般情况, 可不可以达成?当然还是要结合他的具体业务来聊聊~时间序列预测本身这件事, 在行业里被广泛运用, 比如用于销量预测, 用于流量预估, 用于库存补货, 用于金融波动分析, 用于设备告警提示, 用于能源负荷判定, 几乎每个业务系统都无法避开。一般来讲, 能够轻易被理解的情况是, 仅凭借一个模型, 时常会碰到这样的问题, 即“趋势能够看得明白, 波动却难以留住掌控。还有“短期内精准无误, 长期则飘忽不定, 以及遇到节假日、促销活动和突发事件之时就失去效用运行不灵”。所以, 今朝我们所要分享的这个具备融合性质的方案, 从根本上来说, 便是将三类模型各自的出众之处聚合起来: 其中一类负责趋势以及周期, LSTM承担捕捉序列当中的复杂时序依赖的任务, 还有一类负责处理结构化特征、残差以及非线性关系, 最终会把这些所产生的结果融合成为一体, 从而创建一个更加稳定的预测系统。作为实现能先将整套给定方案关于主线内容清晰予以看清的一种方式, 即进行辅助性观察, 我们能够施行这样一个举措, 也就是先去查看一张展现全部内容的架构图。此架构图呢, 针对“原始时间序列 外部特征”各自是怎样朝着所提及的 、LSTM 和 方向流动前行 的情形 , 以及最终究竟是以怎样的方式输出预测结果这一情况, 实现了一种全幅度的连贯串联。我们能够从这张图着手建起一个总的印象, 即这般, 可不是三个模型各自单一作业, 而是一个存在分工、有着协作的融合系统。首先要弄明白这条主要线索, 随后再去看每个模型承担什么职责、为何要进行如此组合, 如此一来就会顺利许多。01 分别聊聊这三个模型可以将时间序列预测, 想成是“去看一条特别长的路”, 然后“判断在前面该如何去走”。仿若一位极为擅长把控大方向的教师, 其深谙如何去识别走势以及季节性特征。举例来讲, 倘若存在一家电商店铺, 在年末时分其销售量将会呈现出上涨态势, 于周末期间流量会有所增高, 那么这种情形格外契合于要率先将这般“周期规律”予以把握。像一个记忆力超强的学生般的LSTM它会记住前面那一串数据彼此之间的关系, 比如说昨天忽然上涨了, 前天同样是处于上涨态势, 依照这样的情况那今天继续上涨的概率便会更高, 它擅长去捕捉那些呈现短期、非线性特点的时序依赖。它如同一个特别擅长进行综合判断的分析员, 它并非直接去看原始序列, 而是去看整理好的特征, 像是“最近7 天均值”, “最近3天最大值”, “是否节假日”, “预测值”, “LSTM预测值”等, 接着借助树模型来做强力组合, 专门对前两个模型尚未彻底理解的部分进行补充。所以, 融合模型的核心逻辑并非是那种“将三个模型生硬地拼凑在一起”的做法, 而是有着明确的分工, 具体是:好比做菜, 有负责底味的部分, 有负责火候的LSTM, 还有负责最后调味的部分。单独吃, 各个部分都能吃, 合起来味道才更香。要是期望更加直观地晓得这三个模型各自所充当的什么角色, 那么能够先瞅一瞅下边的这张分工图示, 其将每个模型“擅长的方面是什么、输入的内容是什么、输出的内容是什么”拆分叙述明白了。在于这张图的价值, 它能够助力我们迅速构建起“谁负责长周期、谁负责短依赖、谁负责最终修正”的认知点。后续当再去看例子以及公式的时候, 就不太容易将三个模型的责任给混淆到一块儿。02 一个通俗例子咱们今儿再来买饮料~假设咱们在观察一个小卖部每天卖多少瓶饮料。发现现在让三个“小帮手”一起预测明天销量第一个帮手它会说“我先看大趋势和星期规律周末要涨夏天要涨。”第二个帮手 LSTM它会这样讲: “我并非仅仅查看周末情况, 还关注意近几日当中的持续变动状况。昨天呈现上涨态势, 今日同样也处于上升之态, 这就表明此种上涨情形仍在持续进行着。”。第三个帮手它会这样讲: “行, 我去把前两个帮手给出的答案拿来, 再结合天气情况、促销活动以及最近7天的平均销量的数据内容, 进行综合的判断分析, 最终给出一个更加稳妥一点的数字。”。比如此128瓶, 并非必然一直为“平均值”, 它乃是依据历史误差学得而来的更为优质的结果。这样呈现的便是融合模型最为直观的那种逻辑, 其中一个承担着看长线的职责, 一个发挥着看短期的作用, 一个履行着做最终裁决的使命。03 核心原理为什么融合比单模型更稳时间序列里最常见的问题是不同模型擅长的东西不一样。的优势是可解释性强能很好拟合如下形式这里这个尤为适用于“趋势 周期”类业务的模型, 像流量, 像销量, 还像负荷。但, 它存在短板, 它在平滑规律方面更具优势, 在处理特别复杂的非线性跳变方面不太擅长, 比如说, 某天骤然进行大力促销, 某段时期规则有所更改, 又或者诸多外部变量产生交叉影响之际, 效果便会受到影响。LSTM的核心优势在于记忆存有对序列的依赖, 它所具备的门控构使它能够留存关键的历史方面信息, 典型公式能够被写成:这里不用怕公式多我给翻译一下它的本质就是 该忘的忘该记的记 。旨在让那“门控记忆”的进程更为直观些, 要再单独瞧一张 LSTM 结构图。可以将其理解为, 先是遗忘门去决定旧信息留存的数量, 跟着是输入门来判定新信息写入的数量, 最终输出门把在当前时刻切实要交出的信息筛选出来。如此便使得, LSTM不仅仅只是做到完全记住历史这么简单, 反而是在有选择性地加以保留真正具备效用的时序线索。因此遇到情况是短期波动, 以及非线性关联, 还有滞后影响的时候, 长短期记忆网络通常比普通回归要强大许多。那属于梯度提升树之代表, 它所为乃是一棵又一棵地去修正误差, 目标函数常常被写成:其中这类模型特别会处理“非线性特征组合”。比如这些信息组合起来 很容易学出一条比单模型更好的修正规则。所以融合方法一般有两种思路1并行融合、LSTM、 都先独立预测然后再做加权平均或者二次学习。2堆叠融合先使得, 让其以及有着“LSTM”之称的事物输出预测所得的值, 而后将它们与另外些特征一块儿给予, 使得去进行最终的融合。就今天这个案例而言, 我们选用第二种会更适配, 鉴于其更具工业实战特性, 先是提出基础预测, 而后使用树模型开展总装配。借助直接去看完整流程图的方式, 以此来将那个“先基础预测、再统一融合”的思路进一步压实一些。把数据准备、建模、LSTM建模、特征拼接、融合以及最终预测输出, 通过这张流程图连接成了一条线, 对此会发现, 真正的工业式融合, 并非是简单平均之事, 而是要把前面模型的预测结果, 也当作“高价值特征”, 持续交给后面的模型来实施学习。接着再深入一步, 要是将单模型跟融合模型放置到一块儿去做比较, 那么差异将会更为显著。从这类对比图当中, 我等通常会关注两点, 其一, 融合之后哒预测曲线是否是更加贴近真实值其二, 误差指标是不是更加稳定, 它并非必定在所有场景之下都绝对最优, 然而, 在那种 “既有趋势、又存在波动、还带有外部因素” 的业务里面, 融合方案往往具备更强哒韧性。04 完整案例倘若我们打算去预测某电商店铺的每日销量, 我们构建一个恰当的数据集, 该数据集涵盖这些字段:数据规律设定成这样这类数据很适合融合模型因为它同时包含import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns np.random.seed(42) n 900 date pd.date_range(start2021-01-01, periodsn, freqD) trend np.linspace(50, 180, n) weekly 12 * np.sin(2 * np.pi * np.arange(n) / 7) yearly 18 * np.sin(2 * np.pi * np.arange(n) / 365) noise np.random.normal(0, 6, n) temp 22 10 * np.sin(2 * np.pi * np.arange(n) / 365) np.random.normal(0, 2, n) promo np.random.binomial(1, 0.18, n) holiday np.random.binomial(1, 0.08, n) sales ( trend weekly yearly 8 * promo - 5 * holiday 0.8 * temp noise ) df pd.DataFrame({ date: date, sales: sales, temp: temp, promo: promo, holiday: holiday }) df.head销量时序图plt.figure(figsize(16, 6)) plt.plot(df[date], df[sales], colordeeppink, linewidth2) plt.title(Virtual Daily Sales Time Series, fontsize16) plt.xlabel(Date) plt.ylabel(Sales) plt.grid(alpha0.3) plt.tight_layout plt.show能直接看到销量随时间的变化有没有明显趋势、波动、尖峰。这个图, 乃是时间序列剖析的第一眼, 极为关键极其重要。若不首先去查看整体的走势面貌情形, 后续模型进行调参之时, 便极易出现偏差偏离正轨跑偏。建模思路输入需要 ds 和 y 两列。from prophet import Prophet prophet_df df[[date, sales]].rename(columns{date: ds, sales: y}) prophet_model Prophet( yearly_seasonalityTrue, weekly_seasonalityTrue, daily_seasonalityFalse ) prophet_model.fit(prophet_df) future prophet_model.make_future_dataframe(periods60) prophet_forecast prophet_model.predict(future)分解图fig1 prophet_model.plot(prophet_forecast) plt.title(Prophet Forecast, fontsize14) plt.show fig2 prophet_model.plot_components(prophet_forecast) plt.show第一张图看整体预测是否平滑是否跟真实走势接近。第二张图看趋势、周周期、年周期拆出来后长什么样。只要是一个存在显著周末效果、节假日效果的业务难题现身之地, 在这里就能够清晰地被看清。构造LSTM输入LSTM需要固定长度窗口。比如用过去 30 天预测今天。from sklearn.preprocessing import MinMaxScaler scaler MinMaxScaler df[sales_scaled] scaler.fit_transform(df[[sales]]) defcreate_sequences(data, seq_len30): X, y , for i in range(len(data) - seq_len): X.append(data[i:iseq_len]) y.append(data[iseq_len]) return np.array(X), np.array(y) seq_len 30 sales_values df[sales_scaled].values.reshape(-1, 1) X_seq, y_seq create_sequences(sales_values, seq_len) X_seq.shape, y_seq.shape用搭LSTMimport torch import torch.nn as nn from torch.utils.data import TensorDataset, DataLoader X_tensor torch.FloatTensor(X_seq) y_tensor torch.FloatTensor(y_seq) dataset TensorDataset(X_tensor, y_tensor) loader DataLoader(dataset, batch_size32, shuffleTrue) classLSTMModel(nn.Module): def__init__(self, input_size1, hidden_size32, num_layers2): super.__init__ self.lstm nn.LSTM(input_size, hidden_size, num_layers, batch_firstTrue) self.fc nn.Linear(hidden_size, 1) defforward(self, x): out, _ self.lstm(x) out out[:, -1, :] out self.fc(out) return out lstm_model LSTMModel criterion nn.MSELoss optimizer torch.optim.Adam(lstm_model.parameters, lr0.001) for epoch in range(15): lstm_model.train total_loss 0 for xb, yb in loader: optimizer.zero_grad pred lstm_model(xb) loss criterion(pred, yb) loss.backward optimizer.step total_loss loss.item print(fEpoch {epoch1}, Loss: {total_loss/len(loader):.6f})真实值 vs LSTM预测值lstm_model.eval with torch.no_grad: lstm_pred lstm_model(X_tensor).numpy lstm_pred_real scaler.inverse_transform(lstm_pred) y_real scaler.inverse_transform(y_seq) plt.figure(figsize(16, 6)) plt.plot(y_real[:300], labelTrue, colorgold, linewidth2) plt.plot(lstm_pred_real[:300], labelLSTM Pred, colorcyan, linewidth2, alpha0.9) plt.title(True vs LSTM Prediction, fontsize16) plt.legend plt.grid(alpha0.3) plt.tight_layout plt.show会直观看出 LSTM 能不能跟住短期波动。要是预测曲线呈现出过于平缓的现象, 这就要表明模型存在欠拟合的状况要是预测曲线抖动得极为厉害, 那就意味着模型的记忆太过零碎或者模型的学习率过高啦。构造特征需要表格特征我们把这些信息整理进去from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, mean_absolute_error from xgboost import XGBRegressor df_model df.copy df_model[lag1] df_model[sales].shift(1) df_model[lag7_mean] df_model[sales].shift(1).rolling(7).mean prophet_pred_full prophet_forecast[[ds, yhat]].rename(columns{ds: date}) df_model df_model.merge(prophet_pred_full, ondate, howleft) lstm_full_pred np.full(len(df_model), np.nan) lstm_full_pred[seq_len:] lstm_pred_real.flatten df_model[lstm_pred] lstm_full_pred df_model df_model.dropna.reset_index(dropTrue) features [temp, promo, holiday, lag1, lag7_mean, yhat, lstm_pred] X df_model[features] y df_model[sales] X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, shuffleFalse) xgb XGBRegressor( n_estimators300, max_depth4, learning_rate0.05, subsample0.9, colsample_bytree0.9, random_state42 ) xgb.fit(X_train, y_train) pred_xgb xgb.predict(X_test)融合模型预测效果plt.figure(figsize(16, 6)) plt.plot(y_test.values, labelTrue, colorlime, linewidth2) plt.plot(pred_xgb, labelXGBoost Fusion Pred, colormagenta, linewidth2) plt.title(Fusion Prediction: True vs XGBoost Output, fontsize16) plt.legend plt.grid(alpha0.3) plt.tight_layout plt.show print(MAE:, mean_absolute_error(y_test, pred_xgb)) print(RMSE:, mean_squared_error(y_test, pred_xgb, squaredFalse))融合后的模型到底有没有比单模型更贴近真实值。要是紫色的线条, 相较于单独的情况, 或者是相较LSTM, 更加贴近绿色的真实线条, 那就表明融合具备有效性。特征重要性importances xgb.feature_importances_ feat_imp pd.DataFrame({feature: features, importance: importances}).sort_values(importance, ascendingFalse) plt.figure(figsize(10, 6)) sns.barplot(datafeat_imp, ximportance, yfeature, paletteturbo) plt.title(XGBoost Feature Importance, fontsize16) plt.tight_layout plt.show可以看出最终模型到底更依赖谁。若 yhat 呈现出较大之值, 且权重处于较高水平, 这便表明某些构建要素连同 LSTM 一同给予了颇具成效的根基。如果 lag1 、 权重高说明历史滞后特征很关键如果 promo 权重高说明促销对销量影响很大。05 这个融合方案实操这里我直接讲实战经验不绕弯子。第一时间序列一定要按时间切分不能乱打乱。有不少人随机切割出来训练集与测试集, 得出的分数似乎很好看看起来成绩貌似十分不错, 然而上线以后却直接遭遇失败成绩严重下滑。时间序列遵循的原则相当简单易懂: 依据过去的情况去预测未来的走向, 在时间顺序排列方面, 训练集一定得处在前面, 测试集必然要在后面跟着。第二更适合给“可解释的基线”。要是业务方对趋势、节假日以及周规律格外在意, 那么先把逻辑讲明白是很相符的。它确实不一定是最强的, 然而它极其适宜当作第一层参考。第三LSTM对数据量和窗口长度很敏感。少数据量致使 LSTM 难以学到内容, 短些的窗口会导致其记不住周期性状况, 长一些的窗口则会让训练速度易于变慢, 通常能够先以 30 天、60 天这般的窗口着手尝试。第四很适合做最终修正。它在结构化特质层面极为适配优越, 特别是“模型施予输出的结果与未作处理的特征以及具有延后情况特色的表征相互组合拼加一处达成形式”, 极为适合用于实行为某种事项。第五评价指标别只看一个。时间序列里常看 MAE、RMSE、MAPE。在业务对于大误差更为惧怕的情形下, 重点关注的是RMSE当业务更加看重平均绝对偏差的时候, 所查看的是MAE要是对相对误差有所关切, 所查看的便是MAPE。总结融合, LSTM的核心, 并非是将三个模型进行简单的叠加, 而是要使它们各自分别去做擅长之事, 即, 抓趋势和周期, LSTM抓时序依赖, 然后做最终修正, 构建出的这样的系统, 一般而言会比单模型更为稳定, 并且也更契合真实业务里那些“既有规律又有波动”的场景。若此刻当下正在开展销量预测, 或者进行流量预测事项, 再有就是着手于能耗预测之事, 甚至在做任何带有时间顺序的数据任务, 此套思路一概都值得去尝试一回。它所具备的价值并不仅仅在于能够提升分数, 更为关键重要是的, 其能使得对于“为什么要如此这般进行预测”拥有一套能够说得出来理由、站得住脚且能落地的逻辑。超硬核学习圈子欢迎加入这里再介绍一下我们的 学习圈子 ~我们目前已经更新的内容有更加详细的介绍可以看 这里 会有更多超级干货带给大家~往期精华硬核学习圈子免费了机器学习小册子最强组合随机森林和融合LSTMARIMA 时序预测你用Codex一把梭把时间序列代码跑通了你用 Codex 跑完 项目就算会了吗导师追着问Codex能帮你学会时间序列建模#cos大壮的机器学习#cos大壮的机器学习实战

相关新闻