Pyts入门之时间序列的分解---奇异谱分析(七)

简介

Pyts库针对时间序列的分解,只有一种算法,即奇异谱分析(Singular Spectrum Analysis),它能将时间序列分解为趋势和噪音两部分,它的名字的由来和奇异值分解有关,实际上SSA的实质就是将协方差矩阵进行奇异值分解(singular value decomposition),再对得到的奇异值进行谱分析变换,所以它的算法包含以下过程(由于比较复杂,此处简要叙述重点,如需详情请自行查看wiki或者搜索引擎):
1.嵌入矩阵(embedding),或者其实就是我们之前学过的窗口变换,把时间序列变为存在很多窗口的矩阵。即以下这种形式,

在这里插入图片描述
2.对协方差矩阵进行奇异值分解(这步是关键)。这里的协方差矩阵S或者说相关系数矩阵S其实就是XX^T,怎么算的可能有人不理解,我放一个油管视频的图在这里。
在这里插入图片描述
注意图片里手放的第二排。然后在SSA里有一点令人迷惑的是…它确定了这个神奇的公式:
在这里插入图片描述
并且此处U是正交的,代入之后总之就变成了以下东西:
在这里插入图片描述
其中带根号的就是特征值也就是油管图片中的西格玛符号。
3.分组(grouping)。简单理解就是把总的索引分成了m个子集。
4.对角线平均化(Diagonal averaging)。过程依然复杂,总之就是把上面的重组成了m个子序列。

API

class pyts.decomposition.SingularSpectrumAnalysis
(window_size=4, groups=None)
参数 说明
window_size int or float,窗口大小,小数就是总长度x小数,窗口的实际大小会通过以下公式计算:max(2, ceil(window_size * n_timestamps(序列长度,或者说特征数目)))
groups None, int or array-like,算法第三步的分组数目,如果为None,直接跳过分组,如果为整数则为分组数目,同时组边界是np.linspace(0, window_size, groups + 1).astype(‘int64’),或者可以传入索引数组

就两个参数,具体说明一下第二个分组参数:
1.关于索引数组。
假如传入以下索引数组:

groups = np.arange(i, i + 5) for i in range(0, 11, 5)
print(groups)
#[array([0, 1, 2, 3, 4]), array([5, 6, 7, 8, 9]), array([10, 11, 12, 13, 14])]

和你直接传入groups=3,也就是:

print(np.linspace(0, 15, 3+1).astype('int64'))
#array([ 0,  5, 10, 15], dtype=int64)

的结果是一样的,所以如果是按顺序传入索引的话,不如直接写整数。
2.Groups有几个,最后得到的特征X的第二维度就有几个(也就是分解得到的时间序列有几个),啥意思直接看以下官网示例:

import numpy as np
import matplotlib.pyplot as plt
from pyts.decomposition import SingularSpectrumAnalysis

# 100个样本,48个时间点
n_samples, n_timestamps = 100, 48

# 随机生成数据集
rng = np.random.RandomState(41)
X = rng.randn(n_samples, n_timestamps)

# 分解成三个时间序列
window_size = 15
groups = [np.arange(i, i + 5) for i in range(0, 11, 5)]

# SSA
ssa = SingularSpectrumAnalysis(window_size=15, groups=groups)
X_ssa = ssa.fit_transform(X)

# 作图部分,第一幅为原时间序列,第二幅为转换后的对比
plt.figure(figsize=(16, 6))

ax1 = plt.subplot(121)
ax1.plot(X[0], 'o-', label='Original')
ax1.legend(loc='best', fontsize=14)

ax2 = plt.subplot(122)
for i in range(len(groups)):
    ax2.plot(X_ssa[0, i], 'o--', label='SSA {0}'.format(i + 1))
ax2.legend(loc='best', fontsize=14)

plt.suptitle('Singular Spectrum Analysis', fontsize=20)

plt.tight_layout()
plt.subplots_adjust(top=0.88)
plt.show()

在这里插入图片描述
分解后得到的三个时间序列,蓝色虚线为趋势,橙色和绿色都为噪音,这是groups=3的时候,
在这里插入图片描述
groups=4时,
在这里插入图片描述
在这里插入图片描述

总结

SSA分解时间序列得到的趋势可以用来进行预测,但其是建立在弱平稳时间序列的基础上。从方法论上讲似乎处于传统方法的范畴,例如ARMA,ARIMA其实也是对时间序列进行分解。pyts目前也只有这一个模块,感觉分解的方法并不理想?毕竟现实的时间序列非常复杂,在平稳性上都不能满足要求,可能还是神经网络更符合现实的预测要求吧…
ps:最近工作上的糟心事越来越多了,导致现在才发文,本来早就想写了…

猜你喜欢

转载自blog.csdn.net/weixin_43945848/article/details/123869027
今日推荐