如何在数据集中找到峰?


47

如果我有一个生成如下图的数据集,我将如何算法确定所显示峰的x值(在本例中为其中的三个):

在此处输入图片说明


13
我看到六个局部最大值。您指的是哪三个?:-)。(当然,这很明显,我的意思是鼓励您更精确地定义一个“峰值”,因为这是创建良好算法的关键。)
whuber

3
如果数据是纯周期时间序列,并且添加了一些随机噪声分量,则可以拟合谐波回归函数,其中周期和幅度是根据数据估算的参数。所得模型将是一个平滑的周期函数(即,几个正弦和余弦的函数),因此,当一阶导数为零而二阶导数为负时,它将具有唯一可识别的时间点。那将是高峰。一阶导数为零而二阶导数为正的位置将被称为波谷。
Michael Chernick 2012年

2
我添加了模式标签,查看其中一些问题,他们将提供您感兴趣的答案。
安迪W

感谢大家的回答和评论,非常感谢!我将需要一些时间来理解和实现与数据相关的建议算法,但是我将确保稍后再提供反馈。
nonaxiomatic 2012年

也许是因为我的数据确实很嘈杂,但是下面的答案并没有取得任何成功。不过,我的确获得了以下答案:stackoverflow.com/a/16350373/84873
Daniel

Answers:


35

一种通用方法是对数据进行平滑处理,然后通过将局部最大滤波器与平滑处理进行比较来找到峰值。在R

argmax <- function(x, y, w=1, ...) {
  require(zoo)
  n <- length(y)
  y.smooth <- loess(y ~ x, ...)$fitted
  y.max <- rollapply(zoo(y.smooth), 2*w+1, max, align="center")
  delta <- y.max - y.smooth[-c(1:w, n+1-1:w)]
  i.max <- which(delta <= 0) + w
  list(x=x[i.max], i=i.max, y.hat=y.smooth)
}

它的返回值包括局部最大值(x)的参数(可回答问题),以及局部最大值出现的x和y数组的索引(i)。

有两种参数可根据情况调整: w是用于计算局部最大值的窗口的半角。(其值应实质上小于数据数组长度的一半。)较小的值将拾取微小的局部凸起,而较大的值将经过这些凸起。另一个(在此代码中未明确span列出)是loess平滑器的参数。(它通常介于零和一之间;它反映的是窗口宽度与x值范围的比例。)较大的值将更积极地平滑数据,从而使局部凹凸完全消失。

为了看到这种调整的效果,让我们创建一个小的测试函数来绘制结果:

test <- function(w, span) {
  peaks <- argmax(x, y, w=w, span=span)

  plot(x, y, cex=0.75, col="Gray", main=paste("w = ", w, ", span = ", span, sep=""))
  lines(x, peaks$y.hat,  lwd=2) #$
  y.min <- min(y)
  sapply(peaks$i, function(i) lines(c(x[i],x[i]), c(y.min, peaks$y.hat[i]),
         col="Red", lty=2))
  points(x[peaks$i], peaks$y.hat[peaks$i], col="Red", pch=19, cex=1.25)
}

以下是一些适用于某些合成的,噪音较小的数据的实验。

x <- 1:1000 / 100 - 5
y <- exp(abs(x)/20) * sin(2 * x + (x/5)^2) + cos(10*x) / 5 + rnorm(length(x), sd=0.05)
par(mfrow=c(3,1))
test(2, 0.05)
test(30, 0.05)
test(2, 0.2)

情节

宽窗口(中间图)或更积极的平滑(底部图)消除了在顶部图中检测到的局部最大值。此处最好的组合可能是宽窗口且只能进行柔和的平滑处理,因为积极的平滑处理似乎会移动这些峰(请参阅底部图中的中点和右点,并将它们的位置与原始数据的表观峰进行比较)。在这个例子中,w=50span=0.05做了伟大的工作(未显示)。

请注意,检测到端点处的局部最大值。这些可以单独检查。(为此,argmax返回平滑的y值。)


与针对通用工作的更为正式的建模相比,该方法具有多个优点:

  • 它没有采用任何先入为主的数据模型。

  • 可以适应数据特征。

  • 它可以适用于检测一个人感兴趣的峰的种类。


3
相反,@ Michael:我对周期性没有任何假设。实际上,该示例看起来是周期性的,但不是周期性的:请注意二次项。此示例(以及许多其他此类序列)将导致谐波回归失败。而且,我不会“视觉上”挑选出任何东西:这一切都是通过算法完成的。(为什么我会给人留下深刻的印象,即您实际上尚未阅读此答案?)
2012年

1
我可以通过一阶和二阶导数测试从算法上找到这些峰,而您需要使用其他一些方法(例如,类似于数字搜索)。我的观点不是要声称一种方法比另一种方法更好,也不是要批评您的答案。我只是看到很多相似之处和一些不同之处,我试图对您如何识别峰进行更清晰的了解。
迈克尔·切尔尼克

3
@Michael峰值是不超过移动最大值的位置。这使它们快速且易于计算:没有数值搜索,只有简单的扫描。使用微分平滑的优点是它可以在给定的x值之间内插峰:这对于粗糙或不均匀的x分辨率很有用。O(n)
ub

4
@Michael,如果您“没有时间”阅读答案/评论,那么您可以考虑避免对帖子的回复/断言。这是您反复执行的操作,通常会导致无建设性的交流和/或您做出不正确的陈述,之后又撤回。似乎浪费您的时间,以及您参与此类对话的其他人。例如,整个注释线程肯定比仅阅读答案开始花费了更多时间。为什么您选择以这种方式使用该网站仍然困扰着我。我看不出它对任何人有什么好处。
2012年

2
感谢您的有趣方法。我想我也明白了迈克尔深远的:你需要查看图表,以决定最佳的价值wspan,同时也发现,值越高,span发生转变的峰值。感觉甚至这些步骤也可以自动化。例如,对于第一个问题,如果我们可以评估发现的峰的质量,则可以optimize使用这些参数!对于第二个问题,例如,在发现的峰的任一侧选择一个窗口并寻找更高的值。
达伦·库克

1

正如我在评论中提到的,如果时间序列似乎是周期性拟合,则谐波回归模型提供了一种通过应用一阶和二阶导数测试来平滑函数并识别峰的方法。Huber指出了一种非参数测试,当存在多个峰并且该函数不一定是周期性的时,它具有优势。但是没有免费的午餐。尽管他提到了他的方法的优点,但如果参数模型合适,可能会有缺点。这始终是使用非参数技术的另一面。尽管它避免了参数假设,但当参数假设合适时,参数方法会更好。他的过程也没有充分利用数据中的时间序列结构。

我认为尽管指出建议程序的优点是适当的,但指出潜在的缺点也很重要。我的方法和Huber都以有效的方式找到了高峰。但是,我认为当局部最大值低于先前确定的最高峰时,他的程序需要做更多的工作。


2
您能否证明您的方法的“有效方式”?挑战的一部分是设计一种算法来找到多个峰-在您的情况下,这意味着找到一个(昂贵计算的)导数的所有零,而不仅仅是一个零-并明确说明您将对这些关键点进行分类作为“峰值”,哪些不是。同样,一些支持或扩大您的主张,即“在参数假设适当时,参数方法会更好”的主张,这是很好的,因为众所周知,参数假设永远不会完全正确。
ub

@whuber我说过,您会适合模型的,因为该模是正弦和余弦的和,所以该函数是周期性的,因此当一阶导数为零且二阶导数在零点都减小时,会出现峰值。这就是我说您参加一阶和二阶导数测试时的意思。现在,您可以求解以找到所有解决方案,但是如果您有一个高峰,那么其他高峰就离您所拥有的解决方案只有一个时期和多个时期。我的观点不是要主张该方法的任何优势。我只想指出,那里没有免费的午餐。
Michael Chernick 2012年

非参数方法的优点是不需要建模假设,在这种情况下,不需要周期性假设。当建模假设成立时,我关于参数化方法比非参数化方法更好的陈述应该非常熟悉。我无需争论从未完全成立的参数假设。我基本上同意这一观点。但是我说的是像皮特曼效率这样的东西。当模型“正确”时,非参数估计不如参数估计有效。
Michael Chernick 2012年

那是理论。在实践中,参数模型可以很好地逼近现实。在那种情况下,参数估计(例如mle)比非参数估计更有效。同样,参数置信区间会更好,因为它们会更紧密。但是很多时候您都不知道参数模型对您的示例有多好。在这种情况下,您必须在使用非参数方法的保守主义(安全)或使用参数方法的粗体(可能错误)之间做出选择。
Michael Chernick 2012年

1
我要提出的建议是,迈克尔,在这种情况下,非参数方法可能会比任何参数方法都要好得多,除非数据分裂得特别接近模型,即使这样它也会表现良好。假设周期性是一个很好的例子:您的算法将产生与数据中偏离周期性相同数量级的误差。犯此类错误的可能性使渐近效率提高所带来的任何优势均告无效。在不首先进行广泛的GoF测试的情况下使用这样的过程将是一个坏主意。
ub

1

信号处理中的经典峰值检测方法如下:

  1. 根据采样率和信号属性,将信号过滤到合理的合理范围内,例如,对于ECG,使用IIR带通滤波器@ 0.5-20Hz,零相位滤波器将确保不引入相移(以及相关的时滞)
  2. 然后可以使用希尔伯特变换或小波方法来强调峰
  3. 然后可以应用静态或动态阈值,其中高于阈值的所有样本均视为峰值。在动态阈值的情况下,通常将其定义为均值的移动平均估计值之上或之下的阈值N个标准偏差。

另一种可行的方法是将尖锐的高通滤波信号与高度平滑的信号(低通或中值滤波)进行比较,然后应用步骤3。

希望这可以帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.