【问题标题】:Detection of regime change in time series检测时间序列中的状态变化
【发布时间】:2019-06-26 12:19:50
【问题描述】:

我想检测时间序列状态变化(或异常)。 通过政权更迭,我的意思是线性趋势被改变/打破(见下图)。

import numpy as np
import matplotlib.pyplot as plt

x = range(50)
y = [1.28, 1.28, 1.26, 1.32, 1.34, 1.33, 1.38, 1.39, 1.37, 1.42, 
1.42, 1.41, 1.39, 1.41, 1.45, 1.45, 1.46, 1.5, 1.49, 1.53, 1.53, 
1.54, 1.61, 1.59, 1.62, 1.66, 1.63, 1.66, 1.66, 1.7, 1.76, 1.84, 
1.88, 1.97, 1.94, 1.98, 2.01, 2.02, 0.73, 0.72, 0.76, 0.87, 0.97, 
1.01, 0.98, 1.16, 1.22, 1.3, 1.27, 1.33]

plt.scatter(x, y)
plt.show()

我一直在寻找一段时间,但无法找到一种方法来检测这个时间序列中的大变化。

检测差异对我来说是不够的,因为我需要能够检测到粗略的线性趋势发生了变化。数据可以从一个观测值到下一个观测值的差异很大,但趋势(线性趋势)仍然正确。

解释一下为什么我放弃了 diff 方法:

x 轴在 45-46 附近的观察显示该值出现了跳跃,但实际上处于线性趋势中,因此对我来说不是“政权更迭”。这正是我放弃 diff 方法并寻找“趋势”方法的原因。 我一直在考虑循环观察,拟合线性回归并预测下一点,计算错误等。但如果存在的话,我宁愿使用为此而制作的库。

【问题讨论】:

  • 定义“政权更迭”。而你想用这个“检测”的结果做什么?
  • 你看过thisthisthis
  • 使用np.diff()查看标记副本中的第一个答案
  • @tucson 那么请举一个例子,其中简单的差异(其绝对值)是不够的。
  • @dedObed 实际上,x 轴在 45-46 附近的观察显示了值的跳跃,这会引发相当大的差异,但实际上是线性趋势,因此不是“政权更迭” “ 为了我。这正是我放弃 diff 方法并寻找“趋势”方法的原因。

标签: python


【解决方案1】:

让我绘制数据的差异(橙色)和二阶(绿色):

据我所见,这两种方法似乎都对检测跳跃具有相当大的区别,在这种情况下,一个简单的阈值可以作为分类器。

二阶差异应该特别指示跳跃,因为您描述了任务:对于线性变化,它必然(大约)为零非跳跃部分。

重现剧情的完整代码:

import numpy as np                                                                                                                                                                                                                           
import matplotlib.pyplot as plt                                                                                                                                                                                                              


x = range(50)                                                                                                                                                                                                                                
y = [1.28, 1.28, 1.26, 1.32, 1.34, 1.33, 1.38, 1.39, 1.37, 1.42,                                                                                                                                                                             
1.42, 1.41, 1.39, 1.41, 1.45, 1.45, 1.46, 1.5, 1.49, 1.53, 1.53,                                                                                                                                                                             
1.54, 1.61, 1.59, 1.62, 1.66, 1.63, 1.66, 1.66, 1.7, 1.76, 1.84,                                                                                                                                                                             
1.88, 1.97, 1.94, 1.98, 2.01, 2.02, 0.73, 0.72, 0.76, 0.87, 0.97,                                                                                                                                                                            
1.01, 0.98, 1.16, 1.22, 1.3, 1.27, 1.33]                                                                                                                                                                                                     


def get_deltas(series):                                                                                                                                                                                                                      
    return [series[i+1] - series[i] for i in range(len(series)-1)]                                                                                                                                                                           


y_delta = get_deltas(y)                                                                                                                                                                                                                      
y_delta_delta = get_deltas(y_delta)                                                                                                                                                                                                          

plt.scatter(x, y)                                                                                                                                                                                                                            
plt.scatter(x[:-1], y_delta)                                                                                                                                                                                                                 
plt.scatter(x[:-2], y_delta_delta)                                                                                                                                                                                                           
plt.show()                                                                                                                                                                                                                                   

【讨论】:

    猜你喜欢
    • 2021-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-25
    • 2022-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多