成人av在线资源一区,亚洲av日韩av一区,欧美丰满熟妇乱XXXXX图片,狠狠做五月深爱婷婷伊人,桔子av一区二区三区,四虎国产精品永久在线网址,国产尤物精品人妻在线,中文字幕av一区二区三区欲色
    您正在使用IE低版瀏覽器,為了您的雷峰網賬號安全和更好的產品體驗,強烈建議使用更快更安全的瀏覽器
    此為臨時鏈接,僅用于文章預覽,將在時失效
    人工智能開發者 正文
    發私信給AI研習社
    發送

    0

    時間序列預測教程:如何利用 Python 預測波士頓每月持械搶劫案數量?

    本文作者: AI研習社 2017-02-17 12:08
    導語:專家手把手帶你做時間序列預測練習。

    編者按:本文是澳大利亞知名機器學習專家 Jason Brownlee 撰寫的教程,極其全面細致,一步步向讀者解釋如何操作,以及為什么這么做。雷鋒網整理編譯,特與大家分享。更多AI開發技術文章,請關注AI研習社(微信號:okweiwu)。

    時間序列預測教程:如何利用 Python 預測波士頓每月持械搶劫案數量?

    Jason Brownlee:時間序列預測法是一個過程,而獲得良好預測結果的唯一途徑是實踐這個過程。

    在本教程中,您將了解如何利用Python語言來預測波士頓每月持械搶劫案發生的數量。

    本教程所述為您提供了一套處理時間序列預測問題的框架,包括方法步驟和工具,通過實踐,可以用它來解決自己遇到的相關問題。

    本教程結束之后,您將了解:

    • 如何核查Python環境并準確地定義一個時間序列預測問題。

    • 如何構建一套測試工具鏈,用于評估模型,開發預測原型。以及如何通過時間序列分析工具更好地理解你的問題。

    • 如何開發自回歸積分滑動平均模型(ARIMA),將其保存到文件,并在之后加載它對新的時間步驟進行預測。

    讓我們開始吧。

    時間序列預測教程:如何利用 Python 預測波士頓每月持械搶劫案數量?

    波士頓

    概述

    在本教程中,我們將端到端地來解析一個時間序列預測工程,從下載數據集、定義問題到訓練出最終模型并進行預測。

    該工程并不面面俱到,但展示了如何通過系統性地處理時間序列預測問題,來快速獲得好的結果。

    我們將通過如下步驟來解析該工程 :

    1. 環境配置.

    2. 問題描述

    3. 測試工具鏈

    4. 持續性.

    5. 數據分析

    6. ARIMA 模型

    7. 模型驗證

    該部分提供一個解決時間序列預測問題的模板,你可以套用自己的數據集。

    1. 環境配置

    本教程假設在已安裝好了SciPy及其相關依賴庫的環境下進行,包括:

    1. SciPy

    2. NumPy

    3. Matplotlib

    4. Pandas

    5. scikit-learn

    6. statsmodels

    我使用的是Python2.7。該腳本將幫助你確認你安裝這些庫的版本。

    # scipy

    import scipy

    print('scipy: {}'.format(scipy.__version__))

    # numpy

    import numpy

    print('numpy: {}'.format(numpy.__version__))

    # matplotlib

    import matplotlib

    print('matplotlib: {}'.format(matplotlib.__version__))

    # pandas

    import pandas

    print('pandas: {}'.format(pandas.__version__))

    # scikit-learn

    import sklearn

    print('sklearn: {}'.format(sklearn.__version__))

    # statsmodels

    import statsmodels

    print('statsmodels: {}'.format(statsmodels.__version__))


    我編寫該教程的所用的開發環境顯示的結果如下:

    scipy: 0.18.1

    numpy: 1.11.2

    matplotlib: 1.5.3

    pandas: 0.19.1

    sklearn: 0.18.1

    statsmodels: 0.6.1 

    2. 問題描述

    我們研究的問題是預測美國波士頓每月持械搶劫案的數量。

    該數據集提供了從1966年1月到1975年10月在波士頓每月發生的的武裝搶劫案的數量, 或者說,是這十年間的數據。

    這些值是一些記錄的觀察計數,總有118個觀察值。

    數據集來自于McCleary&Hay(1980)。

    您可以了解有關此數據集的更多信息,并直接從 DataMarket 下載。

    下載地址:https://datamarket.com/data/set/22ob/monthly-boston-armed-robberies-jan1966-oct1975-deutsch-and-alt-1977#!ds=22ob&display=line

    將數據集下載為CSV文件,并將其放在當前工作目錄中,文件名為“robberies.csv”。

    3.測試工具鏈

    我們必須開發一套測試工具鏈來審查數據和評估候選模型。

    這包含兩個步驟:

    1.定義好驗證數據集。

    2.開發一套模型評估方法。

    3.1 驗證數據集

    這個數據集不是當前時間段的數據集。 這意味著我們不能輕輕松松收集更新后的數據來驗證該模型。

    因此,我們假設現在是1974年10月,并將分析和模型選擇的數據集里扣除最后一年的數據。

    最后一年的數據將用于驗證生成的最終模型。

    下面的代碼會加載該數據集為Pandas序列對象并將其切分成兩部分,一個用于模型開發(dataset.csv)和另一個用于驗證(validation.csv)。

    from pandas import   Series

    series = Series.from_csv('robberies.csv', header=0)

    split_point = len(series) - 12

    dataset, validation = series[0:split_point], series[split_point:]

    print('Dataset   %d, Validation %d' % (len(dataset), len(validation)))

    dataset.to_csv('dataset.csv')

    validation.to_csv('validation.csv')

    運行該示例將會創建兩個文件并打印出每個文件中的觀察數。

    1. Dataset 106, Validation 12

    這些文件的具體內容是:

    • dataset.csv:1966年1月至1974年10月的觀察(106次觀察)

    • validation.csv:1974年11月至1975年10月的觀察(12次觀察)

    驗證數據集大小是原始數據集的10%。

    請注意,由于保存的數據集中沒有標題行,因此,稍后處理這些文件時,我們也不需要滿足此要求。

    3.2. 模型驗證

    模型評估將僅對上一節中準備的dataset.csv中的數據進行處理。

    模型評估涉及兩個要素:

    1. 評價指標。

    2. 測試策略。

    3.2.1評價指標

    這些觀察值是搶劫案的計數。

    我們將使用均方根誤差(RMSE)的方式來評價預測的好壞。這將給予錯誤的預測更多的權重,并且將具有與原始數據相同的單位。

    在RMSE進行計算和報告之前,必須反轉對數據的所有轉換,以使不同方法的效果可直接比較。

    我們可以使用scikit-learn庫的輔助函數mean_squared_error()來執行RMSE計算,該函數計算出了預期值列表(測試集)和預測列表之間的均方誤差。 然后我們可以取這個值的平方根來作為一個RMSE分數。

    例如: 

    1. from sklearn.metrics import mean_squared_error

    2. from math import sqrt

    3. ...

    4. test = ...

    5. predictions = ...

    6. mse = mean_squared_error(test, predictions)

    7. rmse = sqrt(mse)

    8. print('RMSE:   %.3f' % rmse)

    3.2.2 測試策略

    將使用步進驗證的方式(walk-forward)來評估候選模型。

    這是因為該問題定義需要滾動式預測的模型。給定所有可用數據,這需要逐步進行預測。

    步進驗證的方式將按照如下幾步執行:

    • 數據集的前50%將被用來訓練模型。

    • 剩余的50%的數據集將被迭代并測試模型。

    • 對于測試數據集中的每個步驟:

    • 訓練該模型

    • 利用該模型預測一次,并經預測結果保存下來用于之后的驗證

    • 測試數據集的數據作為下一個迭代的訓練集數據

    • 對在測試數據集迭代期間進行的預測結果進行評估,并報告RMSE得分。

    由于較小的數據規模,我們將允許在每次預測之前,在給定所有可用數據的情況下重新訓練模型。

    我們可以使用簡單的NumPy和Python來編寫測試工具的代碼。

    首先,我們可以將數據集直接分成訓練和測試集。 我們總要將加載的數據轉換為float32類型,以防止仍然有一些數據為String或Integer數據類型。

    1. # prepare data

    2. X = series.values

    3. X = X.astype('float32')

    4. train_size = int(len(X) * 0.50)

    5. train, test = X[0:train_size], X[train_size:]

    接下來,我們可以時間步長遍歷測試數據集。訓練數據集存儲在一個Python的list對象中,因為我們需要在每次迭代中很容易的附加一些觀察值,Numpy數組連接有些overkill。

    模型進行的預測,按慣例稱為yhat。這是由于結果或觀察被稱為y,而yhat(有上標“^”的y)是用于預測y變量的數學符號。

    打印預測和觀察結果,對每個觀察值進行完整性檢查,以防模型存在問題。

    1. # walk-forward   validation

    2. history = [x for x in train]

    3. predictions = list()

    4. for i in range(len(test)):

    5. # predict

    6. yhat = ...

    7. predictions.append(yhat)

    8. # observation

    9. obs = test[i]

    10. history.append(obs)

    11. print('>Predicted=%.3f,   Expected=%3.f' % (yhat, obs))

    4. Persistence(持續性模型)

    在數據分析和建模陷入困境之前的第一步是建立一個評估原型。

    這里將為利用測試工具進行模型評估和性能測量,分別提供一套模版。通過該性能測量,可以將當前模型和其他更復雜的預測模型進行比較。

    時間序列預測的預測原型被稱為天真預測或Persistence。

    在這里,先前時間步驟的觀察結果將被用作于下一時間步長的預測。

    我們可以將其直接插入上一節中定義的測試工具中。

    下面羅列了完整的代碼:

    1. from pandas import   Series

    2. from sklearn.metrics import mean_squared_error

    3. from math import sqrt

    4. # load data

    5. series = Series.from_csv('dataset.csv')

    6. # prepare data

    7. X = series.values

    8. X = X.astype('float32')

    9. train_size = int(len(X) * 0.50)

    10. train, test = X[0:train_size], X[train_size:]

    11. # walk-forward   validation

    12. history = [x for x in train]

    13. predictions = list()

    14. for i in range(len(test)):

    15. # predict

    16. yhat = history[-1]

    17. predictions.append(yhat)

    18. # observation

    19. obs = test[i]

    20. history.append(obs)

    21. print('>Predicted=%.3f,   Expected=%3.f' % (yhat, obs))

    22. # report performance

    23. mse = mean_squared_error(test, predictions)

    24. rmse = sqrt(mse)

    25. print('RMSE:   %.3f' % rmse)

    運行測試工具,打印測試數據集中每次迭代的預測值和實際觀察值。

    示例到進行打印模型的RMSE這一步結束。

    在該示例中,我們可以看到持久性模型實現了51.844的RMSE。 這意味著,對于每個預測,該模型中平均有51次搶劫值預測是錯誤的。

    1. ...

    2. >Predicted=241.000, Expected=287

    3. >Predicted=287.000, Expected=355

    4. >Predicted=355.000, Expected=460

    5. >Predicted=460.000, Expected=364

    6. >Predicted=364.000, Expected=487

    7. RMSE: 51.844

    我們現在有了一個預測方法和性能評估的原型; 現在我們可以開始深入數據。

    5. 數據分析

    我們可以使用統計匯總和數據的繪圖,來快速了解該預測問題的數據結構。

    在本節中,我們將從四個角度來看數據:

    1.摘要統計。

    2.線圖。

    3.密度圖。

    4.盒型-虛線圖。

    5.1 摘要統計

    利用文本編輯器中打開數據dataset.csv文件或原始的robberies.csv文件,并查看數據。

    快速檢查表明,數據集里沒有明顯丟失的觀察數據。 我們可能已經更早的發現了像NaN或'?'等值數,如果我們試圖強制序列化數據為浮點值。

    摘要統計提供了觀察值的快速預覽。 它可以幫助我們快速了解我們正在使用的東西。

    以下示例為計算并打印時間系列的摘要統計信息。 

    1. from pandas import   Series

    2. series = Series.from_csv('dataset.csv')

    3. print(series.describe())

    運行該示例會提供大量的摘要信息供回顧。

    這些統計數據包含的一些信息為:

    • 觀察次數(計數)與我們的期望相符,這意味著我們將數據正確處理了。

    • 平均值約為173,我們可以想象出我們在這個序列中的級別。

    • 在112次搶劫時,標準偏差(平均值的平均分布)相對較大。

    • 百分位數與標準差一致表明數據有很大的差異。

    1. count    106.000000

    2. mean     173.103774

    3. std      112.231133

    4. min       29.000000

    5. 25%       74.750000

    6. 50%      144.500000

    7. 75%      271.750000

    8. max      487.000000

    對于序列中比較大的變化將可能模型很難進行高度準確的預測,如果它是由隨機波動(例如,非系統的)引起,

    5.2 線圖

    畫一個時間序列的線圖可以對該問題提供很多深入的信息。

    下面的示例創建并顯示出數據集的線圖。

    1. from pandas import   Series

    2. from matplotlib   import pyplot

    3. series = Series.from_csv('dataset.csv')

    4. series.plot()

    5. pyplot.show()

    運行示例并查看繪圖。 注意系列中的任何明顯的時間結構。

    • 圖中的一些觀察結果包括:

    • 隨著時間的推移,劫案有增加的趨勢。

    • 似乎沒有任何明顯的異常值。

    • 每年都有相對較大的波動,上下波動。

    • 后幾年的波動似乎大于前幾年的波動。

    • 整體趨勢表明該數據集幾乎肯定不是穩定的,并且波形的明顯變化也可能對此有所提示。

    時間序列預測教程:如何利用 Python 預測波士頓每月持械搶劫案數量?

    每月波士頓搶劫案數據線圖

    這些簡單的觀察結果表明,我們可以看到對趨勢進行建模和從時間序列中將它提取出來的好處。

    或者,我們可以使用差分法從而使序列的建模平穩。如果后期波動有增長趨勢,我們甚至可能需要兩個差分到不同級別。

    5.3 密度圖

    提取出密度圖,可以提供對數據結構的進一步了解。

    下面的示例創建了沒有任何時間結構的觀測值的直方圖和密度圖。

    1. from pandas import   Series

    2. from matplotlib   import pyplot

    3. series = Series.from_csv('dataset.csv')

    4. pyplot.figure(1)

    5. pyplot.subplot(211)

    6. series.hist()

    7. pyplot.subplot(212)

    8. series.plot(kind='kde')

    9. pyplot.show()

    運行示例并查看繪圖。

    圖中展示的一些分析結果包括:

    • 分布不是高斯分布。

    • 分布是左移的,可以是指數或雙高斯分布

      時間序列預測教程:如何利用 Python 預測波士頓每月持械搶劫案數量?

    每月波士頓搶劫密案數量密度圖

    我們可以看到在建模之前進行一些數據的維度變換的一些益處。

    5.4 盒形-虛線圖

    我們可以按年份對月度數據進行分組,并了解每年觀察值的分布情況,以及觀察值可能如何變化。

    我們確實希望從數據中看到一些趨勢(增加平均值或中位數),但看到其余的分布是如何變化的可能會更有趣。

    下面的示例將觀察值按照年份劃分,并為每個觀察年創建一個盒型-虛線圖。 最后一年(1974年)只包含10個月,可能與其他有12個月的觀察值的年份相比會無效。 因此,只有1966年和1973年之間的數據被繪制。

    1. from pandas import   Series

    2. from pandas import   DataFrame

    3. from pandas import   TimeGrouper

    4. from matplotlib   import pyplot

    5. series = Series.from_csv('dataset.csv')

    6. groups = series['1966':'1973'].groupby(TimeGrouper('A'))

    7. years = DataFrame()

    8. for name, group in groups:

    9. years[name.year] = group.values

    10. years.boxplot()

    11. pyplot.show()

    圖中的一些觀察結果包括:

    • 每年的中間值(紅線)顯示可能不是線性的趨勢

    • 散列值和中間50%的數據(藍色框)不同,但時間長了可能會有變化。

    • 較早的年份,也許是前2年,與數據集的其余部分有很大的不同。

    時間序列預測教程:如何利用 Python 預測波士頓每月持械搶劫案數量?

    波士頓每月搶劫案數目的盒形-虛線圖

    觀察結果表明,年度波動可能不是系統性的,難以模擬。 他們還建議將建模的前兩年的數據從模型分離出來可能有一些好處,如果確實不同。

    這種對數據進行年度觀察是一個有趣的方法,而且可以通過查看年度匯總統計數據和其中的變化,來進一步跟進未來的變化。

    接下來,我們可以開始查看該序列的預測模型。

    6. ARIMA 模型

    在本節中,我們將會針對該問題開發自回歸積分滑動平均模型,即ARIMA模型。

    我們將其分四個步驟:

    1.開發一套手動配置的ARIMA模型。

    2.使用ARIMA的網格搜索來找到優化的模型。

    3.預測殘差的分析,以評估模型中的所有偏差。

    4.使用能量變換探索模型的改進。

    6.1 手動配置ARIMA

    Nasonasonal ARIMA(p,d,q)需要三個參數,并且通常是傳統地進行手動配置。

    時間序列數據的分析。假設我們使用的是靜態時間序列。

    時間序列基本上肯定是非靜態的。我們可以通過首先區分序列,并使用統計測試,來確保結果是靜態的。

    下面的示例創建一個靜態版本的序列,并將其保存到文件stationary.csv。

    1. from pandas import   Series

    2. from statsmodels.tsa.stattools   import adfuller

    3.  

    4. # create a differe

    5. def difference(dataset):

    6. diff = list()

    7. for i in range(1, len(dataset)):

    8. value = dataset[i] - dataset[i - 1]

    9. diff.append(value)

    10. return Series(diff)

    11.  

    12. series = Series.from_csv('dataset.csv')

    13. X = series.values

    14. # difference data

    15. stationary = difference(X)

    16. stationary.index = series.index[1:]

    17. # check if stationary

    18. result = adfuller(stationary)

    19. print('ADF   Statistic: %f' % result[0])

    20. print('p-value:   %f' % result[1])

    21. print('Critical   Values:')

    22. for key, value in result[4].items():

    23. print('\t%s:   %.3f' % (key, value))

    24. # save

    25. stationary.to_csv('stationary.csv')

    運行示例輸出統計顯著性測試的結果,以表明序列是否靜止。 具體來說,強化迪基-福勒檢驗。

    結果表明,測試的統計值-3.980946小于-2.893的5%時的臨界值。 這表明我們可以否決具有小于5%的顯著性水平的零假設(即,結果為統計結果的概率很低)。

    拒絕零假設意味著過程沒有單位根,反過來說就是,該時間序列是固定的或者不具有時間依賴性結構。

    1. ADF Statistic: -3.980946

    2. p-value: 0.001514

    3. Critical Values:

    4. 5%: -2.893

    5. 1%: -3.503

    6. 10%: -2.584

    這表明至少需要一個級別的差分。 我們的ARIMA模型中的d參數應至少為1的值。

    下一步是分別選擇自回歸(AR)和移動平均(MA)參數的滯后值,p和q。

    我們可以通過審查自相關函數(ACF)和部分自相關函數(PACF)圖來做到這一點。

    以下示例為該序列創建ACF和PACF圖。

    1. from pandas import   Series

    2. from statsmodels.graphics.tsaplots   import plot_acf

    3. from statsmodels.graphics.tsaplots   import plot_pacf

    4. from matplotlib   import pyplot

    5. series = Series.from_csv('dataset.csv')

    6. pyplot.figure()

    7. pyplot.subplot(211)

    8. plot_acf(series, ax=pyplot.gca())

    9. pyplot.subplot(212)

    10. plot_pacf(series, ax=pyplot.gca())

    11. pyplot.show()

    運行示例并查看繪圖,詳細了解一下如何設置ARIMA模型的p和q變量。

    下面是從圖中得到的一些觀察結論。

    • ACF顯示1個月的顯著滯后。

    • PACF顯示了大約2個月的顯著滯后,滯后至大約12個月以后。

    • ACF和PACF在同一點顯示出下降,可能是AR和MA參數的混合。

    p和q值的正確的起點是1或2。

    時間序列預測教程:如何利用 Python 預測波士頓每月持械搶劫案數量?

    每月波士頓搶劫案數量的ACF和PACF圖

    這個快速分析結果表明ARIMA(1,1,2)對原始數據可能是一個很好的切入點。

    雷鋒網了解,實驗表明,這套ARIMA的配置不會收斂,并引起底層庫的錯誤。一些實驗表明,該模型表現不太穩定,同時定義了非零的AR和MA階數。

    該模型可以簡化為ARIMA(0,1,2)。 下面的示例演示了此ARIMA模型在測試工具上的性能。

    1. from pandas import   Series

    2. from sklearn.metrics import mean_squared_error

    3. from statsmodels.tsa.arima_model   import ARIMA

    4. from math import sqrt

    5. # load data

    6. series = Series.from_csv('dataset.csv')

    7. # prepare data

    8. X = series.values

    9. X = X.astype('float32')

    10. train_size = int(len(X) * 0.50)

    11. train, test = X[0:train_size], X[train_size:]

    12. # walk-forward   validation

    13. history = [x for x in train]

    14. predictions = list()

    15. for i in range(len(test)):

    16. # predict

    17. model = ARIMA(history, order=(0,1,2))

    18. model_fit = model.fit(disp=0)

    19. yhat = model_fit.forecast()[0]

    20. predictions.append(yhat)

    21. # observation

    22. obs = test[i]

    23. history.append(obs)

    24. print('>Predicted=%.3f,   Expected=%3.f' % (yhat, obs))

    25. # report performance

    26. mse = mean_squared_error(test, predictions)

    27. rmse = sqrt(mse)

    28. print('RMSE:   %.3f' % rmse)

    運行此示例結果的RMSE值為49.821,低于持續性模型(Persistence)。

    1. ...

    2. >Predicted=280.614, Expected=287

    3. >Predicted=302.079, Expected=355

    4. >Predicted=340.210, Expected=460

    5. >Predicted=405.172, Expected=364

    6. >Predicted=333.755, Expected=487

    7. RMSE: 49.821

    這是一個好的開始,但是我們可以達到改進結果通過一個配置更好的ARIMA模型。

    6.2 網格搜索ARIMA超參數

    許多ARIMA配置在此數據集上不穩定,但可能有其他超參數導向一個表現良好的模型。

    在本節中,我們將搜索p,d和q的值,以找出不會導致錯誤的組合,并找到可獲得最佳性能的組合。 我們將使用網格搜索來探索整數值子集中的所有組合。

    具體來說,我們將搜索以下參數的所有組合:

    • p:      0 - 12.

    • d:      0 - 3.

    • q:      0 -12.

    這是(13 * 4 * 13),或676,測試工具的運行結果,并且將花費需要一些時間用來執行。

    下面是利用網格搜索的測試工具的完整示例:

    1. import warnings

    2. from pandas import   Series

    3. from statsmodels.tsa.arima_model   import ARIMA

    4. from sklearn.metrics import mean_squared_error

    5. from math import sqrt

    6.  

    7. # evaluate an ARIMA   model for a given order (p,d,q) and return RMSE

    8. def   evaluate_arima_model(X, arima_order):

    9. # prepare training   dataset

    10. X = X.astype('float32')

    11. train_size = int(len(X) * 0.50)

    12. train, test = X[0:train_size], X[train_size:]

    13. history = [x for x in train]

    14. # make predictions

    15. predictions = list()

    16. for t in range(len(test)):

    17. model = ARIMA(history, order=arima_order)

    18. model_fit = model.fit(disp=0)

    19. yhat = model_fit.forecast()[0]

    20. predictions.append(yhat)

    21. history.append(test[t])

    22. # calculate out of   sample error

    23. mse = mean_squared_error(test, predictions)

    24. rmse = sqrt(mse)

    25. return rmse

    26.  

    27. # evaluate   combinations of p, d and q values for an ARIMA model

    28. def evaluate_models(dataset, p_values, d_values, q_values):

    29. dataset = dataset.astype('float32')

    30. best_score, best_cfg = float("inf"), None

    31. for p in p_values:

    32. for d in d_values:

    33. for q in q_values:

    34. order = (p,d,q)

    35. try:

    36. mse = evaluate_arima_model(dataset, order)

    37. if mse < best_score:

    38. best_score, best_cfg = mse, order

    39. print('ARIMA%s   MSE=%.3f' % (order,mse))

    40. except:

    41. continue

    42. print('Best   ARIMA%s MSE=%.3f' % (best_cfg, best_score))

    43.  

    44. # load dataset

    45. series = Series.from_csv('dataset.csv')

    46. # evaluate parameters

    47. p_values = range(0,13)

    48. d_values = range(0, 4)

    49. q_values = range(0, 13)

    50. warnings.filterwarnings("ignore")

    51. evaluate_models(series.values, p_values, d_values, q_values)

    運行該示例并運行所有組合,并將無錯誤收斂的結果報出來。

    該示例當前硬件上運行至少需要2小時。

    結果表明,最佳配置為ARIMA(0,1,2),巧合的是,這在前面的部分中已經被證明。

    1. ...

    2. ARIMA(6, 1, 0) MSE=52.437

    3. ARIMA(6, 2, 0) MSE=58.307

    4. ARIMA(7, 1, 0) MSE=51.104

    5. ARIMA(7, 1, 1) MSE=52.340

    6. ARIMA(8, 1, 0) MSE=51.759

    7. Best ARIMA(0, 1, 2) MSE=49.821

    6.3 檢查殘差

    對一個模型來說,一個不錯的最終檢查,是檢查其殘差預測誤差。

    理想情況下,殘差的分布應該是符合零均值的高斯分布。

    我們可以通過用直方圖和密度圖繪制殘差來檢查這一點。

    以下示例為計算測試集上預測的殘差,并創建該密度圖。

    1. from pandas import   Series

    2. from pandas import   DataFrame

    3. from sklearn.metrics import mean_squared_error

    4. from statsmodels.tsa.arima_model   import ARIMA

    5. from math import sqrt

    6. from matplotlib   import pyplot

    7. # load data

    8. series = Series.from_csv('dataset.csv')

    9. # prepare data

    10. X = series.values

    11. X = X.astype('float32')

    12. train_size = int(len(X) * 0.50)

    13. train, test = X[0:train_size], X[train_size:]

    14. # walk-foward   validation

    15. history = [x for x in train]

    16. predictions = list()

    17. for i in range(len(test)):

    18. # predict

    19. model = ARIMA(history, order=(0,1,2))

    20. model_fit = model.fit(disp=0)

    21. yhat = model_fit.forecast()[0]

    22. predictions.append(yhat)

    23. # observation

    24. obs = test[i]

    25. history.append(obs)

    26. # errors

    27. residuals = [test[i]-predictions[i] for i in range(len(test))]

    28. residuals = DataFrame(residuals)

    29. pyplot.figure()

    30. pyplot.subplot(211)

    31. residuals.hist(ax=pyplot.gca())

    32. pyplot.subplot(212)

    33. residuals.plot(kind='kde', ax=pyplot.gca())

    34. pyplot.show()

    運行該示例會創建兩個圖表。

    這些圖表征了一個有長右尾的高斯樣分布。

    這可能表明該預測是有偏差的,并且在這種情況下,在建模之前對原始數據進行基于能量的變換可能是有用的。

    時間序列預測教程:如何利用 Python 預測波士頓每月持械搶劫案數量?

    殘差密度圖

    通過檢查所有時間序列的殘差中是否有某種類型的自相關性也是一個好辦法。 如果存在,它將表明模型有更多的機會來建模數據中的時間結構。

    下面的示例是重新計算殘差,并創建ACF和PACF圖以檢查出比較明顯的的自相關性。

    1. from pandas import   Series

    2. from pandas import   DataFrame

    3. from sklearn.metrics import mean_squared_error

    4. from statsmodels.tsa.arima_model   import ARIMA

    5. from statsmodels.graphics.tsaplots   import plot_acf

    6. from statsmodels.graphics.tsaplots   import plot_pacf

    7. from math import sqrt

    8. from matplotlib   import pyplot

    9. # load data

    10. series = Series.from_csv('dataset.csv')

    11. # prepare data

    12. X = series.values

    13. X = X.astype('float32')

    14. train_size = int(len(X) * 0.50)

    15. train, test = X[0:train_size], X[train_size:]

    16. # walk-foward   validation

    17. history = [x for x in train]

    18. predictions = list()

    19. for i in range(len(test)):

    20. # predict

    21. model = ARIMA(history, order=(0,1,2))

    22. model_fit = model.fit(disp=0)

    23. yhat = model_fit.forecast()[0]

    24. predictions.append(yhat)

    25. # observation

    26. obs = test[i]

    27. history.append(obs)

    28. # errors

    29. residuals = [test[i]-predictions[i] for i in range(len(test))]

    30. residuals = DataFrame(residuals)

    31. pyplot.figure()

    32. pyplot.subplot(211)

    33. plot_acf(residuals, ax=pyplot.gca())

    34. pyplot.subplot(212)

    35. plot_pacf(residuals, ax=pyplot.gca())

    36. pyplot.show()

    結果表明,該時間序列中存在的少量的自相關性已被模型捕獲。

    時間序列預測教程:如何利用 Python 預測波士頓每月持械搶劫案數量?

    殘差ACF和PACF圖

    6.4 Box-Cox 變換數據集

    Box-Cox變換是可以對一組能量變換進行評估的方法,包括但不限于數據的對數,平方根和互逆變換。

    下面的示例對數據的執行一個對數變換,并生成一些曲線以查看對時間序列的影響。

    1. from pandas import   Series

    2. from pandas import   DataFrame

    3. from scipy.stats import boxcox

    4. from matplotlib   import pyplot

    5. from statsmodels.graphics.gofplots   import qqplot

    6. series = Series.from_csv('dataset.csv')

    7. X = series.values

    8. transformed, lam = boxcox(X)

    9. print('Lambda:   %f' % lam)

    10. pyplot.figure(1)

    11. # line plot

    12. pyplot.subplot(311)

    13. pyplot.plot(transformed)

    14. # histogram

    15. pyplot.subplot(312)

    16. pyplot.hist(transformed)

    17. # q-q plot

    18. pyplot.subplot(313)

    19. qqplot(transformed, line='r', ax=pyplot.gca())

    20. pyplot.show()

    運行示例創建三個圖:經變換的時間序列的線圖,展示變換后值的分布的直方圖,以及展示變換后的值得分布與理想化高斯分布相比的Q-Q圖。

    這些圖中的一些觀察結果如下:

    • 大的波動已在時間序列的線圖中被移除。

    • 直方圖顯示出了數值更平坦更均勻(表現良好)的分布。

    • Q-Q圖是合理的,但仍然不適合高斯分布。

    時間序列預測教程:如何利用 Python 預測波士頓每月持械搶劫案數量?

    每月波士頓搶劫案數據的BoxCox變換圖

    毫無疑問,Box-Cox變換對時間序列做了一些事情,而且是有效的。

    在使用轉換數據測試ARIMA模型之前,我們必須有一種方法來進行逆轉轉換,以便可以將對在轉換后的尺度上進行訓練的模型所做的預測轉換回原始尺度。

    示例中使用的boxcox()函數通過優化損失函數找到理想的lambda值。

    lambda在以下函數中用于數據轉換:

    1. transform = log(x), if lambda == 0

    2. transform = (x^lambda - 1) / lambda, if lambda != 0

    這個變換函數可以直接逆過來,如下:

    1. x = exp(transform) if lambda == 0

    2. x = exp(log(lambda * transform + 1) / lambda)

    這個逆Box-Cox變換函數可以在Python中如下實現:

    1. # invert box-cox   transform

    2. from math import log

    3. from math import exp

    4. def boxcox_inverse(value, lam):

    5. if lam == 0:

    6. return exp(value)

    7. return exp(log(lam   * value + 1) / lam)

    我們可以用Box-Cox變換重新評估ARIMA(0,1,2)模型。

    這包括在擬合ARIMA模型之前的初次變換,然后在存儲之前對預測進行反變換,以便稍后與期望值進行比較。

    boxcox()函數可能失敗。 在實踐中,我已經認識到這一點,它似乎是返回了一個小于-5的lambda值。 按照慣例,lambda值在-5和5之間計算。

    對于小于-5的lambda值添加檢查,如果是這種情況,則假定lambda值為1,并且使用原始數據來擬合模型。 lambda值為1與未轉換相同,因此逆變換沒有效果。

    下面列出了完整的示例。

    1. from pandas import   Series

    2. from sklearn.metrics import mean_squared_error

    3. from statsmodels.tsa.arima_model   import ARIMA

    4. from math import sqrt

    5. from math import log

    6. from math import exp

    7. from scipy.stats import boxcox

    8.  

    9. # invert box-cox   transform

    10. def boxcox_inverse(value, lam):

    11. if lam == 0:

    12. return exp(value)

    13. return exp(log(lam   * value + 1) / lam)

    14.  

    15. # load data

    16. series = Series.from_csv('dataset.csv')

    17. # prepare data

    18. X = series.values

    19. X = X.astype('float32')

    20. train_size = int(len(X) * 0.50)

    21. train, test = X[0:train_size], X[train_size:]

    22. # walk-foward   validation

    23. history = [x for x in train]

    24. predictions = list()

    25. for i in range(len(test)):

    26. # transform

    27. transformed, lam = boxcox(history)

    28. if lam < -5:

    29. transformed, lam = history, 1

    30. # predict

    31. model = ARIMA(transformed, order=(0,1,2))

    32. model_fit = model.fit(disp=0)

    33. yhat = model_fit.forecast()[0]

    34. # invert transformed   prediction

    35. yhat = boxcox_inverse(yhat, lam)

    36. predictions.append(yhat)

    37. # observation

    38. obs = test[i]

    39. history.append(obs)

    40. print('>Predicted=%.3f,   Expected=%3.f' % (yhat, obs))

    41. # report performance

    42. mse = mean_squared_error(test, predictions)

    43. rmse = sqrt(mse)

    44. print('RMSE:   %.3f' % rmse)

    運行此示例將打印每次迭代的預測值和預期值

    注意,當使用boxcox()轉換函數時,可能會看到一些警告; 例如:

    1. RuntimeWarning: overflow encountered in square

    2. llf -= N / 2.0 * np.log(np.sum((y - y_mean)**2. / N, axis=0))

    不過現在可以忽略這些。

    在轉換數據上生成的模型最終的RMSE為49.443。 對于未轉換的數據,這是一個比ARIMA模型更小的誤差,但只是很細微的,它可能是,也可能不是統計意義上的不同。

    1. ...

    2. >Predicted=276.253, Expected=287

    3. >Predicted=299.811, Expected=355

    4. >Predicted=338.997, Expected=460

    5. >Predicted=404.509, Expected=364

    6. >Predicted=349.336, Expected=487

    7. RMSE: 49.443

    我們將使用該Box-Cox變換的模型作為最終模型。

    7. 模型驗證

    在開發完模型并選擇最終模型后,必須對其進行驗證和確定。

    驗證是一個可選的過程,為我們提供了“最后的檢查手段”,以確保我們沒有被自己欺騙。

    此部分包括以下步驟:

    1.    確定模型:訓練并保存最終模型。

    2.    進行預測: 加載最終模型并進行預測。

    3.    驗證模型: 加載和驗證最終模型。

    7.1 確定模型

    模型的確定涉及在整個數據集上擬合ARIMA模型,值得注意的一點是,該步驟中的數據集已經經過了變換。

    一旦擬合好之后,模型可以保存到文件以供后續使用。這里由于我們對數據執行了Box-Cox變換,因此我們需要明確所選擇的lamda值,以便使得來自模型的任何預測都可以被轉換回原始的未轉換的尺度。

    下面的示例展示了在Box-Cox變換數據集上使用ARIMA(0,1,2)模型,并將整個擬合對象和lambda值保存到文件中的過程。

    1. from pandas import   Series

    2. from statsmodels.tsa.arima_model   import ARIMA

    3. from scipy.stats import boxcox

    4. import numpy

    5. # load data

    6. series = Series.from_csv('dataset.csv')

    7. # prepare data

    8. X = series.values

    9. X = X.astype('float32')

    10. # transform data

    11. transformed, lam = boxcox(X)

    12. # fit model

    13. model = ARIMA(transformed, order=(0,1,2))

    14. model_fit = model.fit(disp=0)

    15. # save model

    16. model_fit.save('model.pkl')

    17. numpy.save('model_lambda.npy', [lam])

    運行該示例會創建兩個本地文件:

    • model.pkl這是通過ARIMA.fit()      調用生成的ARIMAResult對象。 包括了各種系數和在擬合模型時返回的所有其他內部數據。

    • model_lambda.npy這是作為一行一列NumPy數組對象存儲的lambda值。

    這些文件或許會保存的過于詳細。其實在操作中真正需要的是:來自模型的AR和MA系數、用于差異數量的d參數、以及滯后的觀察值、模型殘差和用于變換的lamda值。

    7.2 進行預測

    這里,最直接的方法是加載模型并進行單一預測。

    這是相對直接的,涉及恢復保存的模型、lambda值和調用forecast() 方法。

    然而,在當前穩定版本的statsmodels庫(v0.6.1)中存在一個Bug,它的錯誤提示如下:

    1. TypeError: __new__() takes at least 3 arguments (1 given)

    據我測試發現,這個bug也似乎存在于statsmodels的0.8版本候選1版本中。

    更多詳細信息,請參閱Zae Myung Kim的討論和在GitHub上的解決辦法。

    鏈接:https://github.com/statsmodels/statsmodels/pull/3217

    我們可以使用一個猴子補丁(monkey patch)來解決這個問題,在保存之前將一個 __getnewargs __() 實例函數添加到ARIMA類中。

    下面的示例與上一小節的變化相同。

    1. from pandas import   Series

    2. from statsmodels.tsa.arima_model   import ARIMA

    3. from scipy.stats import boxcox

    4. import numpy

    5.  

    6. # monkey patch around   bug in ARIMA class

    7. def __getnewargs__(self):

    8. return ((self.endog),(self.k_lags, self.k_diff, self.k_ma))

    9.  

    10. ARIMA.__getnewargs__ = __getnewargs__

    11.  

    12. # load data

    13. series = Series.from_csv('dataset.csv')

    14. # prepare data

    15. X = series.values

    16. X = X.astype('float32')

    17. # transform data

    18. transformed, lam = boxcox(X)

    19. # fit model

    20. model = ARIMA(transformed, order=(0,1,2))

    21. model_fit = model.fit(disp=0)

    22. # save model

    23. model_fit.save('model.pkl')

    24. numpy.save('model_lambda.npy', [lam])

    我們現在可以加載模型并進行單一預測。

    下面這個示例展示了加載模型,對下一時間步進進行了預測,反轉Box-Cox變換,并打印預測結果的過程。

    1. from pandas import   Series

    2. from statsmodels.tsa.arima_model   import ARIMAResults

    3. from math import exp

    4. from math import log

    5. import numpy

    6.  

    7. # invert box-cox   transform

    8. def boxcox_inverse(value, lam):

    9. if lam == 0:

    10. return exp(value)

    11. return exp(log(lam   * value + 1) / lam)

    12.  

    13. model_fit = ARIMAResults.load('model.pkl')

    14. lam = numpy.load('model_lambda.npy')

    15. yhat = model_fit.forecast()[0]

    16. yhat = boxcox_inverse(yhat, lam)

    17. print('Predicted:   %.3f' % yhat)

    最后得到的預測值為452。

    如果我們在validation.csv中查看的話,我們可以看到下一個時間段的第一行的數值是452。模型達到了100% 的正確率,這是非常驚人的(也是幸運的)。

    1. Predicted: 452.043

    7.3 驗證模型

    在這一步驟中,我們可以加載模型并以模擬操作的方式使用它。

    在測試工具部分中,我們將原始數據集的最后12個月保存在單獨的文件中,以驗證最終模型。

    我們現在可以加載此validation.csv文件,并用它來檢驗我們的模型對真正“未知”的數據究竟表現如何。

    這里可以采用兩種方式:

    • 加載模型并使用它預測未來的12個月。 超過前一兩個月的預測將很快開始降低技能(start to degrade in skill)。

    • 加載模型并以步進預測的方式使用該模型,更新每個時間步長上的變換和模型。      這是首選的方法,在實踐中使用這個模型,它將表現出最佳的性能。

    與前面章節中的模型評估一樣,我們將以步進預測的方式進行預測。 這意味著我們將在驗證數據集中逐步引導時間點,并將觀察結果作為歷史記錄的更新。

    1. from pandas import   Series

    2. from matplotlib   import pyplot

    3. from statsmodels.tsa.arima_model   import ARIMA

    4. from statsmodels.tsa.arima_model   import ARIMAResults

    5. from scipy.stats import boxcox

    6. from sklearn.metrics import mean_squared_error

    7. from math import sqrt

    8. from math import exp

    9. from math import log

    10. import numpy

    11.  

    12. # invert box-cox   transform

    13. def boxcox_inverse(value, lam):

    14. if lam == 0:

    15. return exp(value)

    16. return exp(log(lam   * value + 1) / lam)

    17.  

    18. # load and prepare   datasets

    19. dataset = Series.from_csv('dataset.csv')

    20. X = dataset.values.astype('float32')

    21. history = [x for x in X]

    22. validation = Series.from_csv('validation.csv')

    23. y = validation.values.astype('float32')

    24. # load model

    25. model_fit = ARIMAResults.load('model.pkl')

    26. lam = numpy.load('model_lambda.npy')

    27. # make first   prediction

    28. predictions = list()

    29. yhat = model_fit.forecast()[0]

    30. yhat = boxcox_inverse(yhat, lam)

    31. predictions.append(yhat)

    32. history.append(y[0])

    33. print('>Predicted=%.3f,   Expected=%3.f' % (yhat, y[0]))

    34. # rolling forecasts

    35. for i in range(1, len(y)):

    36. # transform

    37. transformed, lam = boxcox(history)

    38. if lam < -5:

    39. transformed, lam = history, 1

    40. # predict

    41. model = ARIMA(transformed, order=(0,1,2))

    42. model_fit = model.fit(disp=0)

    43. yhat = model_fit.forecast()[0]

    44. # invert transformed   prediction

    45. yhat = boxcox_inverse(yhat, lam)

    46. predictions.append(yhat)

    47. # observation

    48. obs = y[i]

    49. history.append(obs)

    50. print('>Predicted=%.3f,   Expected=%3.f' % (yhat, obs))

    51. # report performance

    52. mse = mean_squared_error(y, predictions)

    53. rmse = sqrt(mse)

    54. print('RMSE:   %.3f' % rmse)

    55. pyplot.plot(y)

    56. pyplot.plot(predictions, color='red')

    57. pyplot.show()

    運行以上示例將打印出在驗證數據集中所有時間步長上的每個預測值和預期值。

    修正階段最終的RMSE預測結果為53次搶劫。 這與預期的49次并沒有太大的出入,我希望它在簡單的持久性模型上也能有類似的表現。

    1. >Predicted=452.043, Expected=452

    2. >Predicted=423.088, Expected=391

    3. >Predicted=408.378, Expected=500

    4. >Predicted=482.454, Expected=451

    5. >Predicted=445.944, Expected=375

    6. >Predicted=413.881, Expected=372

    7. >Predicted=413.209, Expected=302

    8. >Predicted=355.159, Expected=316

    9. >Predicted=363.515, Expected=398

    10. >Predicted=406.365, Expected=394

    11. >Predicted=394.186, Expected=431

    12. >Predicted=428.174, Expected=431

    13. RMSE: 53.078

    我們在這里同時提供了預測結果與驗證數據集之間相互比較的圖表。

    該預測具有持續性預測的特性。這表明雖然這個時間序列有明顯的趨勢,但它仍然是一個相當困難的問題。

    時間序列預測教程:如何利用 Python 預測波士頓每月持械搶劫案數量?

    驗證時間步驟的預測

    教程擴展

    需要說明的是,本教程并不完美,你可以有很多改善結果的方法。

    本節列出了一些或許可行的改進措施。

    • 統計顯著性檢驗。使用統計學測試來檢查不同模型之間的結果差異是否具有統計學的意義。T檢驗將是一個很好的入手點。

    • 使用數據變換的網格進行搜索。通過Box-Cox變換在ARIMA超參數中重復網格搜索過程,并查看是否可以實現一個與此前不同的,并且更好的參數集。

    • 檢查殘差。通過Box-Cox變換檢測最終模型的預測誤差的殘差,以查看是否存在可以進一步優化的偏差或自相關。

    • 精簡模型存儲。嘗試簡化模型保存,僅僅存儲那些必要的系數,而不是整個ARIMAResults對象。

    • 手動處理趨勢。使用線性或非線性模型直接對趨勢進行建模,并明確地從序列中刪除它。如果該趨勢是非線性的,并且更適合非線性建模,那這種方式可能會帶來更好的性能表現。

    • 置信區間。顯示驗證數據集中預測的置信區間。

    • 數據選擇。考慮在沒有前兩年數據的情況下對問題進行建模,并查看這是否對預測技能(forecast skill)有影響。

    總結

    通過本教程的學習,你可以初步了解到基于Python的時間序列預測項目的具體實現步驟和工具。

    我們在本教程中討論了很多內容,具體來說包括以下三個方面:

    • 如何通過性能指標和評估方法開發測試工具,以及如何快速開發基準預測原型和方法。

    • 如何通過時間序列分析來提出最好的模擬預測問題的方法。

    • 如何開發ARIMA模型,并保存它,然后加載它用來對新數據進行預測。

    歡迎加入雷鋒網 ML 開發者讀者群,添加“ycopen3”微信號,回復關鍵詞“開發者”,群助拉您進群交流!

    via machine learning mastery

    雷峰網版權文章,未經授權禁止轉載。詳情見轉載須知

    時間序列預測教程:如何利用 Python 預測波士頓每月持械搶劫案數量?

    分享:
    相關文章

    編輯

    聚焦數據科學,連接 AI 開發者。更多精彩內容,請訪問:yanxishe.com
    當月熱門文章
    最新文章
    請填寫申請人資料
    姓名
    電話
    郵箱
    微信號
    作品鏈接
    個人簡介
    為了您的賬戶安全,請驗證郵箱
    您的郵箱還未驗證,完成可獲20積分喲!
    請驗證您的郵箱
    立即驗證
    完善賬號信息
    您的賬號已經綁定,現在您可以設置密碼以方便用郵箱登錄
    立即設置 以后再說