在之前的专栏中我们用ARIMA的方法做了时间序列的趋势性预测。

不过我们经常还会遇到一种情况,即某些时间序列中存在明显的周期性变化,这种周期是由于季节性变化(季度、月度等)引起的。

如下图所示,为1949年到1960年每月国际航空公司的乘客人数。从中可以看到明显的季节性,该周期为12个月。

机器学习SARIMA模型架构图 sarima模型定阶_matlab

其中包含了季节性和趋势性

一种适用于描述这类序列的模型称作季节时间序列模型(SARIMA, seasonal ARIMA model),也叫乘积ARIMA模型,因为模型的形式是以相乘的形式表示。

有关于SARIMA的理论知识这里也不展开了,需要了解基础原理的可以看这里(这个文档是付费的,不过免费预览的那段也足够用了)。

假设你已经了解了模型的基本形式,现在开始编程。编程答题思路与ARIMA相同,不过细节处有颇多不同。

1.加载试验数据与参数设置

%% 1.加载数据
load('Data_Airline.mat')   %加载航空公司数据
data = Data(:);            %转为列向量
S = 12;                    %季节性序列变化周期,12个月
figflag = 'on';            %打开画图
step = 48;                 %预测步数

2.确定季节性与非季节性差分数

与ARIMA模型一样,使用SARIMA模型也要求数据平稳。不同的是SARIMA的差分项有两个,分别是季节性差分与非季节性差分。通常季节性差分经过一次即可,非季节性差分通常在0~3之间。

使用下述代码将原始序列进行差分计算,需要注意差分后的序列长度将会缩短。

%% 2.确定季节性与非季节性差分数,D取默认值1,d从0至3循环,平稳后停止
for d = 0:3
    D1 = LagOp({1 -1},'Lags',[0,d]);     %非季节差分项的滞后算子
    D12 = LagOp({1 -1},'Lags',[0,1*S]);  %季节差分项的滞后算子
    D = D1*D12;                          %相乘
    dY = filter(D,data);                 %对原数据进行差分运算
    if(getStatAdfKpss(dY))               %数据平稳
        disp(['非季节性差分数为',num2str(d),',季节性差分数为1']);
        break;
    end
end

上述代码中的getStatAdfKpss为检验数据是否已经平稳的自定义函数,当函数返回1时说明数据已经平稳。

3.确定SARIMA模型阶数

这个步骤中需要确定的阶数有四个:AR阶数p,MA阶数q,SAR阶数P,SMA阶数Q。这里就不贴PCA和FPCA定阶的方法了,而是直接用简单粗暴的暴力定阶(基于AICBIC准则的方法)。

%% 3.确定阶数ARlags,MALags,SARLags,SMALags
max_ar = 3;  %
max_ma = 3;
max_sar = 3;
max_sma = 3;
try
    [AR_Order,MA_Order,SAR_Order,SMA_Order] = SARMA_Order_Select(dY,max_ar,max_ma,max_sar,max_sma,S,d); %自动定阶
catch ME %捕捉错误信息
    msgtext = ME.message;
    if (strcmp(ME.identifier,'econ:arima:estimate:InvalidVarianceModel'))
         msgtext = [msgtext,'  ','无法进行arima模型估计,这可能是由于用于训练的数据长度较小,而要进行拟合的阶数较高导致的,请尝试减小max_ar,max_ma,max_sar,max_sma的值'];
    end
    msgbox(msgtext, '错误')
end
disp(['ARlags=',num2str(AR_Order),',MALags=',num2str(MA_Order),',SARLags=',num2str(SAR_Order),',SMALags=',num2str(SMA_Order)]);

SARMA_Order_Select是我自己写的一个函数,只需要输入信号、最大p值、最大q值、最大P、最大Q、序列周期和差分阶数就可以得到推荐p、q、P、Q。

运行结果为:

ARlags=1,MALags=1,SARLags=1,SMALags=1

即p=1,q=1,P=1,Q=1

4.残差检验

为了确保确定的阶数合适,还需要进行残差检验。残差即原始信号减掉模型拟合出的信号后的残余信号。如果残差是随机正态分布的、不自相关的,这说明残差是一段白噪声信号,也就说明有用的信号已经都被提取到ARMA模型中了。

下述代码中的creatSARIMA是笔者专门写的构建模型的函数,这里的处理方式的不同就是ARMA与SARIMA方法的众多差别的体现。总体来说SARIMA的是更复杂的。

Mdl = creatSARIMA(AR_Order,MA_Order,SAR_Order,SMA_Order,S,d);  %创建SARIMA模型
try
    EstMdl = estimate(Mdl,data);
catch ME %捕捉错误信息
    msgtext = ME.message;
    if (strcmp(ME.identifier,'econ:arima:estimate:InvalidVarianceModel'))
         msgtext = [msgtext,'  ','无法进行arima模型估计,这可能是由于用于训练的数据长度较小,而要进行拟合的阶数较高导致的,请尝试减小max_ar和max_ma的值']
    end
    msgbox(msgtext, '错误')
    return
end
[res,~,logL] = infer(EstMdl,data);   %res即残差

stdr = res/sqrt(EstMdl.Variance);
figure('Name','残差检验','Visible','on')
subplot(2,3,1)
plot(stdr)
title('Standardized Residuals')
subplot(2,3,2)
histogram(stdr,10)
title('Standardized Residuals')
subplot(2,3,3)
autocorr(stdr)
subplot(2,3,4)
parcorr(stdr)
subplot(2,3,5)
qqplot(stdr)

机器学习SARIMA模型架构图 sarima模型定阶_开发语言_02

残差检验

上图为残差检验的结果图。Standardized Residuals是查看残差是否接近正态分布,理想的残差要接近正态分布;ACF和PACF检验残差的自相关和偏自相关,理想的结果应该在图中不存在超出蓝线的点;最后一张QQ图是检验残差是否接近正太分布的,理想的结果中蓝点应该靠近红线。

除了上述图像检验方法,还可以通过Durbin-Watson对相关性进行检验:

% Durbin-Watson 统计是计量经济学分析中最常用的自相关度量
diffRes0 = diff(res);  
SSE0 = res'*res;
DW0 = (diffRes0'*diffRes0)/SSE0 % Durbin-Watson statistic,该值接近2,则可以认为序列不存在一阶相关性。

运算结果为1.9887,这个值越接近2越说明残差不存在一阶相关性。

上述检验可以证明,残差接近正态分布,且相互独立,可以认为ARMA建模符合要求。

5.预测

[forData,YMSE] = forecast(EstMdl,step,data);   %matlab2018及以下版本写为Predict_Y = forecast(EstMdl,step,'Y0',Y);   matlab2019写为Predict_Y = forecast(EstMdl,step,Y);

lower = forData - 1.96*sqrt(YMSE); %95置信区间下限
upper = forData + 1.96*sqrt(YMSE); %95置信区间上限

figure('Visible','on')
plot(data,'Color',[.7,.7,.7]);
hold on
h1 = plot(length(data):length(data)+step,[data(end);lower],'r:','LineWidth',2);
plot(length(data):length(data)+step,[data(end);upper],'r:','LineWidth',2)
h2 = plot(length(data):length(data)+step,[data(end);forData],'k','LineWidth',2);
legend([h1 h2],'95% 置信区间','预测值',...
	     'Location','NorthWest')
title('Forecast')
hold off

直接上结果:

上图中灰线为用来训练的数据,黑线为未来值的预测,红线为95%置信区间上下限。也就是说未来真实值有95%的概率落在这个范围内。

机器学习SARIMA模型架构图 sarima模型定阶_开发语言_03

6.封装

上述整个过程可以封装成一个函数,如下:

function [forData,lower,upper] = Fun_SARIMA_Forecast(data,step,max_ar,max_ma,max_sar,max_sma,S,figflag)
% 使用SARIMA进行预测的函数,可以直接调用,非季节差分阶数自动确定。p,q,P,Q自动确定
% 输入:
% data为待预测数据,一维数据,使用SARIMA时,该数据长度至少为10+S,S为周期长度,但是达到10+S之后仍然可能会报错,可能是由数据的差分处理使得目标数据长度变短导致的。
% step为拟预测步数
% max_ar为AR模型搜寻的最大阶数   建议不大于3
% max_ma为MA模型搜寻的最大阶数   建议不大于3
% max_sar为SAR模型搜寻的最大阶数   建议不大于3
% max_sms为SMA模型搜寻的最大阶数   建议不大于3
% S为季节性周期
% figflag 为画图标志位,'on'为画图,'off'为不画
% 输出:
% forData为预测结果,其长度等于step
% lower为预测结果的95%置信下限值
% upper为预测结果的95%置信上限值

直接调用就可以出结果。

获取文章中全部源码,可以点击下述链接获取:

SARIMA代码说明文档(公开版) | 工具箱文档

SARIMA时间序列预测图形界面版软件(完整版) | 工具箱文档

参考:

MATLAB 文档中心 - MathWorks 中国