奇异谱分析
奇异谱分析简介
奇异谱分析(SSA)是一种谱估计方法,可以作为一种自适应信号分解工具,将信号分解为若干个分量,在不剔除任何信息的情况下,所有SSA分量之和可以完美重构回之前的时间序列。
但奇异谱分析的亮点在于,它可以将时间序列分解成趋势项、季节项、噪音等等,将其中的噪音进行提取并剔除是最常用的一种应用,因此奇异谱分析在时间序列预测中多用于降噪处理。
奇异谱分析算法过程
总述
奇异谱分析的原理大致可以分为四步:构成轨迹矩阵——奇异值分解——分组——通过对角线平均法重构信号。接下来对每一步进行通俗的介绍,以便理解。
嵌入
将一维原始时间序列数据构建轨迹矩阵
输入:1.原始时间序列 2.窗口长度
输出:轨迹矩阵
将原始序列(一维数据)类似样本熵分组那样,依次往后平移一个进行区间划分,将划分出来的数据作为一列,组合拼成轨迹矩阵。
注意:分组的个数一定要保证窗口长度大于1小于等于N/2。
# step1 嵌入windowLen = 20 # 嵌入窗口长度 一定确保窗口长度小于seriesLen = len(series) # 序列长度K = seriesLen - windowLen + 1 #轨迹矩阵一共有多少列数据X = np.zeros((windowLen, K))for i in range(K): X[:, i] = series[i:i + windowLen]
# step1 嵌入
windowLen = 20 # 嵌入窗口长度 一定确保窗口长度小于
seriesLen = len(series) # 序列长度
K = seriesLen - windowLen + 1 #轨迹矩阵一共有多少列数据
X = np.zeros((windowLen, K))
for i in range(K):
X[:, i] = series[i:i + windowLen]
分解
进行奇异值及其对应特征向量的分解
输入:轨迹矩阵
输出:多个可以加和生成轨迹矩阵的分量
通过奇异值分解,求奇异值以及对应的特征向量,其中的个特征值由大到小对角线排列。
通过把特征向量矩阵单拎出来,用单列特征项向量和轨迹矩阵进行处理,生成轨迹矩阵的分量(我的理解:每个分量分别代表每个特征值对应的在轨迹矩阵中的信息)
# step2: SVD奇异值分解, U和sigma已经按升序排序U, sigma, VT = np.linalg.svd(X, full_matrices=False)for i in range(VT.shape[0]): VT[i, :] *= sigma[i]A = VT
# step2: SVD奇异值分解, U和sigma已经按升序排序
U, sigma, VT = np.linalg.svd(X, full_matrices=False)
for i in range(VT.shape[0]):
VT[i, :] *= sigma[i]
A = VT
分组
将分解得到的矩阵单拎出来,进行分组。去噪的环节。
输入:1.分组数量 2.如何分组 3.其中的哪几组用于重构信号
输出:保留了哪几组轨迹矩阵的分量的加和
可以不等距的将轨迹矩阵的分量进行分组,然后决定哪几组是用来重构的。
最常见的方法是,将轨迹矩阵的分量划分为两组,第一组有多少个是根据提前设置的阈值,当特征值的依次加和/总特征值的和 达到阈值时,以此为界限,进行两组的划分。
# 分组的代码部分和重构混合在一起,见重构部分代码。
重构
对角平均法重构信号,将矩阵转换成多个一维数据,然后进行相加成一条一维数据。
输入:保留了哪几组轨迹矩阵的分量的加和
输出:重构之后的一维数据(已去噪)
使用对角平均法,将进行重构的每组轨迹矩阵分量的加和分别进行对角平均,每个对应一个一维的数据,将多个一维的数据进行加和,完成重构。
# 分组+重组rec = np.zeros((windowLen, seriesLen))for i in range(windowLen): for j in range(windowLen - 1): for m in range(j + 1): rec[i, j] += A[i, j - m] * U[m, i] rec[i, j] /= (j + 1) for j in range(windowLen - 1, seriesLen - windowLen + 1): for m in range(windowLen): rec[i, j] += A[i, j - m] * U[m, i] rec[i, j] /= windowLen for j in range(seriesLen - windowLen + 1, seriesLen): for m in range(j - seriesLen + windowLen, windowLen): rec[i, j] += A[i, j - m] * U[m, i] rec[i, j] /= (seriesLen - j)rrr = np.sum(rec, axis=0) # 选择重构的部分,这里选了全部# 根据rec的索引选择需要的部分就可以了,比如rrr = np.sum(rec[1:5, :], axis=0)
# 分组+重组
rec = np.zeros((windowLen, seriesLen))
for i in range(windowLen):
for j in range(windowLen - 1):
for m in range(j + 1):
rec[i, j] += A[i, j - m] * U[m, i]
rec[i, j] /= (j + 1)
for j in range(windowLen - 1, seriesLen - windowLen + 1):
for m in range(windowLen):
rec[i, j] += A[i, j - m] * U[m, i]
rec[i, j] /= windowLen
for j in range(seriesLen - windowLen + 1, seriesLen):
for m in range(j - seriesLen + windowLen, windowLen):
rec[i, j] += A[i, j - m] * U[m, i]
rec[i, j] /= (seriesLen - j)
rrr = np.sum(rec, axis=0) # 选择重构的部分,这里选了全部
# 根据rec的索引选择需要的部分就可以了,比如rrr = np.sum(rec[1:5, :], axis=0)
至此,奇异谱的分析的降噪工作已完成。
注:分组环节如果不剔除噪音的话,可以完美重构回之前的原始序列。