应用 Catboost 从 RNN、ARIMA 和 Prophet 模型中提取信号进行预测
集成各种弱学习器能够进步预测精度,然而如果咱们的模型曾经很弱小了,集成学习往往也可能起到精益求精的作用。风行的机器学习库 scikit-learn 提供了一个 StackingRegressor,能够用于工夫序列工作。然而 StackingRegressor 有一个局限性; 它只承受其余 scikit-learn 模型类和 api。所以像 ARIMA 这样在 scikit-learn 中不可用的模型,或者来自深度神经网络的模型都无奈应用。在这篇文章中,我将展现如何重叠咱们能见到的模型的预测。
咱们将用到上面的包:
pip install --upgrade scalecast
conda install tensorflow
conda install shap
conda install -c conda-forge cmdstanpy
pip install prophet
数据集
数据集每小时一次,分为训练集 (700 个观测值) 和测试集(48 个观测值)。上面代码是读取数据并将其存储在 Forecaster 对象中:
importpandasaspd
importnumpyasnp
fromscalecast.ForecasterimportForecaster
fromscalecast.utilimportmetrics
importmatplotlib.pyplotasplt
importseabornassns
defread_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
)
returnf, test.values
f, test_set=read_data()
f# display the Forecaster object
后果是这样的:
模型
在咱们开始构建模型之前,咱们须要从中生成最简略的预测,naive 办法就是向前流传最近 24 个观测值。
f.set_estimator('naive')
f.manual_forecast(seasonal=True)
而后应用 ARIMA、LSTM 和 Prophet 作为基准。
ARIMA
Autoregressive Integrated Moving Average 是一种风行而简略的工夫序列技术,它利用序列的滞后和误差以线性形式预测其将来。通过 EDA,咱们确定这个系列是高度季节性的。所以最终抉择了利用 order (5,1,4) x(1,1,1,24)的季节性 ARIMA 模型。
f.set_estimator('arima')
f.manual_forecast(order = (5,1,4),
seasonal_order = (1,1,1,24),
call_me = 'manual_arima',
)
LSTM
如果说 ARIMA 是工夫序列模型中比较简单的一种,那么 LSTM 就是比拟先进的办法之一。它是一种具备许多参数的深度学习技术,其中包含一种在程序数据中发现长期和短期模式的机制,这在实践上使其成为工夫序列的现实抉择。这里应用 tensorflow 建设这个模型
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
只管它十分受欢迎,但有人宣称它的准确性并不令人印象粗浅,次要是因为它对趋势的推断有时候很不切实际,而且它没有通过自回归建模来思考部分模式。然而它也有本人的特点。1,它会主动将节日成果利用到模型身上,并且还思考了几种类型的季节性。能够以用户所需的最低需要来实现这所有,所以我喜爱把它用作信号,而不是最终的预测后果。
f.set_estimator('prophet')
f.manual_forecast()
比拟后果
当初咱们曾经为每个模型生成了预测,让咱们看看它们在验证集上的体现如何,验证集是咱们训练集中的最初 48 个察看后果。
results=f.export(determine_best_by='TestSetSMAPE')
ms=results['model_summaries']
ms[
[
'ModelNickname',
'TestSetLength',
'TestSetSMAPE',
'InSampleSMAPE',
]
]
每个模型的体现都优于 naive 办法。ARIMA 模型体现最好,百分比误差为 4.7%,其次是 Prophet 模型。让咱们看看所有的预测与验证集的关系:
f.plot(order_by="TestSetSMAPE",ci=True)
plt.show()
所有这些模型在这个工夫序列上的体现都很正当,它们之间没有很大的偏差。上面让咱们把它们堆起来!
重叠模型
每个重叠模型都须要一个最终预计器,它将过滤其余模型的各种预计,创立一组新的预测。咱们将把之前后果与 Catboost 预计器叠加在一起。Catboost 是一个弱小的程序,心愿它能从每个曾经利用的模型中空虚出最好的信号。
f.add_signals(f.history.keys(), # add signals from all previously evaluated models
)
f.add_ar_terms(48)
f.set_estimator('catboost')
下面的代码将来自每个评估模型的预测增加到 Forecaster 对象中。它称这些预测为“信号”。它们的解决形式与存储在同一对象中的任何其余协变量雷同。这里还增加了最初 48 个系列的滞后作为 Catboost 模型能够用来进行预测的附加回归变量。当初让咱们调用三种 Catboost 模型:一种应用所有可用信号和滞后,一种仅应用信号,一种仅应用滞后。
f.manual_forecast(
Xvars='all',
call_me='catboost_all_reg',
verbose=False,
)
f.manual_forecast(Xvars=[xforxinf.get_regressor_names() ifx.startswith('AR')],
call_me='catboost_lags_only',
verbose=False,
)
f.manual_forecast(Xvars=[xforxinf.get_regressor_names() ifnotx.startswith('AR')],
call_me='catboost_signals_only',
verbose=False,
)
上面能够比拟所有模型的后果。咱们将钻研两个度量:SMAPE 和均匀相对比例误差(MASE)。这是理论 M4 较量中应用的两个指标。
test_results=pd.DataFrame(index=f.history.keys(),columns= ['smape','mase'])
fork, vinf.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')
能够看到,通过组合来自不同类型模型的信号生成了两个优于其余预计器的预计器: 应用所有信号训练的 Catboost 模型和只应用信号的 Catboost 模型。这两种办法的样本误差都在 2.8% 左右。上面是比照图:
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()
哪些信号最重要?
为了欠缺剖析,咱们能够应用 shapley 评分来确定哪些信号是最重要的。Shapley 评分被认为是确定给定机器学习模型中输出的预测能力的最先进的办法之一。得分越高,意味着输出在特定模型中越重要。
f.export_feature_importance('catboost_all_reg')
下面的图只显示了前几个最重要的预测因子,但咱们能够从中看出,ARIMA 信号是最重要的,其次是序列的第一个滞后,而后是 Prophet。RNN 模型的得分也高于许多滞后模型。如果咱们想在将来训练一个更轻量的模型,这可能是一个很好的终点。
总结
在这篇文章中,我展现了在工夫序列上下文中集成模型的力量,以及如何应用不同的模型在工夫序列上取得更高的精度。这里咱们应用 scalecast 包,这个包的性能还是很弱小的,如果你喜爱,能够去它的主页看看:
https://avoid.overfit.cn/post/cd910a41e6b94852b762cd6f2abf8b16
作者:Michael Keith