如何摆脱时间序列数据中的背景噪音?

机器算法验证 r 时间序列 生物统计学
2022-03-27 07:19:26

我在实地考察时从一些鸟类那里收集了大量的时间深度数据。

我试图通过设置深度阈值来对潜水行为进行分类,超过该深度阈值可以说发生了潜水。然而,数据中存在在鸟类内部和鸟类之间变化的背景噪声,这使得确定固定阈值存在问题(对于一只鸟来说,它主要会捕捉到潜水,但对于另一只鸟会捕捉到所有东西 - 见图)。

有没有办法将数据转换为“展平”背景噪声的基线,例如 0,以便深度值 > 0 可以捕获所有尖峰?

我知道有各种聚类技术可以很容易地在这里对潜水行为进行分类,但问题是我之后必须从加速度和深度值的滚动窗口创建一个巨大的数据集(用于深度学习),以及二进制值最后指示是否在该窗口内发生了潜水,并且使用可变阈值执行此操作会使事情变得非常复杂。(理想情况下,我希望能够从给定窗口获取深度向量并运行一行代码,int((d_vec > thrshold).any())以确定是否发生了任何潜水)

深度时间序列示例

更新:

我制定了一个令人满意的解决方案,即采用约 30 个值的滚动窗口并将它们偏移该窗口的中值(被视为“基线”)。这很好地“平滑”了我的情节,同时保留了每次潜水的形状,但我仍然全神贯注地寻求更好的解决方案(或改进下面的代码)......

cat("\rTransforming data...")
k = 30

# take rolling median as baseline for each window
offset = zoo::rollapply(ts_data_d$Depth, width=k, by=k, FUN=median)
offset = rep(offset, each=k)

# match lengths
dif = length(ts_data_d$Depth) - length(offset)
offset = c(offset, rep(tail(offset, 1), dif))

# Zero-offset data
new_series = ts_data_d$Depth - offset
new_series[new_series<0] = 0  # negative depth meaningless
new_series[(length(new_series)-dif):length(new_series)] = 0  # no dives as device removed
ts_data_d$Depth_mod = new_series

在此处输入图像描述

2个回答

这是一个分析示例,此处change-point描述了这些工具,以及在 loess(平滑的标准方法)的上下文中,hereR 中的提供了一些可能有用的工具。请注意,在潜水期间深度读数的平均值和方差都会发生巨大变化,因此该软件包中用于评估这些基础上的变化点的工具可能会有所帮助。(但是,我没有太多的实践经验。)changepoint

在这种情况下,作为一种简单的方法,您可以考虑处理连续深度读数之间的差异。当鸟在水面上时,这些差异看起来很小,但随后在潜水期间经历了双相大幅正/负变化。然后,调用潜水的阈值可以基于这些双相变化的幅度,通过返回每次潜水的原始无差异数据来确定潜水深度。

也就是说,如果它能够可靠地执行您想要的操作,那么您使用 30 的滚动窗口的解决方案就可以了。它很好地结合了您对主题的知识,因为窗口的大小似乎足够大,可以平滑单个潜水,而不会过于激进地平滑。

您的问题可能会在https://dsp.stackexchange.com/上得到更好的答案。您在更新中描述的内容非常接近中值过滤器中值滤波器是称为阶数统计滤波器的更大类滤波器的一部分。您可能感兴趣的另一个顺序统计过滤器是LULU 过滤器

通过谷歌快速搜索,我找到了可能适用的平滑功能。