检测时间序列的变化(R 示例)

机器算法验证 r 时间序列 变化点 结构变化
2022-01-27 05:59:31

我想检测通常具有相同形状的时间序列数据的变化。到目前为止,我已经使用了changepointR 包和cpt.mean(), cpt.var()andcpt.meanvar()函数。cpt.mean()当数据通常停留在一个级别时,使用 PELT 方法效果很好。但是我也想检测下降过程中的变化。我想检测的一个变化示例是黑色曲线突然下降而实际上应该遵循示例性红色虚线的部分。我已经尝试过 cpt.var() 函数,但是我无法获得好的结果。你有什么建议吗(那些不一定要使用 R)?

变化曲线

这是更改的数据(作为 R 对象):

dat.change <- c(12.013995263488, 11.8460207231808, 11.2845153487846, 11.7884417180764, 
11.6865425802022, 11.4703118125303, 11.4677576899063, 11.0227199625084, 
11.274775836817, 11.03073498338, 10.7771805591742, 10.7383206158923, 
10.5847230134625, 10.2479315651441, 10.4196381241735, 10.467607842288, 
10.3682422713283, 9.7834431752935, 9.76649842404295, 9.78257968297228, 
9.87817694914062, 9.3449034905713, 9.56400153361727, 9.78120084558148, 
9.3445162813738, 9.36767436354887, 9.12070987223648, 9.21909859069157, 
8.85136359917466, 8.8814423003979, 8.61830163359642, 8.44796977628488, 
8.06957847272046, 8.37999165387824, 7.98213210294954, 8.21977468333673, 
7.683960439316, 7.73213584532496, 7.98956476021092, 7.83036046746187, 
7.64496198988985, 4.49693528397253, 6.3459274845112, 5.86993447552116, 
4.58301192892403, 5.63419551523625, 6.67847511602895, 7.2005344054883, 
5.54970477623895, 6.00011922569104, 6.882667104467, 4.74057284230894, 
6.2140437333397, 6.18511450451019, 5.83973575417525, 6.57271194428385, 
5.36261938326723, 5.48948831338016, 4.93968645996861, 4.52598133247377, 
4.56372558828803, 5.74515428123725, 5.45931581984165, 5.58701112949141, 
6.00585679276365, 5.41639695946931, 4.55361875158434, 6.23720558202826, 
6.19433060301002, 5.82989415940829, 5.69321394985076, 5.53585871082265, 
5.42684812413063, 5.80887522466946, 5.56660158483312, 5.7284521523444, 
5.25425775891636, 5.4227645808924, 5.34778016248718, 5.07084809927736, 
5.324066161355, 5.03526881241705, 5.17387528516352, 5.29864121433813, 
5.36894461582415, 5.07436929444317, 4.80619983525015, 4.42858947882894, 
4.33623051506001, 4.33481791951228, 4.38041031792294, 3.90012900415342, 
4.04262777674943, 4.34383842876647, 4.36984816425014, 4.11641092254315, 
3.83985887104645, 3.81813419810962, 3.85174630901311, 3.66434598962311, 
3.4281724860426, 2.99726515704766, 2.96694634792395, 2.94003031547181, 
3.20892607367132, 3.03980832743458, 2.85952185077593, 2.70595278908964, 
2.50931109659839, 2.1912274016859)
4个回答

您可以使用时间序列异常值检测来检测时间序列的变化。 TsayChen 和 Liu 的程序是流行的时间序列异常值检测方法。在这个网站上查看我之前的问题。

R 的tsoutlier包使用 Chen 和 Liu 的方法检测异常值。SAS/SPSS/Autobox 也可以做到这一点。请参阅下面的 R 代码以检测时间序列的变化。

library("tsoutliers")
dat.ts<- ts(dat.change,frequency=1)
data.ts.outliers <- tso(dat.ts)
data.ts.outliers
plot(data.ts.outliers)

tsoultlier 包中的 tso 函数可识别以下异常值。您可以阅读文档以了解异常值的类型。

Outliers:
  type ind time coefhat   tstat
1   TC  42   42 -2.9462 -10.068
2   AO  43   43  1.0733   4.322
3   AO  45   45 -1.2113  -4.849
4   TC  47   47  1.0143   3.387
5   AO  51   51  0.9002   3.433
6   AO  52   52 -1.3455  -5.165
7   AO  56   56  0.9074   3.710
8   LS  62   62  1.1284   3.717
9   AO  67   67 -1.3503  -5.502

该软件包还提供了不错的情节。见下文。该图显示了异常值的位置以及如果没有异常值会发生什么。

在此处输入图像描述

我还使用了名为strucchange的 R 包来检测电平变化。以您的数据为例

library("strucchange")
breakpoints(dat.ts~1)

程序正确识别断点或结构变化。

Optimal 4-segment partition: 

Call:
breakpoints.formula(formula = dat.ts ~ 1)

Breakpoints at observation number:
17 41 87 

Corresponding to breakdates:
17 41 87 

希望这可以帮助

我会从以下几个方面来处理这个问题这些只是我脑海中浮现的一些想法——请对它们持保留态度。尽管如此,我希望这将是有用的。

  • 时间序列聚类例如,通过使用流行的动态时间规整 (DTW)或替代方法。请参阅我的相关答案:on DTW for classification/clusteringon DTW or Alternatives for even time series这个想法是将时间序列聚类为“正常”和“异常”(或类似)类别。

  • 熵度量请参阅我关于时间序列熵度量的相关答案这个想法是确定“正常”时间序列的熵,然后将其与其他时间序列进行比较(这个想法假设在偏离“正常”的情况下会出现熵偏差)。

  • 异常检测请参阅我关于异常检测的相关答案(包括 R 资源)。这个想法是通过各种方法直接检测异常(请参阅参考资料)。预警信号 (EWS) 工具箱R软件包earlywarnings似乎特别有前途。

我使用 AUTOBOX 的响应与@forecaster 非常相似,但模型更简单。Box 和 Einstein 以及其他人已经考虑过保持解决方案简单但不要太简单。自动开发的模型是在此处输入图像描述. 实际和清理后的情节非常相似在此处输入图像描述残差图(应始终显示)在此处输入图像描述与残差的强制性 acf 一起在这里在此处输入图像描述残差的统计数据在比较“决斗模型”时总是有用的在此处输入图像描述实际/拟合/预测图在这里在此处输入图像描述

如果您对数据进行去趋势化,您的问题似乎会大大简化。它似乎呈线性下降。一旦您对数据进行去趋势化处理,您就可以应用各种非平稳性检验。