使用SARIMA做季節時間序列預測全流程(附MATLAB代碼)

在之前的專欄中我們用ARIMA的方法做了時間序列的趨勢性預測。

不過我們經常還會遇到一種情況,即某些時間序列中存在明顯的週期性變化,這種週期是由於季節性變化(季度、月度等)引起的。

如下圖所示,爲1949年到1960年每月國際航空公司的乘客人數。從中可以看到明顯的季節性,該週期爲12個月。

其中包含了季節性和趨勢性

一種適用於描述這類序列的模型稱作季節時間序列模型(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)

v2-2428304cbb5a6a68e810a57ddddd0fa2_720w.jpg

殘差檢驗

上圖爲殘差檢驗的結果圖。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%的概率落在這個範圍內。

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%置信上限值

直接調用就可以出結果。

獲取文章中全部源碼,可以關注公衆號“括號的城堡”,微信號“khscience”,回覆“季節序列預測”獲取。

 

參考:

MATLAB 文檔中心 - MathWorks 中國

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章