时间序列之间的相关性检测

为了检测时间序列的相关性,我们经常使用自相关,互相关或归一化互相关。

互相关(Cross-Correlation)

互相关是两个不同时间序列的比较,以检测具有相同最大值和最小值的指标之间是否存在相关性。例如:“两个音频信号同相吗?”

为了检测两个信号之间的相关程度,我们使用互相关。 只需将两个时间序列相乘和相加即可计算得出。

在以下示例中,序列A和B是互相关的,但序列C都不与此相关。

cross-correlation

a = [1, 2, -2, 4, 2, 3, 1, 0]
b = [2, 3, -2, 3, 2, 4, 1, -1]
c = [-2, 0, 4, 0, 1, 1, 0, -2]

pyplot.figure()
pyplot.title("Series")
pyplot.plot(range(len(a)), a, color="#f44e2e", label="a")
pyplot.plot(range(len(b)), b, color="#27ccc0", label="b")
pyplot.plot(range(len(c)), c, color="#273ecc", label="c")
pyplot.ylabel("value")
pyplot.xlabel("index")
pyplot.show()

c r o s s _ c o r r ( x , y ) = ∑ i = 0 n − 1 x i ∗ y i cross\_corr(x, y) = \sum_{i=0}^{n-1} x_i*y_i cross_corr(x,y)=i=0n1xiyi

使用上面的互相关公式,我们可以计算序列之间的相关度。

import numpy as np
def cross_corr(set1, set2):
    return np.sum(set1 * set2)

a = np.array([1, 2, -2, 4, 2, 3, 1, 0])
b = np.array([2, 3, -2, 3, 2, 4, 1, -1])
c = np.array([-2, 0, 4, 0, 1, 1, 0, -2])

print(f"Cross Correlation a,b: {cross_corr(a, b)}")
print(f"Cross Correlation a,c: {cross_corr(a, c)}")
print(f"Cross Correlation b,c: {cross_corr(b, c)}")

OUTPUT:
Cross Correlation a,b: 41
Cross Correlation a,c: -5
Cross Correlation b,c: -4

序列a和b互相关性较大,值为41。序列a和c,a和b相关性较小,值分别为:-5,-4.

标准化的互相关(Normalized Cross-Correlation)

标准化的互相关也是用于两个时间序列的比较,但是使用了不同的评分结果。除了简单的互相关,它还可以比较具有不同值范围的指标。例如:“商店中的顾客数量与每天的销售数量之间是否存在相关性?”

使用互相关值评价相关性存在三个问题:

  1. 互相关的评分值难以理解。
  2. 两个序列必须具有相同的幅度。如如果一个序列值缩小了一半,那么他的相关性会减少。 c r o s s _ c o r r ( a , a / 2 ) = 19.5 cross\_corr(a,a/2)=19.5 cross_corr(a,a/2)=19.5
  3. 无法解决序列值为0的问题,根据互相关公式,由于 0 ∗ 0 = 0 0*0=0 00=0 0 ∗ 200 = 0 0*200=0 0200=0,因此无法解决0值。

为了解决这些问题,使用标准化的互相关

n o r m _ c o r r ( x , y ) = ∑ n = 0 n − 1 x i ∗ y i ∑ n = 0 n − 1 x i 2 ∗ ∑ n = 0 n − 1 y i 2 norm\_corr(x,y)=\dfrac{\sum_{n=0}^{n-1} x_i*y_i}{\sqrt{\sum_{n=0}^{n-1} x_i^2 * \sum_{n=0}^{n-1} y_i^2}} norm_corr(x,y)=n=0n1xi2n=0n1yi2 n=0n1xiyi

计算上边a,b,c序列的标准化的相关性如下:

import numpy as np
def norm_cross_corr(set1, set2):
    # python中求Normalized Cross Correlation的函数是: statsmodels.tsa.stattools.ccf
    return np.sum(set1 * set2) / (np.linalg.norm(set1) * np.linalg.norm(set2))

a = np.array([1, 2, -2, 4, 2, 3, 1, 0])
b = np.array([2, 3, -2, 3, 2, 4, 1, -1])
c = np.array([-2, 0, 4, 0, 1, 1, 0, -2])

print(f"Normalized Cross Correlation a,b: {norm_cross_corr(a, b)}")
print(f"Normalized Cross Correlation a,c: {norm_cross_corr(a, c)}")
print(f"Normalized Cross Correlation b,c: {norm_cross_corr(b, c)}")

OUTPUT:
Normalized Cross Correlation a,b: 0.9476128352180998
Normalized Cross Correlation a,c: -0.15701857325533194
Normalized Cross Correlation b,c: -0.11322770341445959

标准化的互相关值很容易理解:

  1. 值越高,相关性越高。
  2. 当两个信号完全相同时,最大值为1: n o r m _ c r o s s _ c o r r ( a , a ) = 1 norm\_cross\_corr(a,a)=1 norm_cross_corr(a,a)=1
  3. 当两个信号完全相反时,最小值为-1: n o r m _ c r o s s _ c o r r ( a , − a ) = − 1 norm\_cross\_corr(a,-a)=-1 norm_cross_corr(a,a)=1

标准化的互相关可以检测两个幅度不同的信号的相关性,如: n o r m _ c r o s s _ c o r r ( a , a / 2 ) = 1 norm\_cross\_corr(a,a/2)=1 norm_cross_corr(a,a/2)=1。信号A和具有一半振幅的同一信号之间具有最高的相关性!

自相关(Auto-Correlation)

自相关是时间序列在不同时间与其自身的比较。例如,其目的是检测重复模式或季节性。例如:“服务器网站上是否有每周的季节性?”“本周的数据与前一周的数据高度相关吗?”

自相关的用途非常广泛,其中之一就是检测由于季节性导致的可重复的模式。

下图展示了具有季节性为8的序列:

image

import numpy as np
np.random.seed(10)
a = np.tile(np.array(range(8)), 8) + np.random.normal(loc=0.0, scale=0.5, size=64)
pyplot.figure(figsize=(12, 4))
pyplot.title("Series")
pyplot.plot(range(len(a)), a, color="#f44e2e", label="a")
pyplot.ylabel("value")
pyplot.xlabel("index")
pyplot.legend(loc="upper right")
pyplot.show()

图像由如上代码生成,他是1~8的可重复序列,并且夹杂了一些随机噪声。

接下来计算时间偏移为4和时间偏移为8时信号与自身之间的自相关。
image

import numpy as np
np.random.seed(10)
a = np.tile(np.array(range(8)), 8) + np.random.normal(loc=0.0, scale=0.5, size=64)

ar4 = a[:len(a) - 4]
ar4_shift = a[4:]
print(f"Auto Correlation with shift 4: {cross_correlation(ar4, ar4_shift)}")

pyplot.figure(figsize=(12, 4))
pyplot.title("Series")
pyplot.plot(range(len(ar4)), ar4, color="blue", label="ar4")
pyplot.plot(range(len(ar4_shift)), ar4_shift, color="green", label="ar4_shift")
pyplot.ylabel("value")
pyplot.xlabel("index")
pyplot.legend(loc="upper right")
pyplot.show()

OUTPUT:
Auto Correlation with shift 4: 623.797612892277

image

import numpy as np
np.random.seed(10)
a = np.tile(np.array(range(8)), 8) + np.random.normal(loc=0.0, scale=0.5, size=64)

ar8 = a[:len(a) - 8]
ar8_shift = a[8:]
print(f"Auto Correlation with shift 4: {cross_correlation(ar8, ar8_shift)}")

pyplot.figure(figsize=(12, 4))
pyplot.title("Series")
pyplot.plot(range(len(ar4)), ar4, color="blue", label="ar4")
pyplot.plot(range(len(ar4_shift)), ar4_shift, color="green", label="ar4_shift")
pyplot.ylabel("value")
pyplot.xlabel("index")
pyplot.legend(loc="upper right")
pyplot.show()

OUTPUT:
Auto Correlation with shift 8: 996.8417240253186

上图清楚地显示了时间偏移8处的高自相关,而时间偏移4处没有。计算出的自相关值可以看到shift为8时的自相关值大于shift为4时的值。所以相比于4,我们觉得季节性更可能为8。

标准化的自相关(Normalized Auto-Correlation)

如前所述,用标准化的互相关可以更好地表达两个序列的相关性

print(f"Auto Correlation with shift 4: {norm_cross_correlation(ar4, ar4_shift)}")
print(f"Auto Correlation with shift 8: {norm_cross_correlation(ar8, ar8_shift)}")

OUTPUT:
Auto Correlation with shift 4: 0.5779124931215941
Auto Correlation with shift 8: 0.9874907451139486

相关性与时移(Correlation with Time Shift)

标准化的互相关与时移(Normalized Cross-Correlation with Time Shift)

时移可以应用于所有上述算法。想法是将指标与具有不同“时间偏移”的另一个指标进行比较。将时间偏移应用于归一化互相关函数将导致“具有X的时间偏移的归一化互相关”。这可以用来回答以下问题:“当许多顾客进我的商店时,我的销售额在20分钟后会增加吗?”

为了处理时移,我们将原始信号与由x元素向右或向左移动的另一个信号关联。就像我们为自相关所做的一样。

为了检测两个指标是否与时移相关,我们需要计算所有可能的时移。

image

image

from statsmodels.tsa.stattools import ccf
a = np.array([0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4])
b = np.array([1, 2, 3, 3, 0, 1, 2, 3, 4, 0, 1, 1, 4, 4, 0, 1, 2, 3, 4, 0])
res_ary = ccf(a, b, unbiased=False)  # 计算各种time shift下的互相关值

print(res_ary)

pyplot.bar(range(len(res_ary)), res_ary, fc="blue")
pyplot.show()

OUTPUT:
[-3.29180823e-17  8.67261700e-01  1.27247799e-01 -4.65751654e-01
 -3.92862138e-01 -1.09726941e-17  6.20178595e-01  1.27247799e-01
 -2.92793480e-01 -2.94028896e-01 -2.47083106e-02  3.48387179e-01
  1.02539489e-01 -1.19835306e-01 -1.70487343e-01 -2.47083106e-02
  1.01304073e-01  5.31228677e-02 -2.10020640e-02 -4.69457901e-02]

从上图以及数据可以看出,当time shift为1时,序列a和b高度相关。

标准化的自相关与时移(Normalized Auto-Correlation with Time Shift)

image

image

from statsmodels.tsa.stattools import acf

np.random.seed(5)
a = np.tile(np.array(range(8)), 8) + np.random.normal(loc=0.0, scale=0.5, size=64)
res_ary = acf(a, nlags=30, fft=False)
print(res_ary)
pyplot.bar(range(len(res_ary)), res_ary, fc="blue")
pyplot.show()

OUTPUT:
[ 1.          0.33436187 -0.06325233 -0.39112367 -0.46168766 -0.43537856
 -0.15175395  0.24403119  0.86075234  0.31051923 -0.03270547 -0.32083613
 -0.40031665 -0.38383002 -0.14645852  0.20649692  0.72864895  0.2693097
 -0.01707009 -0.2658133  -0.3339456  -0.32771517 -0.1214095   0.17008013
  0.60740024  0.22492556 -0.01633838 -0.21157885 -0.27896827 -0.27765971
 -0.10762048]

原始序列是有8的季节性,自相关检测也看到了在8的整数倍的偏移处得到了较高的自相关值。

将相关指标聚类(Cluster Correlated Metrics Together)

我们可以用Normalized Cross Correlation,根据相似度将相关性较大的metric聚类。

使用数据集:graphs45.csv

import numpy as np
import pandas as pd

def get_correlation_table(metric_df):
    metric_cnt = metric_df.shape[1]
    correlation_table = np.zeros((metric_cnt, metric_cnt))
    for i in range(metric_cnt):
        metric_1 = metric_df.iloc[:, i]
        for j in range(metric_cnt):
            if i == j:
                continue
            else:
                metric_2 = metric_df.iloc[:, j]
                cc_ary = ccf(metric_1, metric_2, unbiased=False)
                correlation_table[i, j] = cc_ary[0]
    return correlation_table


def find_related_metric(correlation_table, orig, high_corr):
    metric_corr_table = correlation_table[orig]
    corr_metric_lst = []
    for i in range(len(metric_corr_table)):
        if metric_corr_table[i] > high_corr:
            corr_metric_lst.append(i)

    return corr_metric_lst

if __mian__:
    metric_df = pd.read_csv("./graphs45.csv")
    correlation_table_ary = get_correlation_table(metric_df)

    orig = 3
    high_corr = 0.9
    corr_metric_lst = find_related_metric(correlation_table_ary, orig, high_corr)
    corr_metric_lst.append(orig)
    print(corr_metric_lst)

    pyplot.figure()
    pyplot.title("Series")
    for idx in corr_metric_lst:
        metric = metric_df.iloc[:, idx]
        pyplot.plot(range(len(metric)), metric, label=f"graph_{idx + 1}")
    pyplot.ylabel("value")
    pyplot.xlabel("index")
    pyplot.legend(loc="upper right")
    pyplot.show()

get_correlation_table()计算了所有metric之间的标准化的互相关值,结果存在correlation_table中,correlation_table[i,j]代表第i个metric和第j个metric之间的相关值。

然后find_related_metric()根据相关值表找出和graph_4相关值大于0.9的序列,最后找出的相关序列画图如下:

image

参考

  1. Understanding Cross-Correlation, Auto-Correlation, Normalization and Time Shift
  2. Detecting Correlation Among Multiple Time Series
  • 14
    点赞
  • 143
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
时间序列分析模型有以下优点和缺点: 优点: 1. 能够捕捉和利用数据中的时间相关性时间序列模型考虑了数据点之间的顺序和依赖关系,可以更好地预测未来的趋势和模式。 2. 可以处理非线性关系。时间序列模型可以捕捉到非线性的趋势和周期性,因此在处理非线性问题时比较有效。 3. 可以考虑季节性和周期性。时间序列模型可以分析和预测数据中的季节性和周期性变化,对于具有重复模式的数据集很有用。 4. 提供不同的建模技术。时间序列模型包括传统的统计方法(如ARIMA、VAR)和机器学习方法(如神经网络、支持向量回归等),可以根据具体情况选择适当的模型。 缺点: 1. 对数据质量要求较高。时间序列模型对数据的平稳性、连续性和无缺失值等要求较高,如果数据不满足这些条件,可能会导致模型不准确或无法建模。 2. 对参数选择敏感。时间序列模型中的参数选择对结果影响较大,需要通过实验或领域知识来确定最佳参数,否则可能会导致预测结果不准确。 3. 难以处理异常值和离群点。时间序列模型在处理异常值和离群点时可能会受到干扰,需要进行数据清洗或使用异常检测技术。 4. 可能不适用于复杂的非线性问题。某些复杂的非线性问题可能超出时间序列模型的建模能力,这时可能需要考虑其他类型的模型。 这些是一般性的优缺点,具体的模型在不同场景下可能会有不同的特点和适用性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值