在本篇中,我們將展式使用 Python 統計學模型進行時間序列數據分析。
** 問題描述 **
目標:根據兩年以上的每日廣告支出歷史數據,提前預測兩個月的廣告支出金額。
原始數據:2017-01-01 到 2019-09-23 期間的每日廣告支出。
數據準備:劃分訓練集和測試集。
df1 = data[['Date','Spend']].set_index('Date')train = df1.iloc[:933,:]test = df1.iloc[933:,:]test.shape,train.shape
測試集大小:(63,1);訓練集大小:(933,1)。
本文目錄
綜述時間序列分析常用統計模型單變量時間序列數據建模的關鍵要素ARIMAACF 和 PACFSARIMA案例:通過 SARIMA 預測廣告支出ETSETSHolt-Winter 季節性預測算法案例:通過 Holt-Winter 季節性預測算法預測廣告支出算法對比結束語綜述
時間序列分析常用統計模型
單變量時間序列統計學模型,如:平均方法、平滑方法、有/無季節性條件的 ARIMA 模型。多變量時間序列統計學模型,如:外生回歸變量、VAR。附加或組件模型,如:Facebook Prophet、ETS。結構化時間序列模型,如:貝葉斯結構化時間序列模型、分層時間序列模型。在本篇文章中,我們主要關注 SARIMA 和 Holt-winters 方法。
單變量時間序列統計學模型的關鍵要素
如果我們想要對時間序列數據進行上述統計學模型分析,需要進行一系列處理使得:(1)數據均值(2)數據方差 (3)數據自協方差 這三個指標不依賴於時間項。即時間序列數據具有平穩性。
如何明確時間序列數據是否具有平穩性?可以從兩個特徵進行判斷。(1) 趨勢,即均值隨時間變化;(2) 季節性,即方差隨時間變化、自協方差隨時間變化。若滿足以上兩個條件,則時間序列數據不符合平穩性要求。
可以通過以下方法消除上述問題:
變換,如:取對數、取平方等。平滑處理,如:移動平均等。差分。分解。多項式擬合,如:擬合回歸。ARIMA
Autoregressive Integrated Moving Average model (ARIMA),差分整合移動平均自回歸模型。ARIMA(p,d,q)主要包含三項:
p:AR項,即自回歸項(autoregression),將時間序列下一階段描述為前一階段數據的線性映射。 d項,即積分項(integration),時間序列的差分預處理步驟,使其滿足平穩性要求 q:MA項,即移動平均項(moving average),將時間序列下一階段描述為前一階段數據平均過程中的殘留誤差的線性映射。
該模型需要指定 p d q 三項參數,並按照順序執行。ARIMA 模型也可以用於開發 AR, MA 和 ARMA 模型。
ACF 和 PACF 圖
自相關函數,autocorrelation function(ACF),描述了時間序列數據與其之後版本的相關性(如:Y(t) 與 Y(t-1) 之間的相關性)。
偏自相關函數,partial autocorrelation function(PACF),描述了各個序列的相關性。
通過 PACF 圖可以確定 p通過 ACF 圖可以確定 qSARIMA
季節性差分自回歸滑動平均模型,seasonal autoregressive integrated moving averaging(SARIMA),在 ARIMA 模型的基礎上進行了季節性調節。
其形式為:SARIMA(p,d,q)(P,D,Q)s,其中P,D,Q為季節參數,s為時間序列周期。
案例:通過 SARIMA 預測廣告支出
首先,我們建立 test_stationarity 來檢查時間序列數據的平穩性。
from statsmodels.tsa.stattools import adfullerdf1=df.resample('D', how=np.mean)def test_stationarity(timeseries):rolmean = timeseries.rolling(window=30).mean() rolstd = timeseries.rolling(window=30).std() plt.figure(figsize=(14,5)) sns.despine(left=True) orig = plt.plot(timeseries, color='blue',label='Original') mean = plt.plot(rolmean, color='red', label='Rolling Mean') std = plt.plot(rolstd, color='black', label = 'Rolling Std') plt.legend(loc='best'); plt.title('Rolling Mean & Standard Deviation') plt.show() print ('<Results of Dickey-Fuller Test>') dftest = adfuller(timeseries, autolag='AIC') dfoutput = pd.Series(dftest[0:4], index=['Test Statistic','p-value','#Lags Used','Number of Observations Used']) for key,value in dftest[4].items(): dfoutput['Critical Value (%s)'%key] = value print(dfoutput)test_stationarity(df1.Spend.dropna())
通過 test_stationarity 函數,可以繪製移動平均值以及標準差,並且通過 Augmented Dickey-Fuller test 輸出 P 值。
對比臨界值(critical value)可以看到,時間序列數據時非平穩的。
首先我們試試對數變換,能不能使數據達到平穩性要求。
可以看到,利用對數變換df1[『log_Spend』]=np.log(df1[『Spend』]),時間序列在閾值為5%時滿足平穩性要求。
接下來,我們試試差分操作:test_stationarity(df1[『Spend』].diff(1).dropna())。
顯然,通過差分操作後,效果更好,時間序列在閾值為1%時滿足平穩性要求。
然後,我們就可以建立 SARIMA 模型,並且預測 2019-07-23 到 2019-09-23 這兩個月間每天的廣告指出。
import statsmodels.api as smfit1 = sm.tsa.statespace.SARIMAX(train.Spend, order=(7, 1, 2), seasonal_order=(0, 1, 2, 7)).fit(use_boxcox=True)test['SARIMA'] = fit1.predict(start="2019-07-23", end="2019-09-23", dynamic=True)plt.figure(figsize=(16, 8))plt.plot(train['Spend'], label='Train')plt.plot(test['Spend'], label='Test')plt.plot(test['SARIMA'], label='SARIMA')plt.legend(loc='best')plt.show()
現在,讓我們通過從sklearn.metrics包導入mean_squared_error,mean_absolute_error函數計算mse和mae來檢查這個模型的性能。結果如下:
進行數據可視化:
從 mse、mae 以及預測曲線可以看出,SARIMA 模型成功預測了時間序列變化趨勢和季節性特徵。但是在峰值處的表現仍舊有待提高。
ETS
ETS,Exponential Smoothing
由於時間序列數據隨時間變化但具有一定的隨機性,我們通常希望對數據進行平滑處理。為此,我們將使用 ETS 技術,通過指數方法為過去的數據分配較少的權重。同時將時間序列數據分解為趨勢(T)、季節(S)和誤差(E)分量。
三種常用 ETS 方法如下:
Linear:雙指數平滑;Additive:三指數平滑;Multiplicative:三指數平滑。
Holt-Winter 季節性預測算法
Holt-winter 季節性預測算法是一種三指數平滑方法。它包含三個主要部分:水平、趨勢、季節性分量。
案例:通過 Holt-Winter 季節性預測算法預測廣告支出
通過 Holt-winter 季節性預測算法預測 2019-07-23 到 2019-09-23 期間的每日廣告支出,代碼如下:
from statsmodels.tsa.api import ExponentialSmoothingfit1 = ExponentialSmoothing(np.asarray(train['Spend']) ,seasonal_periods=7 ,trend='add', seasonal='add').fit(use_boxcox=True)test['Holt_Winter'] = fit1.forecast(len(test))plt.figure(figsize=(16,8))plt.plot( train['Spend'], label='Train')plt.plot(test['Spend'], label='Test')plt.plot(test['Holt_Winter'], label='Holt_Winter')plt.legend(loc='best')plt.show()
同樣,我們通過 mean_squared_error,mean_absolute_error 函數查看 mse 和 mae。
可以看到,H-W 模型同樣能夠預測時間序列變化趨勢和季節性特徵。
算法對比
通過將兩種算法的預測結果進行對比,可以評價哪種方法預測能力更好。
從圖中可以看出,在MSE和MAE均較低的情況下,SARIMA模型的性能略優於Holt-Winter模型。儘管這兩種模式都無法完美地抓住峰谷特徵,但它們仍然對企業有用。根據數據,平均每月廣告支出為2百萬美元以上。而這兩種算法的MAE大約在6000左右。換言之,對於一家平均每月廣告支出為2百萬美元的企業,兩個月的廣告支出預測誤差只在6000美元左右,這是相當可觀的。
結束語
在本文中,單變量預測方法在廣告支出數據上表現良好。但這些方法難以組合/合併新的信號(如事件、天氣)。同時這些方法對丟失數據也非常敏感,通常不能很好地預測很長一段時間。
而在下一篇文章中,我們將展示如何使用深度學習技術來預測同一數據集上的時間序列!