介紹
無論多麼強大,機器學習都無法預測一切。 例如與時間序列預測有關的領域中,表現得就不是很好。
儘管有大量自迴歸模型和許多其他時間序列演算法可用,但如果目標分佈是白噪聲或遵循隨機遊走,則無法預測目標分佈。
因此,您必須在進一步努力之前檢測此類分佈。
在本文中,您將瞭解什麼是白噪聲和隨機遊走,並探索經過驗證的統計技術來檢測它們。
關於自相關的簡要說明
自相關涉及找到時間序列與其自身滯後版本之間的相關性。 考慮這個分佈:
deg_C = tps_july[“deg_C”]。to_frame(“temperature”)deg_C。head()
滯後時間序列意味著將其向後移動 1 個或多個週期:
deg_C[“lag_1”] = deg_C[“temperature”]。shift(periods=1)deg_C[“lag_2”] = deg_C[“temperature”]。shift(periods=2)deg_C[“lag_3”] = deg_C[“temperature”]。shift(periods=3)deg_C。head(6)
自相關函式 (ACF) 在每個滯後 k 處找到時間序列與其滯後版本之間的相關係數。 您可以使用 statsmodels 中的 plot_acf 函式繪製它。 這是它的樣子:
from matplotlib import rcParamsfrom statsmodels。graphics。tsaplots import plot_acfrcParams[“figure。figsize”] = 9, 4# ACF function up to 50 lagsfig = plot_acf(deg_C[“temperature”], lags=50)plt。show();
XAxis 是滯後 k,YAxis 是每個滯後的 Pearson 相關係數。 紅色陰影區域是置信區間。 如果條形的高度在該區域之外,則意味著相關性在統計上是顯著的。
什麼是白噪聲?
簡而言之,白噪聲分佈是具有以下特徵的任何分佈:
零均值
恆定的方差/標準偏差(不隨時間變化)
所有滯後的零自相關
本質上,它是一系列隨機數,根據定義,沒有演算法可以合理地對其行為進行建模。
有特殊型別的白噪聲。 如果噪聲是正態的(服從正態分佈),則稱為高斯白噪聲。 讓我們直觀地看一個例子:
noise = np。random。normal(loc=0, scale=0。5, size=1000)plt。figure(figsize=(12, 4))plt。plot(noise);
即使偶爾出現尖峰,也看不到明顯的模式,即分佈是完全隨機的。
驗證這一點的最佳方法是建立 ACF 圖:
fig = plot_acf(noise, lags=40)plt。title(“Autocorrelation of a White Noise Series”)plt。show()
還有“嚴格”的白噪聲分佈——它們的序列相關性嚴格為 0。 這與棕色/粉紅色噪聲或其他自然隨機現象不同,其中存在弱序列相關但仍保持無記憶。
白噪聲在預測和模型診斷中的重要性
儘管白噪聲分佈被認為是死衚衕,但它們在其他情況下也非常有用。
例如,在時間序列預測中,如果預測值和實際值之間的差異代表白噪聲分佈,您可以為自己的工作做得很好而感到欣慰。
當殘差顯示任何模式時,無論是季節性的、趨勢的還是非零均值,這表明仍有改進的空間。相比之下,如果殘差是純白噪聲,則您將所選模型的能力最大化。
換句話說,該演算法設法捕獲了目標的所有重要訊號和屬性。剩下的是無法歸因於任何事物的隨機波動和不一致的資料點。
例如,我們將使用七月 Kaggle 操場比賽來預測空氣中一氧化碳的含量。我們將保留輸入“原樣”——我們不會執行任何特徵工程,我們將選擇一個具有預設引數的基線模型:
preds = forest。predict(X_test)residuals = y_test。flatten() - predsplt。plot(residuals)plt。title(“Plot of the Error residuals”);
fig = plot_acf(residuals, lags=50)plt。title(“Autocorrelation Plot of the Error residuals”)plt。show();
ACF 圖中有一些模式,但它們在置信區間內。 這兩個圖表明,即使使用預設引數,隨機森林也可以從訓練資料中捕獲幾乎所有重要訊號。
隨機遊走
時間序列預測中更具挑戰性但同樣不可預測的分佈是隨機遊走。 與白噪聲不同,它具有非零均值、非常量標準/方差,並且在繪製時看起來很像正則分佈:
隨機遊走系列總是以這種方式巧妙地偽裝,但它們仍然是不可預測的。 對今天數值的最佳猜測是昨天的數值。
初學者常見的困惑是將隨機遊走視為簡單的隨機數序列。 情況並非如此,因為在隨機遊走中,每一步都依賴於前一步。
因此,隨機遊走的自相關函式確實返回非零相關。
隨機遊走的公式很簡單:
無論之前的資料點是什麼,都可以為其新增一些隨機值,並根據需要繼續。 讓我們用 Python 生成它,起始值為 99:
walk = [99]for i in range(1000):# Create random noisenoise = -1 if np。random。random() < 0。5 else 1walk。append(walk[-1] + noise)rcParams[“figure。figsize”] = 14, 4plt。plot(walk);
讓我們也繪製 ACF:
fig = plot_acf(walk, lags=50)plt。show();
如您所見,前 40 個滯後產生統計上顯著的相關性。
那麼,當可視化不是一種選擇時,我們如何檢測隨機遊走?
由於它們的建立方式,時間序列的差分應該隔離每個步驟的隨機新增。 透過將序列滯後 1 並從原始值中減去它來獲取一階差分。 Pandas 有一個方便的 diff 函式來做到這一點:
walk_diff = pd。Series(walk)。diff()plt。plot(walk_diff);
如果繪製時間序列的一階差分並且結果是白噪聲,則它是隨機遊走。
帶有漂移的隨機遊走
對常規隨機遊走的一個輕微修改是在隨機步驟新增一個稱為漂移的常數值:
Drift 通常用 μ 來表示,就隨時間變化的值而言,漂移意味著逐漸變成某種東西。
例如,即使股票不斷波動,它們也可能有正漂移,即隨著時間的推移整體逐漸增加。
現在,讓我們看看如何在 Python 中模擬這一點。 我們將首先建立起始值為 25 的常規隨機遊走:
walk = [25]for i in range(1000):# Create random noisenoise = -1 if np。random。random() < 0。5 else 1walk。append(walk[-1] + noise)
從上面的公式中,我們看到我們需要在每一步新增所需的漂移。 讓我們新增 5 的漂移並檢視繪圖:
drift = 5drifty_walk = pd。Series(walk) + 5drifty_walk。plot(title=“A Random Walk with Drift”);
儘管波動劇烈,但該系列仍有明顯的上升趨勢。 如果我們執行差分,我們將看到該系列仍然是隨機遊走:
drifty_walk。diff()。plot();
統計檢測隨機遊走
您可能會問,是否有更好的方法來識別隨機遊走,而不僅僅是從圖中“觀察”它們。
作為答案,Dicker D。 A。 和 Fuller W。 A。 在 1979 年概述了一個假設檢驗,它被稱為增廣 Dickey-Fuller 檢驗。
本質上,它試圖檢驗一系列遵循隨機遊走的零假設。 在幕後,它對滯後價格的價格差異進行迴歸。
如果找到的斜率 (β) 等於 0,則該系列是隨機遊走。 如果斜率顯著不同於 0,我們拒絕該系列遵循隨機遊走的原假設。
幸運的是,您不必擔心數學問題,因為該測試已經在 Python 中實現了。
我們從 statsmodels 匯入 adfuller 函式,並將其用於上一節中建立的漂移隨機遊走:
from statsmodels。tsa。stattools import adfullerresults = adfuller(drifty_walk)print(f“ADF Statistic: {results[0]}”)print(f“p-value: {results[1]}”)print(“Critical Values:”)for key, value in results[4]。items():print(“\t%s: %。3f” % (key, value))————————————————————————ADF Statistic: -2。0646595557153424p-value: 0。25896047143602574Critical Values:1%: -3。4375%: -2。86410%: -2。568
我們檢視 p 值,約為 0。26。 由於 0。05 是顯著性閾值,我們無法拒絕drifty_walk 是隨機遊走的零假設,即它是隨機遊走。
讓我們對我們知道不是隨機遊走的分佈進行另一個測試。 我們將使用 TPS 七月 Kaggle 遊樂場比賽中的一氧化碳目標:
results = adfuller(tps_july[“target_carbon_monoxide”])print(f“ADF Statistic: {results[0]}”)print(f“p-value: {results[1]}”)print(“Critical Values:”)for key, value in results[4]。items():print(“\t%s: %。3f” % (key, value))——————————————————————————-ADF Statistic: -8。982102584771997p-value: 7。26341357249666e-15Critical Values:1%: -3。4315%: -2。86210%: -2。567
p 值非常小,這表明我們可以輕鬆拒絕 target_carbon_monoxide 遵循隨機遊走的原假設。
本文作者:Bex T。