一尘不染

从手机的加速度计检测定期数据

algorithm

我正在开发一个Android应用程序,并且需要检测用户上下文(如果步行或开车很少)

我正在使用加速度计和所有轴的总和来检测加速度矢量。它在行走时可以看到一些周期值的方式运行得很好。但是我需要以编程方式检测这些异常事件。

请问有什么数学函数可以检测一组值中的周期吗?我听说傅里叶变换可用于此目的,但我真的不知道如何实现它。看起来很复杂:)

请帮忙


阅读 336

收藏
2020-07-28

共1个答案

一尘不染

自相关是检测数据周期性的最简单方法。这也很容易实现。要获得自相关,i只需将数据的每个数据点乘以每个数据点即可i。这是一些伪代码:

for i = 0 to length( data ) do
  autocorrel[ i ] = 0;
  for j = 0 to length( data ) do
     autocorrel[ i ] += data( j ) * data( ( j + i ) mod length( data ) )
  done
done

这将为您提供一组值。最高的“周期性”在具有最高值的索引处。这样,您可以提取任何周期性的部分(通常不止一个)。

我也建议您不要尝试在应用程序中实现自己的FFT。尽管此算法非常适合学习,但仍有很多错误是很难测试的,而且很可能您的实现将比现有的实现慢很多。如果在您的系统上有可能,我建议您使用FFTW,这在FFT实现方面在任何方面都无法超越。

编辑:

说明,为什么这对即使不是完全重复的值也有效:

计算自相关的通常且完全正确的方法是从数据中减去均值。假设您有[1, 2, 1.2, 1.8 ]。然后您可以从每个样本中提取1.5,从而剩下[-.5, .5, -.3, .3 ]。现在,如果将其与自身乘以零的偏移量,则负数将乘以负数,正数将乘以正数,从而得出(-.5)^2 + (.5)^2 + (-.3)^2 + (.3)^2=.68。负数将与负数乘以正数,产生负数(-.5)*(.5) + (.5)*(-.3) + (-.3)*(.3) + (.3)*(-.5)=-.64。在两个偏移量处,负数将再次乘以负数,正数将乘以正数。在偏移量为3的情况下,类似于偏移量为1的情况再次发生。如您所见,在偏移量0和2(句点)处获得正值,在偏移量1和4处获得负值。

现在只检测周期就不必减去均值了。如果您仅按原样保留样本,则每次添加时都会添加所求平均值。由于将为每个计算出的系数添加相同的值,因此比较将产生与您首先减去均值相同的结果。最坏的情况是,您的数据类型可能会用完(如果您使用某种整数类型),或者当值开始变大时(如果使用float,通常这不是问题),您可能会遇到舍入错误。如果发生这种情况,请先减去均值,然后尝试结果是否有所改善。

使用自相关与某种快速傅立叶变换相比,最大的缺点是速度。就像O(n^2)FFT一样,自动迭代占据了优势O(n log(n))。如果您需要非常频繁地计算很长序列的周期,则自动序列化可能不适用于您的情况。

如果你想知道的傅里叶变换的作品,什么这一切的东西关于实部和虚部,幅度和相位如何(看看马努-
贴例如代码)的手段,我建议你看看这个书

编辑2:

在大多数情况下,数据既不是完全周期性的,也不是完全混乱且非周期性的。通常,您的数据将由多个周期性成分组成,并且强度各不相同。周期是一个时差,通过它您可以移动数据以使其与自身相似。如果将数据移动一定量,则自相关将计算数据的相似程度。因此,它为您提供了所有可能时期的力量。这意味着没有“重复值索引”,因为当数据是完全周期性时,所有索引都会重复。具有最强值的索引可为您提供偏移,在该偏移处数据与自身最相似。因此,该索引提供了时间偏移,而不是数据的索引。为了理解这一点,重要的是要理解,

如果您需要在很长的时间序列中检测到这种情况,通常最好还是在数据上滑动一个窗口,然后检查此较小数据帧的周期。但是,您必须知道,窗口将为数据增加其他时间,您必须注意这些时间。

我在上次编辑中发布的链接中有更多内容。

2020-07-28