淘先锋技术网

首页 1 2 3 4 5 6 7

非平稳时间序列突变检测 -- Bernaola Galvan分割算法

引言

非平稳序列是指包含趋势、季节性或周期性的序列,它可能只含有其中的一种成分, 也可能是几种成分的组合,例如温度、降雨等数据。在一些研究中,如气候突变检测中,经常需要对气候数据进行突变检测。常用的突变检测方法有滑动t-检验、Cramer’s方法、Yamamoto方法、M-K突变检测方法、Pettitt方法、Bernaola Galvan分割算法等。今天主要介绍一种比较适用于非平稳时间序列的启发式突变检测方法–Bernaola Galvan分割算法(简称BG分割算法)。下图是BG算法在检测到的4个突变点。
在这里插入图片描述

去看原理

对于包含N个样本的一时间序列数据X,通过第i(2<=i<=N-1)个数据将X分割为左右两个子序列X1(包含N1个样本)和X2(包含N2个样本),分别计算两个子序列的均值m_i1、m_i2和标准差std_i1、std_i2,以及t-检验统计值T(i),其计算公式为
T(i)=abs(m_i1-m_i2)/SD(i)
其中SD(i)第i个点的合并偏差,
SD(i)=sqrt(((N1-1)*std_i1^2 + (N2-1)*std_i2^2)/(N1+N2-2))*sqrt(1/N1+1/N2)。
这样从左到右依次计算每个数据的t-检验统计值T(i),可以得到一个T序列,从中找到最大值Tmax及其所对应的索引j,如果Tmax的统计显著性P(Tmax)>=P0(P0为给定的参数),那么便可对序列X在第j个样本处进行分割,也就是突变点。P(Tmax)的计算可近似为
在这里插入图片描述
同样的,当分割完后,可以对分割后的两个子序列重复进行上述操作,直到不可分割为止,便可以得到所有的突变点。

实现

在这里,采用Python实现上述原理,并通过测试用例数据(用例数据随机生成)进行验证,具体如下:

# -*- coding: utf-8 -*-
# @Author: 武辛
# @Email: [email protected]
# @Note: 如有疑问,可加微信"wxid-3ccc"
# @All Rights Reserved!import pandas as pd
import numpy as np
import scipy.special
import math, sys
import random
import matplotlib.pyplot as plt
np.random.seed(0)def main():
​
  data = pd.read_csv("data.csv")
  X = list(data["X"])
​
  P0 = 0.95
  MIN_SUB_LENGTH = 100
  N = len(X)
  flag = [0] * N
  results = {}
​
  T, Tmax, Tmax_idx, PTmax = FindTmax(X)
  print(PTmax)
  if PTmax < P0:
    print("No find!")
    sys.exit()
​
  flag[Tmax_idx] = 1
  break_idx = [0, Tmax_idx, len(X)-1]
  results[Tmax_idx] = {"Tmax":Tmax, "T":T, "PTmax":PTmax, "start_idx":0, "end_idx":len(X)-1, "break_order":1}
  ...

结果

在这里插入图片描述
第一栏为原始序列数据,可以看出,存在4个比较明显的突变。第2-5栏为BG算法计算t-检验统计值T的结果,在第2栏图中,红色线部分找到最大Tmax,即在第799个样本数据处存在第一个突变点,第3-5栏图中分别在7000、4999、2799处找到突变点。

原文有源码,更多内容,请关注地学分析与算法。
在这里插入图片描述