集成時(shí)間序列模型提高預(yù)測(cè)精度

發(fā)布時(shí)間:2023-03-15 12:45:48  |  來源:騰訊網(wǎng)  

使用Catboost從RNN、ARIMA和Prophet模型中提取信號(hào)進(jìn)行預(yù)測(cè)


(資料圖片僅供參考)

集成各種弱學(xué)習(xí)器可以提高預(yù)測(cè)精度,但是如果我們的模型已經(jīng)很強(qiáng)大了,集成學(xué)習(xí)往往也能夠起到錦上添花的作用。流行的機(jī)器學(xué)習(xí)庫scikit-learn提供了一個(gè)StackingRegressor,可以用于時(shí)間序列任務(wù)。但是StackingRegressor有一個(gè)局限性;它只接受其他scikit-learn模型類和api。所以像ARIMA這樣在scikit-learn中不可用的模型,或者來自深度神經(jīng)網(wǎng)絡(luò)的模型都無法使用。在這篇文章中,我將展示如何堆疊我們能見到的模型的預(yù)測(cè)。

我們將用到下面的包:

pip install --upgrade scalecast

conda install tensorflow

conda install shap

conda install -c conda-forge cmdstanpy

pip install prophet

數(shù)據(jù)集

數(shù)據(jù)集每小時(shí)一次,分為訓(xùn)練集(700個(gè)觀測(cè)值)和測(cè)試集(48個(gè)觀測(cè)值)。下面代碼是讀取數(shù)據(jù)并將其存儲(chǔ)在Forecaster對(duì)象中:

import pandas as pd

import numpy as np

from scalecast.Forecaster import Forecaster

from scalecast.util import metrics

import matplotlib.pyplot as plt

import seaborn as sns

def read_data(idx = "H1", cis = True, metrics = ["smape"]):

info = pd.read_csv(

"M4-info.csv",

index_col=0,

parse_dates=["StartingDate"],

dayfirst=True,

)

train = pd.read_csv(

f"Hourly-train.csv",

index_col=0,

).loc[idx]

test = pd.read_csv(

f"Hourly-test.csv",

index_col=0,

).loc[idx]

y = train.values

sd = info.loc[idx,"StartingDate"]

fcst_horizon = info.loc[idx,"Horizon"]

cd = pd.date_range(

start = sd,

freq = "H",

periods = len(y),

)

f = Forecaster(

y = y, # observed values

current_dates = cd, # current dates

future_dates = fcst_horizon, # forecast length

test_length = fcst_horizon, # test-set length

cis = cis, # whether to evaluate intervals for each model

metrics = metrics, # what metrics to evaluate

)

return f, test.values

f, test_set = read_data()

f # display the Forecaster object

結(jié)果是這樣的:

模型

在我們開始構(gòu)建模型之前,我們需要從中生成最簡(jiǎn)單的預(yù)測(cè),naive方法就是向前傳播最近24個(gè)觀測(cè)值。

f.set_estimator("naive")

f.manual_forecast(seasonal=True)

然后使用ARIMA、LSTM和Prophet作為基準(zhǔn)。

ARIMA

Autoregressive Integrated Moving Average 是一種流行而簡(jiǎn)單的時(shí)間序列技術(shù),它利用序列的滯后和誤差以線性方式預(yù)測(cè)其未來。通過EDA,我們確定這個(gè)系列是高度季節(jié)性的。所以最終選擇了應(yīng)用order (5,1,4) x(1,1,1,24)的季節(jié)性ARIMA模型。

f.set_estimator("arima")

f.manual_forecast(

order = (5,1,4),

seasonal_order = (1,1,1,24),

call_me = "manual_arima",

)

LSTM

如果說ARIMA是時(shí)間序列模型中比較簡(jiǎn)單的一種,那么LSTM就是比較先進(jìn)的方法之一。它是一種具有許多參數(shù)的深度學(xué)習(xí)技術(shù),其中包括一種在順序數(shù)據(jù)中發(fā)現(xiàn)長(zhǎng)期和短期模式的機(jī)制,這在理論上使其成為時(shí)間序列的理想選擇。這里使用tensorflow建立這個(gè)模型

f.set_estimator("rnn")

f.manual_forecast(

lags = 48,

layers_struct=[

("LSTM",{"units":100,"activation":"tanh"}),

("LSTM",{"units":100,"activation":"tanh"}),

("LSTM",{"units":100,"activation":"tanh"}),

],

optimizer = "Adam",

epochs = 15,

plot_loss = True,

validation_split=0.2,

call_me = "rnn_tanh_activation",

)

f.manual_forecast(

lags = 48,

layers_struct=[

("LSTM",{"units":100,"activation":"relu"}),

("LSTM",{"units":100,"activation":"relu"}),

("LSTM",{"units":100,"activation":"relu"}),

],

optimizer = "Adam",

epochs = 15,

plot_loss = True,

validation_split=0.2,

call_me = "rnn_relu_activation",

)

Prophet

盡管它非常受歡迎,但有人聲稱它的準(zhǔn)確性并不令人印象深刻,主要是因?yàn)樗鼘?duì)趨勢(shì)的推斷有時(shí)候很不切實(shí)際,而且它沒有通過自回歸建模來考慮局部模式。但是它也有自己的特點(diǎn)。1,它會(huì)自動(dòng)將節(jié)日效果應(yīng)用到模型身上,并且還考慮了幾種類型的季節(jié)性??梢砸杂脩羲璧淖畹托枨髞硗瓿蛇@一切,所以我喜歡把它用作信號(hào),而不是最終的預(yù)測(cè)結(jié)果。

f.set_estimator("prophet")

f.manual_forecast()

比較結(jié)果

現(xiàn)在我們已經(jīng)為每個(gè)模型生成了預(yù)測(cè),讓我們看看它們?cè)隍?yàn)證集上的表現(xiàn)如何,驗(yàn)證集是我們訓(xùn)練集中的最后48個(gè)觀察結(jié)果。

results = f.export(determine_best_by="TestSetSMAPE")

ms = results["model_summaries"]

ms[

[

"ModelNickname",

"TestSetLength",

"TestSetSMAPE",

"InSampleSMAPE",

]

]

每個(gè)模型的表現(xiàn)都優(yōu)于naive方法。ARIMA模型表現(xiàn)最好,百分比誤差為4.7%,其次是Prophet模型。讓我們看看所有的預(yù)測(cè)與驗(yàn)證集的關(guān)系:

f.plot(order_by="TestSetSMAPE",ci=True)

plt.show()

所有這些模型在這個(gè)時(shí)間序列上的表現(xiàn)都很合理,它們之間沒有很大的偏差。下面讓我們把它們堆起來!

堆疊模型

每個(gè)堆疊模型都需要一個(gè)最終估計(jì)器,它將過濾其他模型的各種估計(jì),創(chuàng)建一組新的預(yù)測(cè)。我們將把之前結(jié)果與Catboost估計(jì)器疊加在一起。Catboost是一個(gè)強(qiáng)大的程序,希望它能從每個(gè)已經(jīng)應(yīng)用的模型中充實(shí)出最好的信號(hào)。

f.add_signals(

f.history.keys(), # add signals from all previously evaluated models

)

f.add_ar_terms(48)

f.set_estimator("catboost")

上面的代碼將來自每個(gè)評(píng)估模型的預(yù)測(cè)添加到Forecaster對(duì)象中。它稱這些預(yù)測(cè)為“信號(hào)”。 它們的處理方式與存儲(chǔ)在同一對(duì)象中的任何其他協(xié)變量相同。 這里還添加了最后 48 個(gè)系列的滯后作為 Catboost 模型可以用來進(jìn)行預(yù)測(cè)的附加回歸變量。 現(xiàn)在讓我們調(diào)用三種 Catboost 模型:一種使用所有可用信號(hào)和滯后,一種僅使用信號(hào),一種僅使用滯后。

f.manual_forecast(

Xvars="all",

call_me="catboost_all_reg",

verbose = False,

)

f.manual_forecast(

Xvars=[x for x in f.get_regressor_names() if x.startswith("AR")],

call_me = "catboost_lags_only",

verbose = False,

)

f.manual_forecast(

Xvars=[x for x in f.get_regressor_names() if not x.startswith("AR")],

call_me = "catboost_signals_only",

verbose = False,

)

下面可以比較所有模型的結(jié)果。我們將研究?jī)蓚€(gè)度量:SMAPE和平均絕對(duì)比例誤差(MASE)。這是實(shí)際M4比賽中使用的兩個(gè)指標(biāo)。

test_results = pd.DataFrame(index = f.history.keys(),columns = ["smape","mase"])

for k, v in f.history.items():

test_results.loc[k,["smape","mase"]] = [

metrics.smape(test_set,v["Forecast"]),

metrics.mase(test_set,v["Forecast"],m=24,obs=f.y),

]

test_results.sort_values("smape")

可以看到,通過組合來自不同類型模型的信號(hào)生成了兩個(gè)優(yōu)于其他估計(jì)器的估計(jì)器:使用所有信號(hào)訓(xùn)練的Catboost模型和只使用信號(hào)的Catboost模型。這兩種方法的樣本誤差都在2.8%左右。下面是對(duì)比圖:

fig, ax = plt.subplots(figsize=(12,6))

f.plot(

models = ["catboost_all_reg","catboost_signals_only"],

ci=True,

ax = ax

)

sns.lineplot(

x = f.future_dates,

y = test_set,

ax = ax,

label = "held out actuals",

color = "darkblue",

alpha = .75,

)

plt.show()

哪些信號(hào)最重要?

為了完善分析,我們可以使用shapley評(píng)分來確定哪些信號(hào)是最重要的。Shapley評(píng)分被認(rèn)為是確定給定機(jī)器學(xué)習(xí)模型中輸入的預(yù)測(cè)能力的最先進(jìn)的方法之一。得分越高,意味著輸入在特定模型中越重要。

f.export_feature_importance("catboost_all_reg")

上面的圖只顯示了前幾個(gè)最重要的預(yù)測(cè)因子,但我們可以從中看出,ARIMA信號(hào)是最重要的,其次是序列的第一個(gè)滯后,然后是Prophet。RNN模型的得分也高于許多滯后模型。如果我們想在未來訓(xùn)練一個(gè)更輕量的模型,這可能是一個(gè)很好的起點(diǎn)。

總結(jié)

在這篇文章中,我展示了在時(shí)間序列上下文中集成模型的力量,以及如何使用不同的模型在時(shí)間序列上獲得更高的精度。這里我們使用scalecast包,這個(gè)包的功能還是很強(qiáng)大的,如果你喜歡,可以去它的主頁看看:https://github.com/mikekeith52/scalecast

本文的數(shù)據(jù)集是M4的時(shí)序競(jìng)賽:https://github.com/Mcompetitions/M4-methods

使用代碼在這里:https://scalecast-examples.readthedocs.io/en/latest/misc/stacking/custom_stacking.html

作者:Michael Keith

關(guān)鍵詞:

 

網(wǎng)站介紹  |  版權(quán)說明  |  聯(lián)系我們  |  網(wǎng)站地圖 

星際派備案號(hào):京ICP備2022016840號(hào)-16 營(yíng)業(yè)執(zhí)照公示信息版權(quán)所有 郵箱聯(lián)系:920 891 263@qq.com