華文網

ARIMA模型實例講解:時間序列預測需要多少歷史資料?

雷鋒網按:本文源自美國機器學習專家 Jason Brownlee 的博客,雷鋒網編譯。

時間序列預測,究竟需要多少歷史資料?

顯然,這個問題並沒有一個固定的答案,而是會根據特定的問題而改變。

在本教程中,我們將基於 Python 語言,對模型輸入大小不同的歷史資料,對時間序列預測問題展開討論,探究歷史資料對 ARIMA 預測模型的性能影響。(雷鋒網注:ARIMA 全程是 Autoregressive Integrated Moving Average Model,即自回歸積分滑動平均模型)

具體來說,在本教程中,我們將:

● 載入標準資料集並輸入 ARIMA 模型;

● 對歷史資料年份進行敏感性分析;

● 分析敏感性分析的結果。

通過本例提供的範本,大家將可以根據各自特定的時間序列預測場景,展開類似的針對歷史資料大小的敏感性分析。

載入資料集

本例中我們使用來自澳大利亞氣象局的一份資料,該資料描述了墨爾本市 10 年(1981 - 1990年)內的每日最低氣溫,單位為攝氏度,觀測值共 3650 次。

以下代碼展示了如何載入資料庫,並生成 Pandas 庫中的 Series 物件。

# line plot of time series

from pandas import Series

from matplotlib import pyplot

# load dataset

series = Series.from_csv('daily-minimum-temperatures.csv', header=0)

# display first few rows

print(series.head(20))

# line plot of dataset

series.plot

pyplot.show

運行代碼後列印得到的前 20 行資料如下所示:

根據載入資料,可以得到如下圖所示的溫度變化曲線,從圖頭中可以看到明顯的季節性變化。

搭建 ARIMA 預測模型

在本節中,我們將基於以上資料搭建一個 ARIMA 預測模型。

這裡我們不會調整模型參數。而且,為了對資料平穩化並適配 ARIMA 模型,必須先刪除資料中包含的明顯的季節性變化趨勢。

以下代碼中,我們通過減去前一年資料的辦法來獲得資料的季節性差異。需要說明的是,這種方法是很粗糙的,因為它並沒有考慮閏年的因素。而且,這也意味著第一年的資料將無法用於建模,

因為第一年並沒有更早的資料。

# seasonal difference

differenced = series.diff(365)

# trim off the first year of empty data

differenced = series[365:]

接下來,我們將資料導入 ARIMA(7,0,0) 模型,並列印輸出匯總資訊。

# fit model

model = ARIMA(differenced, order=(7,0,0))

model_fit = model.fit(trend='nc', disp=0)

print(model_fit.summary)

列印輸出的匯總資訊如下:

歷史資料的敏感性分析

這一節我們將討論歷史資料大小對模型預測性能的影響。

上文提到,我們原本有 10 年的原始資料,

但是由於季節性差異處理,因此只有 9 年的實際資料可用。為了進行歷史資料大小的敏感性分析,這裡我們將最後一年的資料作為測試樣本,依次選擇1年、2年一直到8年的剩餘資料為訓練樣本,步進地進行測試,並逐日記錄測試情況。根據記錄資料,我們還計算了均方根誤差(RMSE)來明確反應模型的性能表現。

下面這行代碼將經過季節性調整的資料分為訓練資料和測試資料。

train, test = differenced[differenced.index

需要注意的是,這裡根據自己的問題預測規模,選擇合適的間隔很重要。本例中我們未來對歷史資料量進行敏感性分析進行了步進操作。另外,鑒於資料的季節性,本例中一年是資料集的最好的時間間隔。但感興趣的朋友根據問題域的變化也可以選擇其他間隔,例如閱讀或者多年時間間隔。

以下是具體代碼:

# split

train, test = differenced[differenced.index

years = ['1989', '1988', '1987', '1986', '1985', '1984', '1983', '1982']

for year in years:

# select data from 'year' cumulative to 1989

dataset = train[train.index >= year]

定好了資料之後,下一步是評估 ARIMA 模型。

具體的步進評估方法是:首先選取一個時間段的資料,並根據選定資料建模,訓練,然後對下一段資料進行預測,預測後記錄資料並計算正確率。接著,將真實的觀察資料加入建模資料,建立新的模型並展開訓練,對再下一段資料進行預測,並記錄結果。依次進行,知道資料用完。

最終,預測結果將被集合在一起,與真實觀察資料中的最後一年比較,計算出錯誤情況。在這種情況下,RMSE 將被用作預測得分,並將與觀察結果的數量級等同。

具體代碼如下:

# walk forward over time steps in test

values = dataset.values

history = [values[i] for i in range(len(values))]

predictions = list

test_values = test.values

for t in range(len(test_values)):

# fit model

model = ARIMA(history, order=(7,0,0))

model_fit = model.fit(trend='nc', disp=0)

# make prediction

yhat = model_fit.forecast[0]

predictions.append(yhat)

history.append(test_values[t])

rmse = sqrt(mean_squared_error(test_values, predictions))

print('%s-%s (%d values) RMSE: %.3f' % (years[0], year, len(values), rmse))

運行代碼後的列印輸出結果如下。需要注意的是,因為代碼在每個歷史訓練資料間隔都創建了 356 個 ARIMA 模型,因此可能需要一些時間。

1989-1989 (365 values) RMSE: 2.336

1989-1988 (730 values) RMSE: 2.333

1989-1987 (1095 values) RMSE: 2.326

1989-1986 (1460 values) RMSE: 2.321

1989-1985 (1825 values) RMSE: 2.320

1989-1984 (2190 values) RMSE: 2.320

1989-1983 (2555 values) RMSE: 2.318

1989-1982 (2920 values) RMSE: 2.316

從結果可以看到,隨著可用歷史資料的增多,模型的誤差總體呈下降趨勢。

但同時也應該看到,在 4-5 年的時間段,不斷增長歷史資料的效果收益率實際上是遞減的。也就是說,在歷史資料不足或模型訓練時間無法滿足要求時,也可以根據實際需求,利用相對較少的歷史資料,得到一個性價比最高的結果。

以下代碼是根據測試資料繪製曲線圖的過程。

from matplotlib import pyplot

x = [365, 730, 1095, 1460, 1825, 2190, 2555, 2920]

y = [2.336, 2.333, 2.326, 2.321, 2.320, 2.320, 2.318, 2.316]

pyplot.plot(x, y)

pyplot.show

運行後得到的曲線如圖所示。

從曲線圖可以更清晰地看到總體上歷史資料越多,預測結果就更精確這一變化趨勢。因為歷史資料越多,就意味著係數的優化越精確,符合資料變化的內在規律的可能性就越高。

但同時也可以從上圖中看到另一個現象:大多數時候人們覺得歷史資料越多,模型的表現就越好。但實際上,連續兩年或三年的資料之間並沒有什麼根本性的差別,因此靈活選擇時間跨度也至關重要。

局限性和擴展

我們通過本次教程為大家演示了如何設計、執行和分析基於時間序列預測的歷史資料敏感性分析。現針對樣例中的一些局限和可能的擴展項目整理如下:

1. 模型參數未調試。本例中我們使用的 ARIMA 模型並未針對問題域進行過任何的參數調節。在理想狀態下,一個針對歷史資料量的敏感性分析應該基於一個經過參數調節的 ARIMA 模型。

2. 統計學意義。上文中提到的,針對不同的歷史資料,模型的不同預測表現是否具有統計學意義,目前尚不清楚。但 Pairwise 統計學顯著性檢驗可用於評估 RMSE 的差異是否有意義。

3. 其他模型。本例中我們使用了 ARIMA 模型來進行歷史資料的係數擬合。感興趣的朋友可以換用其他模型進行類似的研究,各個模型對歷史資料的敏感性和處理方式也各不相同。

4. 其他時間間隔。本例中我們以一年為時間間隔,但實際上也可以選擇其他間隔。例如幾個星期、幾個月或者幾年,要根據不同的問題域靈活選擇。另外,如上文所述,還要考慮相鄰時間段之間資料的相似性,這也是一個很重要的影響因素。

train, test = differenced[differenced.index

需要注意的是,這裡根據自己的問題預測規模,選擇合適的間隔很重要。本例中我們未來對歷史資料量進行敏感性分析進行了步進操作。另外,鑒於資料的季節性,本例中一年是資料集的最好的時間間隔。但感興趣的朋友根據問題域的變化也可以選擇其他間隔,例如閱讀或者多年時間間隔。

以下是具體代碼:

# split

train, test = differenced[differenced.index

years = ['1989', '1988', '1987', '1986', '1985', '1984', '1983', '1982']

for year in years:

# select data from 'year' cumulative to 1989

dataset = train[train.index >= year]

定好了資料之後,下一步是評估 ARIMA 模型。

具體的步進評估方法是:首先選取一個時間段的資料,並根據選定資料建模,訓練,然後對下一段資料進行預測,預測後記錄資料並計算正確率。接著,將真實的觀察資料加入建模資料,建立新的模型並展開訓練,對再下一段資料進行預測,並記錄結果。依次進行,知道資料用完。

最終,預測結果將被集合在一起,與真實觀察資料中的最後一年比較,計算出錯誤情況。在這種情況下,RMSE 將被用作預測得分,並將與觀察結果的數量級等同。

具體代碼如下:

# walk forward over time steps in test

values = dataset.values

history = [values[i] for i in range(len(values))]

predictions = list

test_values = test.values

for t in range(len(test_values)):

# fit model

model = ARIMA(history, order=(7,0,0))

model_fit = model.fit(trend='nc', disp=0)

# make prediction

yhat = model_fit.forecast[0]

predictions.append(yhat)

history.append(test_values[t])

rmse = sqrt(mean_squared_error(test_values, predictions))

print('%s-%s (%d values) RMSE: %.3f' % (years[0], year, len(values), rmse))

運行代碼後的列印輸出結果如下。需要注意的是,因為代碼在每個歷史訓練資料間隔都創建了 356 個 ARIMA 模型,因此可能需要一些時間。

1989-1989 (365 values) RMSE: 2.336

1989-1988 (730 values) RMSE: 2.333

1989-1987 (1095 values) RMSE: 2.326

1989-1986 (1460 values) RMSE: 2.321

1989-1985 (1825 values) RMSE: 2.320

1989-1984 (2190 values) RMSE: 2.320

1989-1983 (2555 values) RMSE: 2.318

1989-1982 (2920 values) RMSE: 2.316

從結果可以看到,隨著可用歷史資料的增多,模型的誤差總體呈下降趨勢。

但同時也應該看到,在 4-5 年的時間段,不斷增長歷史資料的效果收益率實際上是遞減的。也就是說,在歷史資料不足或模型訓練時間無法滿足要求時,也可以根據實際需求,利用相對較少的歷史資料,得到一個性價比最高的結果。

以下代碼是根據測試資料繪製曲線圖的過程。

from matplotlib import pyplot

x = [365, 730, 1095, 1460, 1825, 2190, 2555, 2920]

y = [2.336, 2.333, 2.326, 2.321, 2.320, 2.320, 2.318, 2.316]

pyplot.plot(x, y)

pyplot.show

運行後得到的曲線如圖所示。

從曲線圖可以更清晰地看到總體上歷史資料越多,預測結果就更精確這一變化趨勢。因為歷史資料越多,就意味著係數的優化越精確,符合資料變化的內在規律的可能性就越高。

但同時也可以從上圖中看到另一個現象:大多數時候人們覺得歷史資料越多,模型的表現就越好。但實際上,連續兩年或三年的資料之間並沒有什麼根本性的差別,因此靈活選擇時間跨度也至關重要。

局限性和擴展

我們通過本次教程為大家演示了如何設計、執行和分析基於時間序列預測的歷史資料敏感性分析。現針對樣例中的一些局限和可能的擴展項目整理如下:

1. 模型參數未調試。本例中我們使用的 ARIMA 模型並未針對問題域進行過任何的參數調節。在理想狀態下,一個針對歷史資料量的敏感性分析應該基於一個經過參數調節的 ARIMA 模型。

2. 統計學意義。上文中提到的,針對不同的歷史資料,模型的不同預測表現是否具有統計學意義,目前尚不清楚。但 Pairwise 統計學顯著性檢驗可用於評估 RMSE 的差異是否有意義。

3. 其他模型。本例中我們使用了 ARIMA 模型來進行歷史資料的係數擬合。感興趣的朋友可以換用其他模型進行類似的研究,各個模型對歷史資料的敏感性和處理方式也各不相同。

4. 其他時間間隔。本例中我們以一年為時間間隔,但實際上也可以選擇其他間隔。例如幾個星期、幾個月或者幾年,要根據不同的問題域靈活選擇。另外,如上文所述,還要考慮相鄰時間段之間資料的相似性,這也是一個很重要的影響因素。