实时时间序列数据中的峰值信号检测Matlab R Golang Python Swift Groovy C ++ C ++ Rust Scala Kotlin Ruby Fortran Julia C
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实时时间序列数据中的峰值信号检测Matlab R Golang Python Swift Groovy C ++ C ++ Rust Scala Kotlin Ruby Fortran Julia C相关的知识,希望对你有一定的参考价值。
更新:迄今为止表现最佳的算法is this one。
该问题探讨了用于检测实时时间序列数据中的突然峰值的稳健算法。
请考虑以下数据集:
p = [1 1 1.1 1 0.9 1 1 1.1 1 0.9 1 1.1 1 1 0.9 1 1 1.1 1 1 1 1 1.1 0.9 1 1.1 1 1 0.9 1, ...
1.1 1 1 1.1 1 0.8 0.9 1 1.2 0.9 1 1 1.1 1.2 1 1.5 1 3 2 5 3 2 1 1 1 0.9 1 1 3, ...
2.6 4 3 3.2 2 1 1 0.8 4 4 2 2.5 1 1 1];
(Matlab格式,但它不是关于语言,而是关于算法)
你可以清楚地看到有三个大峰和一些小峰。此数据集是问题所涉及的时间序列数据集类的特定示例。这类数据集有两个一般特征:
- 基本噪音具有一般意义
- 存在明显偏离噪声的大“峰值”或“更高数据点”。
我们还假设如下:
- 峰的宽度不能预先确定
- 峰的高度明显偏离其他值
- 使用的算法必须计算实时(因此每个新数据点都会改变)
对于这种情况,需要构造触发信号的边界值。但是,边界值不能是静态的,必须基于算法实时确定。
我的问题:什么是实时计算这些阈值的好算法?这种情况是否有特定的算法?什么是最知名的算法?
强大的算法或有用的见解都受到高度赞赏。 (可以用任何语言回答:它是关于算法的)
Smoothed z-score algo (peak detection with robust threshold)
我构建了一种适用于这些类型数据集的算法。它基于dispersion的原理:如果一个新的数据点是一个给定的x个标准偏差,远离某些移动平均值,算法信号(也称为z-score)。该算法非常稳健,因为它构造了单独的移动平均值和偏差,使得信号不会破坏阈值。因此,无论先前信号的量如何,未来信号都以大致相同的精度被识别。该算法需要3个输入:lag = the lag of the moving window
,threshold = the z-score at which the algorithm signals
和influence = the influence (between 0 and 1) of new signals on the mean and standard deviation
。例如,lag
为5将使用最后5个观察值来平滑数据。如果数据点与移动平均值相差3.5个标准偏差,则threshold
为3.5将发出信号。而0.5的influence
给出正常数据点具有一半影响的信号。同样,influence
为0会完全忽略信号以重新计算新阈值。因此0的影响是最强大的选择(但假设stationarity);将影响选项置于1是最不稳健的。因此,对于非平稳数据,影响选项应该放在介于0和1之间的位置。
它的工作原理如下:
伪代码
# Let y be a vector of timeseries data of at least length lag+2
# Let mean() be a function that calculates the mean
# Let std() be a function that calculates the standard deviaton
# Let absolute() be the absolute value function
# Settings (the ones below are examples: choose what is best for your data)
set lag to 5; # lag 5 for the smoothing functions
set threshold to 3.5; # 3.5 standard deviations for signal
set influence to 0.5; # between 0 and 1, where 1 is normal influence, 0.5 is half
# Initialise variables
set signals to vector 0,...,0 of length of y; # Initialize signal results
set filteredY to y(1),...,y(lag) # Initialize filtered series
set avgFilter to null; # Initialize average filter
set stdFilter to null; # Initialize std. filter
set avgFilter(lag) to mean(y(1),...,y(lag)); # Initialize first value
set stdFilter(lag) to std(y(1),...,y(lag)); # Initialize first value
for i=lag+1,...,t do
if absolute(y(i) - avgFilter(i-1)) > threshold*stdFilter(i-1) then
if y(i) > avgFilter(i-1) then
set signals(i) to +1; # Positive signal
else
set signals(i) to -1; # Negative signal
end
# Make influence lower
set filteredY(i) to influence*y(i) + (1-influence)*filteredY(i-1);
else
set signals(i) to 0; # No signal
set filteredY(i) to y(i);
end
# Adjust the filters
set avgFilter(i) to mean(filteredY(i-lag),...,filteredY(i));
set stdFilter(i) to std(filteredY(i-lag),...,filteredY(i));
end
可以在下面找到为数据选择好参数的经验法则。
Demo
可以在here找到此演示的Matlab代码。要使用该演示,只需运行它并通过单击上方图表自行创建时间序列。在绘制lag
观测数后,该算法开始工作。
Result
对于原始问题,此算法在使用以下设置时将提供以下输出:lag = 30, threshold = 5, influence = 0
:
Implementations in different programming languages:
- Matlab(我)
- R(我)
- Golang(Xeoncross)
- Kazkhsvpoi(R Kiselev)
- Python(我)
- Swift(JoshuaCWebDeveloper)
- Groovy(布拉德)
- Cajaxasopi(Animase Panda)
- C++(swizard)
- C++(Mike Roberts)
- Rust(leoderprofi)
- Scala(Kimmo Lehto)
- Kotlin [用于共振检测](THo)
- Ruby(马特营)
- Fortran(海洋空投)
- Julia(DavidC)
- Coxspoi(Tn 15)
Rules of thumb for configuring the algorithm
C#:滞后参数决定了数据的平滑程度以及算法对数据长期平均值变化的适应性。你的数据越C,你应该包括更多的滞后(这应该提高算法的稳健性)。如果您的数据包含随时间变化的趋势,您应该考虑您希望算法适应这些趋势的速度。即,如果你将Java设置为10,那么在将算法的阈值调整为长期平均值的任何系统变化之前需要10个“周期”。因此,请根据数据的趋势行为以及您希望算法的自适应性选择lag
参数。
stationary:此参数确定信号对算法检测阈值的影响。如果置为0,则信号对阈值没有影响,使得基于阈值来检测未来信号,该阈值利用不受过去信号影响的平均值和标准偏差来计算。考虑这个问题的另一种方法是,如果你把影响力设置为0,你就会隐含地假设平稳性(即无论有多少信号,时间序列总是在长期内恢复到相同的平均值)。如果不是这种情况,则应将影响参数置于介于0和1之间的某个位置,具体取决于信号可以系统地影响数据的时变趋势的程度。例如,如果信号导致时间序列的长期平均值的lag
,则影响参数应该被置高(接近1),因此阈值可以快速适应这些变化。
lag
:阈值参数是移动平均值的标准偏差数,超过该标准偏差算法将新数据点分类为信号。例如,如果新数据点高于移动平均值4.0标准偏差且阈值参数设置为3.5,则算法将数据点识别为信号。应根据预期的信号数设置此参数。例如,如果您的数据是正态分布的,则阈值(或:z分数)为3.5对应于0.00047(来自influence
)的信令概率,这意味着您希望每2128个数据点(1 / 0.00047)发出一次信号。因此,阈值直接影响算法的灵敏度,从而也影响算法发出信号的频率。检查您自己的数据并确定一个合理的阈值,使算法在您需要时发出信号(此处可能需要一些试错,以达到您的目的的良好阈值)。
警告:上面的代码每次运行时都会循环遍历所有数据点。实现此代码时,请确保将信号的计算拆分为单独的函数(没有循环)。然后当一个新的数据点到达时,更新structural break, 以上是关于实时时间序列数据中的峰值信号检测Matlab R Golang Python Swift Groovy C ++ C ++ Rust Scala Kotlin Ruby Fortran Julia C的主要内容,如果未能解决你的问题,请参考以下文章threshold
和this table