机器学习多步时间序列预测解决方案
點擊上方入口立即【自由構建 探索無限】
一起共赴年度科技盛宴!
1
簡介
近年來,隨著機器學習與深度學習的發展,以及 Amazon SageMaker
(https://aws.amazon.com/cn/sagemaker/)等機器學習平臺的成熟,數據科學家們不再需要關心底層的基礎設施及構建復雜的訓練與推理環境,從而可以把主要的時間與精力放在數據與算法本身。在機器學習變得更容易的今天,越來越多的傳統行業已經開始使用機器學習算法來解決現實中的問題,降低成本及提升效率。在能源、制造及零售快消等傳統行業中,多步回歸預測任務是較為常見的業務場景之一。
例如:您是一家超市的經理,想要預測未來幾周的銷售情況,并且已經獲得了數百種產品的每日銷售歷史數據。您將面臨的問題是什么樣的?
時間序列預測(如 ARIMA, Exponential Smoothing 等)可能會很自然地出現在您的腦海中。使用此類算法,您可以將產品的銷量作為單獨的時間序列,并根據其歷史銷量來推算其未來的銷售額。
然而,您可能會發現每個產品的銷售并非獨立的,它們之間或許存在著某種依賴性。例如,在夏天時,空調的銷量會增加,同時羽絨服的銷量會下降。當存在著多個變量時,我們就需要使用多變量時間序列預測(multi-variable time series forecasting)來處理變量間的相關性。
此外,您希望的是預測未來幾周的銷售情況,而非僅僅預測明天的銷量,因此,需要的是預測未來的多個時間步驟。這種預測未來的多個時間步長的任務被稱為多步時間序列預測(multi-step time series forecasting)。多步時間序列預測通常有四種主要的方法:
多步遞歸預測(recursive multi-step forecasting)
多步直接預測(direct multi-step forecasting)
直接&遞歸融合預測(direct-recursive hybrid forecasting)
多輸出預測(multiple output forecasting)
下面我們會分別講解這4種方法的原理,對比他們的性能,并在 SageMaker Notebook 中實現它們。可以在命令行執行下列命令,下載相關代碼及數據集。
git?clone?https://github.com/aws-samples/multi-step-forecasting-blog-sample-code左滑查看更多
2
多步遞歸預測
(recursive multi-step?
forecasting)
多步遞歸預測在單步預測的基礎上,把下一步的預測值作為輸入,來進行迭代預測。需要注意的是:在多變量的多步回歸分析中,由于存在外部變量作為輸入,需要同時預測外部變量。多步遞歸的過程如下圖所示:
優點:
需要的模型數量固定
計算量較低
預測的偏差(bias)相對于多步直接預測(后面會講到)較低
缺點:
由于使用上一步的預測值作為輸入,預測誤差會隨著時間傳遞擴大,預測的方差(variance)較高
下面我們結合多變量回歸分析,來實現多步遞歸預測。數據集
(https://aws.amazon.com/cn/blogs/china/machine-learning-multi-step-time-series-prediction-solution/)
使用 Wage Growth and the Inflation Process: An Empirical Approach 論文中的公開數據集,涵蓋1959年 Q1 至1988年 Q4 的工資數據。數據集共有123行和8列,列的定義:
rgnp : 預測目標,實際 GNP(gross national product,國民生產總值)
pgnp : 潛在 GNP
ulc : 單位勞動成本
gdfco : 不包括食物和能源在內的個人消費支出的固定權重平減指數
gdf : 固定重量 GNP 縮減指數
gdfim : 定量進口減縮指數
gdfcf : 個人消費支出中食品的固定重量平減指數
gdfce : 個人消費支出中能量的固定權重平減指數
在進行建模前,我們先查看一下每個變量的走勢,可以看到8個變量均為向上趨勢,各個變量間有一定相關性。此外,可以看到數據沒有季節性(seasonality),因此,我們在后續的建模過程中未加入季節性相關的處理。
在編寫代碼前,首先需要在 Amazon console 中創建 SageMaker Notebook,并運行下列 cell 安裝所需的庫。
!?pip?install?lightgbm我們的預測目標是 rgnp,也就是實際的國民生產總值。我們希望預測未來一年,也就是12個月中,每個月的國民生產總值。接下來,讓我們進入代碼部分。我們的代碼使用的基礎模型是 LightGBM,您也可以根據自己的需求選擇其他任何回歸算法。
首先,加載數據集:
import?pandas?as?pd import?numpy?as?np import?lightgbm?as?lgb from?sklearn.metrics?import?mean_squared_error from?sklearn.multioutput?import?MultiOutputRegressordf?=?pd.read_csv('Raotbl6.csv')#?將date作為索引 df['date']?=?pd.to_datetime(df['date']) df.index?=?df['date'] df.drop('date',?axis=1,?inplace=True) 以?8:2?來分割訓練集與測試集 target?=?'rgnp'X_train?=?df[:?int(len(df)?*?0.8)] y_train?=?df[:?int(len(df)?*?0.8)]X_test?=?df[int(len(df)?*?0.8)?:] y_test?=?df[int(len(df)?*?0.8)?:]左滑查看更多
構建模型,由于迭代預測需要知道全部變量未來的值,因此模型除了預測目標變量,還要預測每一個變量。
MultiOutputRegressor 使用相同的 feature 來預測多個目標,通過該對象,可以針對每個目標訓練出一個回歸器。
model?=?MultiOutputRegressor(lgb.LGBMRegressor(objective='regression')).fit(X_train,?y_train)左滑查看更多
迭代預測,每次預測全部變量的未來值,共預測12次(一年)。
results?=?[] data?=?X_test for?i?in?range(12):data?=?pd.DataFrame(model.predict(data),?columns=data.columns,?index=data.index)results.append(data) 接下來,我們看一下預測結果,我們以MAE(mean average error)作為評價標準。 #?make?future?targets for?i?in?range(12):df['rgnp_{}'.format(i)]?=?df['rgnp'].shift(-i)df.dropna(inplace=True) df.drop('rgnp',?axis=1,?inplace=True)targets?=?[item?for?item?in?df.columns?if?'rgnp'?in?item]X_train?=?df.drop(targets,?axis=1)[:?int(len(df)?*?0.8)] y_train?=?df[targets][:?int(len(df)?*?0.8)]X_test?=?df.drop(targets,?axis=1)[int(len(df)?*?0.8)?:] y_test?=?df[targets][int(len(df)?*?0.8)?:](y_test?-?pred).abs().mean()左滑查看更多
我們可以看到,隨著預測距離逐漸變遠,我們的預測準確率會變得越來越低。這個結果也是合理的,因為預測誤差會不斷向后傳遞。
3
多步直接預測
(direct multi-step?
forecasting)
多步直接預測的邏輯是訓練多個模型,每個模型負責預測未來一個時間步的值。
優點:
與遞歸預測相比,由于不會誤差傳遞,預測方差(variance)更低
缺點:
預測較多時間步時,計算效率低(需要預測多少時間步,就需要訓練多少個模型)
與遞歸預測相比,預測偏差(bias)較高,因為較遠的目標無法獲取與其相近的數據
接下來,我們在同樣的數據集上使用直接預測來進行多步時間序列分析。
使用同樣的方法來加載數據:
import?pandas?as?pd import?numpy?as?np import?lightgbm?as?lgb from?sklearn.metrics?import?mean_squared_error from?sklearn.multioutput?import?MultiOutputRegressordf?=?pd.read_csv('Raotbl6.csv') df['date']?=?pd.to_datetime(df['date']) df.index?=?df['date'] df.drop('date',?axis=1,?inplace=True) 為每個未來的時間步創建一列 #?make?future?targets for?i?in?range(12):df['rgnp_{}'.format(i)]?=?df['rgnp'].shift(-i-1)df.dropna(inplace=True)左滑查看更多
分割訓練集與測試集:
targets?=?[item?for?item?in?df.columns?if?'rgnp_'?in?item]X_train?=?df.drop(targets,?axis=1)[:?int(len(df)?*?0.8)] y_train?=?df[targets][:?int(len(df)?*?0.8)]X_test?=?df.drop(targets,?axis=1)[int(len(df)?*?0.8)?:] y_test?=?df[targets][int(len(df)?*?0.8)?:]model?=?MultiOutputRegressor(lgb.LGBMRegressor(objective='regression')).fit(X_train,?y_train)左滑查看更多
查看預測結果:
pred?=?pd.DataFrame(model.predict(X_test),?columns=targets) pred.index?=?y_test.index (y_test?-?pred).abs().mean()左滑查看更多
我們可以看到,預測的誤差也是隨著時間步的拉遠變大,但與遞歸預測相比,誤差的損失變得更小了。這是直接預測算法的優越性,由于 variance 更低,預測遠距離時間步會更準確。
4
多步直接&遞歸融合預測
(direct-recursive hybrid?
forecasting)
多步遞歸預測與多步直接預測各有千秋,遞歸預測的 bias 低,但 variance 高。而直接預測則是 variance 低,但 bias 高。
那么是否有一種方法可以結合兩者呢?答案是肯定的,這種方法叫做直接&遞歸融合預測。
直接&遞歸融合預測的具體實施方法有很多種,下面我們以其中一種方法舉例:
1.創建遞歸模型
2.創建直接預測模型,但預測模型的輸入還包括遞歸模型在先前時間步中所做的預測作為輸入值
優點:
結合直接預測來在一定程度上避免誤差傳播,降低了預測方差(variance)
結合遞歸預測,擁有較低的預測偏差(bias)
缺點:
計算量比前面兩種方法更大
實現復雜度較高
同樣的,我們先加載數據集:
import?pandas?as?pd import?numpy?as?np import?lightgbm?as?lgb from?sklearn.metrics?import?mean_squared_error from?sklearn.multioutput?import?MultiOutputRegressordf?=?pd.read_csv('Raotbl6.csv') df['date']?=?pd.to_datetime(df['date']) df.index?=?df['date'] df.drop('date',?axis=1,?inplace=True)左滑查看更多
訓練遞歸模型:
target?=?'rgnp'X_train?=?df[:?int(len(df)?*?0.8)].iloc[:-1] y_train?=?df[:?int(len(df)?*?0.8)].shift(-1).dropna()X_test?=?df[int(len(df)?*?0.8)?:].iloc[:-1] y_test?=?df[int(len(df)?*?0.8)?:].shift(-1).dropna()model?=?MultiOutputRegressor(lgb.LGBMRegressor(objective='regression')).fit(X_train,?y_train)左滑查看更多
取得遞歸模型的預測結果:
results?=?[] data?=?X_test for?i?in?range(12):data?=?pd.DataFrame(model.predict(data),?columns=data.columns,?index=data.index)results.append(data)左滑查看更多
為直接模型構建基礎特征:
#?make?future?targets? for?i?in?range(12):df['rgnp_{}'.format(i+1)]?=?df['rgnp'].shift(-i-1)df.dropna(inplace=True)targets?=?[item?for?item?in?df.columns?if?'rgnp_'?in?item]X_train?=?df.drop(targets,?axis=1)[:?int(len(df)?*?0.8)] y_train?=?df[targets][:?int(len(df)?*?0.8)]X_test?=?df.drop(targets,?axis=1)[int(len(df)?*?0.8)?:] y_test?=?df[targets][int(len(df)?*?0.8)?:]左滑查看更多
訓練直接模型,每次把上一步的遞歸模型的預測值也作為特征來訓練模型。
models?=?[] for?i?in?range(1,?13):model?=?lgb.LGBMRegressor(objective='regression').fit(X_train,?y_train['rgnp_{}'.format(i)])X_train['rgnp_{}'.format(i)]?=?y_train['rgnp_{}'.format(i)]models.append(model)左滑查看更多
使用直接模型來做預測:
final_results?=?[]for?i?in?range(12):final_results.append(models[i].predict(X_test))X_test['rgnp_{}'.format(i?+?1)]?=?results[i]['rgnp']左滑查看更多
我們可以看到,遞歸&直接預測融合模型的誤差要低于遞歸預測或直接預測的模型。當然,基于 no free lunch 原則,我們無法完全確定融合方法要好于單獨方法。
5
多輸出預測
(multiple output?forecasting)
前面3種方法中,我們可以計算出輸入間的相關性,但無法計算輸出間的相關性。而多輸出預測,則是使用一個神經網絡模型預測整個預測序列,每個權重對每個輸出都有影響,因此模型會同時學習到輸入與輸出的相關性。
優點:
不會有誤差傳遞風險
同時學習多個輸出,能夠找到每個時間步的關聯
由于神經網絡的特殊性,對特征工程能力的要求較低
缺點:
計算量過大
只能使用神經網絡,不能使用 tree-based 模型
會有過擬合的風險,需要較多數據
接下來以 PyTorch 為例,來進行預測。本案例使用 SageMaker Notebook 的 conda_pytorch_p38 kernel,無需自行安裝 PyTorch 庫。
import?pandas?as?pdimport?torch import?torch.nn?as?nn from?torch.utils.data?import?Dataset,?DataLoader import?torch.optim?as?optimimport?pandas?as?pd import?numpy?as?np import?lightgbm?as?lgb from?sklearn.metrics?import?mean_squared_errordf?=?pd.read_csv('Raotbl6.csv') df['date']?=?pd.to_datetime(df['date']) df.index?=?df['date'] df.drop('date',?axis=1,?inplace=True)#?make?future?targets for?i?in?range(12):df['rgnp_{}'.format(i)]?=?df['rgnp'].shift(-i-1)df.dropna(inplace=True)targets?=?[item?for?item?in?df.columns?if?'rgnp_'?in?item]X_train?=?df.drop(targets,?axis=1)[:?int(len(df)?*?0.8)] y_train?=?df[targets][:?int(len(df)?*?0.8)]X_test?=?df.drop(targets,?axis=1)[int(len(df)?*?0.8)?:] y_test?=?df[targets][int(len(df)?*?0.8)?:]左滑查看更多
構建數據集類,用于訓練數據。
class?Raotbl6Dataset(Dataset):"""Face?Landmarks?dataset."""def?__init__(self,?X_train,?y_train):self.X_train?=?X_trainself.y_train?=?y_traindef?__len__(self):return?len(self.X_train)def?__getitem__(self,?idx):if?torch.is_tensor(idx):idx?=?idx.tolist()X?=?torch.Tensor(self.X_train.iloc[idx].values)y?=?torch.Tensor(self.y_train.iloc[idx].values)return?X,?y左滑查看更多
構建模型類,由于數據集非常小,所以只使用一個隱含層的神經網絡。
class?Model(nn.Module):def?__init__(self,?in_feats,?out_feats=12,?hidden_units=32):super(Model,?self).__init__()self.net?=?nn.Sequential(nn.Linear(in_feats,?hidden_units),nn.ReLU(),nn.Linear(hidden_units,?out_feats))def?forward(self,?x):return?self.net(x)左滑查看更多
訓練模型,由于數據集的數據量太少,因此訓練500輪來盡量提升模型性能。
NUM_EPOCHS?=?500 LEARNING_RATE?=?2e-4 device?=?'cuda'?if?torch.cuda.is_available()?else?'cpu'dataset?=?Raotbl6Dataset(X_train,?y_train) dataloader?=?DataLoader(dataset,batch_size=32,?shuffle=True) criterion?=?torch.nn.?MSELoss()model?=?Model(8).to(device) opt?=?optim.Adam(model.parameters(),?lr=LEARNING_RATE,?betas=(0.5,?0.999))for?epoch?in?range(NUM_EPOCHS):model.train()for?batch_idx,?(X,?y)?in?enumerate(dataloader):X,?y?=?X.to(device),?y.to(device)pred?=?model(X)loss?=?criterion(y,?pred)model.zero_grad()loss.backward()opt.step()print(f"Epoch?[{epoch}/{NUM_EPOCHS}]?\ERROR:?{loss:.4f}")pred?=?pd.DataFrame(model(torch.Tensor(X_test.values).to(device)),?columns=y_test.columns,?index=y_test.index (y_test?-?pred).abs().mean()左滑查看更多
可以看到,由于神經網絡足夠簡單,即使只有100條數據并訓練了500輪,也并沒有過擬合,它的性能也超過前面3種方法較多,這其中也與前面3種方法沒有花費時間調參有關。
6
總結
本篇文章中,我們展示了4種基于機器學習進行多步時間序列預測的方法。下列表格中分別列出了各個算法的優缺點。
多步時間序列預測問題在傳統行業中尤為常見,很多亞馬遜云科技的客戶面臨類似問題。在機器學習任務中,除了構建模型外,還需關注后續模型在實際使用中的表現,并定期更新及優化。Amazon SageMaker 提供了完整的模型訓練、部署及監控工作流,可大幅度降低機器學習開發難度。此外,在一些常見的業務場景下,也可以利用 Amazon?SageMaker Canvas?或 Amazon Forecast?等工具來基于 UI 進行建模,不需要關心算法本身的同時還能得到不錯的效果。
亞馬遜云科技專業技術服務團隊旨在為客戶提供基于亞馬遜云科技的專業咨詢服務,種類包括業務創新、遷移、關鍵業務應用上云、云原生架構和微服務改造、大數據、機器學習、DevOps、容災、安全等,以強大的亞馬遜云科技云服務幫助企業客戶完成云端遷移。其中,隸屬于專業技術服務團隊下的機器學習團隊具有豐富的人工智能行業解決經驗,可在為客戶提供亞馬遜云科技云上 AI 模型開發方面的咨詢。
Amazon SageMaker Canvas:
https://aws.amazon.com/cn/sagemaker/canvas/
Amazon Forecast :
https://aws.amazon.com/cn/forecast/
專業技術服務團隊:
https://aws.amazon.com/cn/professional-services/
本篇作者
劉明
亞馬遜云科技專業服務團隊數據科學家。在機器學習、深度學習、數據挖掘及模型部署開發擁有扎實經驗。深度參與過能源、醫療、教育、媒體等行業的機器學習應用搭建及數據平臺建設。
陳恒智
亞馬遜云科技專業服務團隊數據科學家。
王畇
亞馬遜云科技專業服務團隊助理數據科學家。在傳統機器學習、計算機視覺、強化學習以及數據分析領域擁有多年經驗,深度參與過生物識別、智慧供熱等多個不同行業的人工智能項目,擁有豐富的實戰經驗。
點擊上方【立即報名】
直通大咖云集的亞馬遜云科技中國峰會!
聽說,點完下面4個按鈕
就不會碰到bug了!
總結
以上是生活随笔為你收集整理的机器学习多步时间序列预测解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JAVA-日期类(Date、Simple
- 下一篇: linux d14 Apache、 Vs