时间序列数据中的自相关性

导航至

顾名思义,时间序列是一系列按时间顺序排列的数据点。通常,时间序列用于跟踪某些事物在短期和长期内的变化——股票甚至其他商品的价格就是一个典型的例子。无论如何,您都在仔细观察事物在一段时间内以有规律的间隔发生的变化——这在尝试使用过去来预测未来时非常重要。

为什么时间序列分析很重要

例如,如果您可以确切地看到某种证券的价格随时间的变化情况,那么您可以更准确地猜测未来同一时间间隔内价格可能发生的情况。这可以带来更好、更明智的决策,这就是时间序列分析对如此多行业如此重要的原因。

为什么时间序列数据是独特的

时间序列是按时间索引的一系列数据点。时间序列数据是按顺序排列的这一事实使其在数据空间中独一无二,因为它经常显示序列依赖性。当一个时间点的数据点的值在统计上依赖于另一个时间点的另一个数据点时,就会发生序列依赖性。然而,时间序列数据的这种属性违反了许多统计分析的基本假设之一——数据在统计上是独立的。

什么是时间序列中的自相关性?

术语自相关性指的是 A) 给定的时间序列与 B) 其自身滞后版本在 C) 连续时间间隔内的相似程度。换句话说,自相关性旨在衡量变量的当前值与您可能访问的任何过去值之间的关系。

因此,时间序列自相关性试图衡量变量的当前值与该变量的历史数据。它最终将一个序列绘制在另一个序列之上,并确定两者之间的相似程度。

为了便于比较,自相关性本质上与您自己计算两组不同时间序列值之间的相关性时所经历的过程完全相同。这里的主要区别在于,自相关性使用同一个时间序列两次:一次使用其原始值,然后在经过几个不同的时间段后再次使用。

自相关性也称为序列相关性、时间序列相关性和滞后相关性。无论如何使用,自相关性都是揭示时间序列数据中原本会被忽视的趋势和模式的理想方法。

自相关性示例

重要的是要注意,时间序列数据中的自相关性并非所有领域都以完全相同的方式使用这种技术。它绝不是一成不变的——这意味着将数据与其自身延迟副本进行比较的简单原理在各种情况下都同样有价值。同样,自相关性在各个领域的应用并非都相同——这意味着它们使用一个简单的过程来达到完全不同的最终结果。

示例 1:回归分析

自相关性常用方式的一个突出示例是以使用时间序列数据进行回归分析的形式。在这里,专业人士通常会使用标准自回归模型、移动平均模型或两者结合的模型,称为自回归积分移动平均模型,或简称 ARIMA

示例 2:自相关性的科学应用

自相关性也经常用于荧光相关光谱法,这是理解某些科学环境中的分子水平扩散和化学反应的关键部分。

示例 3:全球定位系统

自相关性也是智能手机或其他移动设备中嵌入的 GPS 芯片核心的主要数学技术之一。在这里,自相关性用于校正传播延迟——这意味着载波信号传输时和最终被相关 GPS 设备接收之前发生的时间偏移。这就是 GPS 始终准确知道您在哪里,并在您到达精确位置之前告诉您何时何地转弯的方式。

示例 4:信号处理

自相关性也是信号处理中非常重要的技术,信号处理是电气工程的一部分,专注于更多地了解(甚至修改或合成)声音、图像,有时甚至是科学测量等信号。在这种情况下,自相关性可以帮助人们更好地理解重复事件,如音乐节拍——这本身对于确定歌曲的适当节奏非常重要。许多人也使用它来估计音调中非常具体的音高。

示例 5:天体物理学

天体物理学是天文学的一个分支,它采用我们已知的物理学和化学原理,并以帮助我们更好地理解外太空物体的性质的方式应用它们,而不仅仅满足于了解它们的相对位置或它们的移动方式。这是自相关性使用的另一个重要方式,因为它有助于专业人士研究宇宙中星系等天体之间的空间分布。它在对低质量 X 射线双星进行多波长观测时也很有用。

为什么自相关性很重要

通常,任何数据分析的第一步都是执行回归分析。但是,回归分析的假设之一是数据没有自相关性。这可能会令人沮丧,因为如果您尝试对具有自相关性的数据进行回归分析,那么您的分析将具有误导性。

此外,一些时间序列预测方法(特别是回归建模)依赖于残差(拟合模型与数据之间的差异)中不存在任何自相关性的假设。人们经常使用残差来评估他们的模型是否拟合良好,同时忽略残差没有自相关性的假设(或者误差是独立同分布或 i.i.d)。这种错误可能会误导人们相信他们的模型拟合良好,但实际上并非如此。我强烈建议阅读这篇关于 如何(不)使用机器学习进行时间序列预测:避免陷阱 的文章,作者在其中演示了日益流行的 LSTM(长短期记忆)网络如何看起来是一个出色的单变量时间序列预测器,但实际上它只是过度拟合数据。他进一步解释了这种误解是如何由于自相关性的存在而导致准确性指标失败的结果。

最后,自相关性分析最引人注目的方面也许是它如何帮助我们揭示数据中的隐藏模式,并帮助我们选择正确的预测方法。具体来说,我们可以使用它来帮助识别时间序列数据中的季节性和趋势。此外,结合分析自相关函数 (ACF) 和偏自相关函数 (PACF) 对于为您的时间序列预测选择合适的 ARIMA 模型是必要的。

自相关性测试

时间序列数据中可能存在的任何自相关性都是使用相关图(也称为 ACF 图)确定的。这用于帮助您确定您的数字系列是否完全表现出自相关性,届时您就可以开始更好地理解系列中的值可能正在预测的模式。

最常见的自相关性测试称为 Durbin-Watson 检验,它以 James Durbin 和 Geoffrey Watson 的名字命名,并于 1950 年代初推导出来。

自相关性统计量和检验

此检验也通常称为 Durbin-Watson 统计量,用于检测从回归分析中发现的任何预测误差中滞后一期的自相关性的存在。用于进行此检验的精确计算可以在这里找到

成功将数字插入 Durbin-Watson 检验后,它会报告一个 0 到 4 之间的统计值。如果返回的值为 2,则您的时间序列中没有自相关性。如果该值介于 0 和 2 之间,您会看到所谓的正自相关性——这在时间序列数据中非常常见。如果该值介于 2 和 4 之间的任何位置,则意味着存在负相关性——这在时间序列数据中不太常见,但在某些情况下确实会发生。

如何确定您的时间序列数据是否具有自相关性

在此练习中,我使用 InfluxDB 和 InfluxDB Python CL。我正在使用来自 美国国家海洋和大气管理局 (NOAA) 运营海洋产品和服务中心 的可用数据。具体来说,我将查看圣莫尼卡一条河流的水位和水温。

数据集

curl https://s3.amazonaws.com/noaa.water-database/NOAA_data.txt -o NOAA_data.txt
influx -import -path=NOAA_data.txt -precision=s -database=NOAA_water_database

此分析和代码包含在此 repo 中的 jupyter 笔记本中。

首先,我导入所有依赖项。

import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from influxdb import InfluxDBClient
from statsmodels.graphics.tsaplots import plot_pacf
from statsmodels.graphics.tsaplots import plot_acf
from scipy.stats import linregress

接下来,我连接到客户端,查询我的水温数据并绘制它。

client = InfluxDBClient(host='localhost', port=8086)
h2O = client.query('SELECT mean("degrees") AS "h2O_temp" FROM "NOAA_water_database"."autogen"."h2o_temperature"  GROUP BY time(12h) LIMIT 60')
h2O_points = [p for p in h2O.get_points()]
h2O_df = pd.DataFrame(h2O_points)
h2O_df['time_step'] = range(0,len(h2O_df['time']))
h2O_df.plot(kind='line',x='time_step',y='h2O_temp')
plt.show()

Fig 1. H2O temperature vs. timestep - autocorrelation in time series data

图 1. H2O 温度与时间步长

从上面的图中可以看出,我们的数据是否具有任何自相关性并不是很明显。例如,我无法检测到季节性的存在,这将产生高自相关性。

我可以使用 Pandas.Sereis.autocorr() 函数计算自相关性,该函数返回 Pearson 相关系数的值。Pearson 相关系数是衡量两个变量之间线性相关性的指标。Pearson 相关系数的值介于 -1 和 1 之间,其中 0 表示没有线性相关性,>0 表示正相关性,<0 表示负相关性。正相关性是指两个变量同步变化,而负相关系数意味着变量反向变化。我将数据与滞后 = 1(或数据 (t) 与数据 (t-1))和滞后 = 2(或数据 (t) 与数据 (t-2))进行比较。

shift_1 = h2O_df['h2O_temp'].autocorr(lag=1)
print(shift_1)
-0.07205847740103073
0.17849760131784975

这些值非常接近 0,这表明几乎没有相关性。但是,计算单个自相关性值可能无法说明全部情况。滞后 = 1 时可能没有任何相关性,但滞后 = 15 时可能存在相关性。最好制作一个 自相关图,以比较自相关函数 (AFC) 的值与不同的滞后大小。同样重要的是要注意,随着滞后值的增加,AFC 变得越来越不可靠。这是因为随着滞后值的增加,您将比较越来越少的观测值。一般准则是观测总数 (T) 应至少为 50,最大滞后值 (k) 应小于或等于 T/k。由于我总共有 60 个观测值,因此我只会考虑 AFC 的前 20 个值。

plot_acf(h2O_df['h2O_temp'], lags=20)
plt.show()

Fig 2. Autocorrelation plot for H2O temperatures

图 2. H2O 温度的自相关图

从此图中,我们看到对于滞后 > 0,ACF 的值在 95% 置信区间内(以实灰色线表示),这验证了我们的数据没有任何自相关性。起初,我发现这个结果令人惊讶,因为通常一天的气温与前一天的气温高度相关。我假设水温也是如此。这个结果提醒我,溪流和河流的行为系统与空气不同。我不是水文学家,但我知道泉水或融雪通常全年温度相同。也许它们表现出每天温度轮廓保持不变,其中均值、方差和自相关性都为常数(其中自相关性 = 0)。

使用时间序列数据中的自相关性揭示季节性

ACF 也可用于揭示和验证时间序列数据中的季节性。让我们看一下来自同一数据集的水位。

client = InfluxDBClient(host='localhost', port=8086)
h2O_level = client.query('SELECT "water_level" FROM "NOAA_water_database"."autogen"."h2o_feet" WHERE "location"=\'santa_monica\' AND time >= \'2015-08-22 22:12:00\' AND time <= \'2015-08-28 03:00:00\'')
h2O_level_points = [p for p in h2O_level.get_points()]
h2O_level_df = pd.DataFrame(h2O_level_points)
h2O_level_df['time_step'] = range(0,len(h2O_level_df['time']))
h2O_level_df.plot(kind='line',x='time_step',y='water_level')
plt.show()

Fig 3. H2O level vs. timestep - autocorrelation in time series data

图 3. H2O 水位与时间步长

仅通过绘制数据,很明显可能存在季节性,数据中可预测的模式就证明了这一点。让我们通过绘制 ACF 来验证这个假设。

plot_acf(h2O_level_df['water_level'], lags=400)
plt.show()

Autocorrelation plot for H2O levels

图 4:H2O 水位的自相关图

从上面的 ACF 图中,我们可以看到我们的季节周期大约由 246 个时间步长组成(其中 ACF 具有第二大正峰值)。虽然从图 3 中的时间序列图中很容易看出水位数据具有季节性,但情况并非总是如此。在 Python 中的季节性 ARIMA 中,作者 Sean Abu 展示了他必须如何在 ARIMA 方法中添加季节性成分,才能解释他的数据集中的季节性。我很欣赏他的数据集选择,因为我在下图中检测不到任何自相关性。这是一个很好的例子,说明了如何使用 ACF 帮助揭示数据中的隐藏趋势。

Monthly Ridership vs. Year. Source: Seasonal ARIMA with Python

图 5:每月乘客人数与年份。来源:Python 中的季节性 ARIMA

使用时间序列数据中的自相关性检查趋势

为了查看时间序列数据的趋势,我们首先需要消除季节性。滞后差分是一种简单的变换方法,可用于消除序列的季节性成分。滞后差分定义为

difference(t) = observation(t) - observation(t-interval)2,

其中 interval 是周期。为了计算水位数据中的滞后差分,我使用了以下函数

def difference(dataset, interval):
    diff = list()
    for i in range(interval, len(dataset)):
        value = dataset[i] - dataset[i - interval]
        diff.append(value)
    return pd.DataFrame(diff, columns = ["water_level_diff"])
h2O_level_diff = difference(h2O_level_df['water_level'], 246)
h2O_level_diff['time_step'] = range(0,len(h2O_level_diff['water_level_diff']))
h2O_level_diff.plot(kind='line',x='time_step',y='water_level_diff')
plt.show()

Lagged difference for H2O levels - autocorrelation in time series data

图 6:H2O 水位的滞后差分

我们现在可以再次绘制 ACF。

plot_acf(h2O_level_diff['water_level_diff'], lags=300)
plt.show()

ACF of lagged difference for H2O levels - autocorrelation in time series data

图 7:H2O 水位滞后差分的 ACF

似乎我们的滞后差分中仍然存在季节性。但是,如果我们注意图 5 中的 y 轴,我们可以看到范围非常小,所有值都接近 0。这告诉我们我们已成功消除了季节性,但存在多项式趋势。我使用 seasonal_decompose 来验证这一点。

from statsmodels.tsa.seasonal import seasonal_decompose
from matplotlib import pyplot
result = seasonal_decompose(h2O['water_level'], model='additive', freq=250)
result.plot()
pyplot.show()

Seasonal Decomposition of H2O levels

图 8. H2O 水位的季节性分解

结论

自相关性很重要,因为它可以帮助我们揭示数据中的模式,成功选择最佳预测模型,并正确评估模型的有效性。我希望这篇关于自相关性的介绍对您有所帮助。如果您有任何问题,请在社区网站上发布,或在 Twitter 上给我们发推文 @InfluxDB。与往常一样,这里有一个脑筋急转弯

参考文献

  1. Time Series Analysis and Forecasting by Example, Søren Bisgaard and Murat Kulachi
  2. How to Remove Trends and Seasonality with a Difference Transform in Python

资源

  1. Season ARIMA with Python: Time Series Forecasting
  2. Time Series in Python Part 2: Dealing with seasonal data
  3. How to Decompose Time Series Data into Trend and Seasonality
  4. How (not) to use Machine Learning for time series forecasting: Avoiding the pitfalls
  5. A Gentle Introduction to Autocorrelation and Partial Autocorrelation
  6. Time Series Concepts
  7. Stationarity
  8. Time Series Forecast Case Study with Python: Monthly Armed Robberies in Boston
  9. How to Create an ARIMA model for Time Series Forecasting in Python
  10. Interpret the partial autocorrelation function (PACF)
  11. Assumptions of Linear Regression