平滑时间序列数据

机器算法验证 时间序列 平滑 信号处理 爪哇
2022-02-13 08:05:10

我正在构建一个在睡眠期间记录加速度计数据的 android 应用程序,以便分析睡眠趋势并可选择在浅睡眠期间在所需时间附近唤醒用户。

我已经构建了收集和存储数据以及警报的组件。我仍然需要以一种真正有意义和清晰的方式来解决显示和保存睡眠数据的问题,这种方式最好也适合于分析。

几张图说两千字:(因为rep少只能发一个链接)

这是未经过滤的数据,运动的总和,每隔 30 秒收集一次

和相同的数据,通过我自己的移动平均平滑表现来平滑

编辑)两个图表都反映了校准——有一个最小的“噪声”滤波器和最大的截止滤波器,以及一个警报触发水平(白线)

不幸的是,这两个都不是最佳解决方案——第一个对于普通用户来说有点难以理解,而第二个更容易理解,隐藏了很多真正发生的事情。特别是平均消除了运动尖峰的细节——我认为这些可能是有意义的。

那么为什么这些图表如此重要呢?这些时间序列在整个晚上作为反馈显示给用户,并将被存储以供以后查看/分析。平滑将理想地降低内存成本(RAM 和存储),并使这些资源匮乏的手机/设备上的渲染速度更快。

显然有一种更好的方法来平滑数据——我有一些模糊的想法,例如使用线性回归来找出运动中的“急剧”变化,并据此修改我的移动平均平滑。在我一头扎进可以更优化解决的问题之前,我真的需要更多的指导和输入。

谢谢!

4个回答

首先,压缩和分析/呈现的要求不一定相同——事实上,对于分析,您可能希望保留所有原始数据并能够以各种方式对其进行切片和切块。什么最适合你,很大程度上取决于你想从中得到什么。但是您可以尝试一些标准技巧:

  • 使用差异而不是原始数据
  • 使用阈值去除低级噪声。(结合差分忽略小的变化。)
  • 使用某个时间窗口的方差而不是平均值来捕捉活动水平而不是运动
  • 将时基从固定间隔更改为可变长度运行,并累积成单个数据点序列的变化,某些标准适用于这些变化(例如,相同方向的差异,达到某个阈值)
  • 将数据从实际值转换为序数(例如低、中、高);您也可以在时间箱而不是单个样本上执行此操作 - 例如,每 5 分钟的活动水平
  • 使用适当的卷积核* 比移动平均线更巧妙地平滑,或挑选出感兴趣的特征,例如急剧变化。
  • 使用FFT库计算功率谱

对于您的目的,最后一个可能有点贵,但可能会为您提供一些非常有用的演示选项,例如“睡眠节奏”等。(我对 Android 几乎一无所知,但可以想象一些/许多/所有手机可能内置了您可以利用的 DSP 硬件。)


* 考虑到中央卷积对数字信号处理的影响,很难在网上找到可访问的介绍。或者至少在 3 分钟的谷歌搜索中。欢迎提出建议!

有许多非参数平滑算法,包括样条和黄土。但他们也会消除突然的变化。低通滤波器也是如此。我认为您可能需要一个基于小波的平滑器,它允许突然跳跃但仍然平滑噪声。

查看Percival 和 Walden (2000)以及相关的R 包虽然你想要一个 java 解决方案,但 R 包中的算法是开源的,你也许可以翻译它们。

这与您的要求有些相切,但可能值得一看卡尔曼滤波器。

Savitzky-Golay 平滑可能是一个很好的答案。这是在滑动时间窗口(对该数据的卷积)上进行最小二乘平滑的一种非常有效的实现,归结为只需将每个时间窗口中的数据乘以固定常数。您可以拟合值、导数、二阶导数等。

您可以根据滑动时间窗口的大小和多项式在该时间窗口上的拟合程度来选择允许结果的尖锐程度。这最初是为色谱法开发的,其中峰是结果的重要组成部分。SG 平滑的一个理想特性是保留峰值的位置。例如,具有三次曲线拟合的 5 到 11 点窗口可以减少噪声,但仍保留峰值。

Wikipedia 上有一篇很好的文章,尽管它被称为 Savitzky-Golay过滤器(对系统控制理论和时间序列分析的正常术语以及原始论文,它被正确地称为平滑)进行了轻微的暴力)。另请注意,维基百科文章中关于二阶导数估计公式的错误(争论) - 请参阅该文章的谈话部分。编辑:维基百科文章已修复