哪些技术可以有效地发现任意数据点的周期性?

问题描述

“任意”是指我没有在适合FFT的网格上采样的信号。我只知道事件发生的时间点(例如时间),例如,我想估计发生率:


const BoilingPeek = (props) => {
  return props.celsius >= 100 ? (
    <p>Water would boil.</p>
  ) : (
    <p>Water is would not boil.</p>
  );
};

class TempCalculator extends React.Component {
  constructor(props) {
    super(props);
    this.handleTempChange = this.handleTempChange.bind(this);
    this.state = {
      temperature: "",};
  }
  handleTempChange(e) {
    this.setState({ temperature: e.target.value });
  }

  render() {
    return (
      <fieldset>
        <legend>Temprature of water in celsius</legend>
        <input
          value={this.state.temperature}
          onChange={this.handleTempChange}
        />
        <BoilingPeek celsius={parseFloat(this.state.temperature)} />
      </fieldset>
    );
  }
}


ReactDOM.render(<TempCalculator/>,document.getElementById("root"))

...可能被标称周期性(重复间隔)为1.0的过程命中,但存在噪音和一些漏检现象。

是否有众所周知的处理此类数据的方法

解决方法

听起来您需要确定要确定的确切内容。如果您想知道一组时间戳的平均间隔,那么这很容易(只需取平均值或中位数即可)。

如果您希望间隔可以改变,那么您需要对间隔改变的速度有所了解。然后,您可以找到窗口移动平均线。您需要了解其变化的速度,以便可以适当地选择窗口大小-较大的窗口将为您提供更平滑的结果,但是较小的窗口将对更快的变化速度具有更好的响应。

如果您不知道数据是否遵循任何类型的模式,那么您可能正在进行数据探索。在那种情况下,我将从绘制间隔开始,看看是否有图案出现在眼中。如果数据非常嘈杂,则可以通过应用移动平均数来受益。

从本质上来说,数据中是否存在某些内容及其含义取决于您和您对域的了解。也就是说,在任何一组时间戳中,将是(您也可以轻松计算出方差以表明数据的变化性),但是由您自己决定该平均值是否包含任何意义。

,

如果正确初始化,最小二乘算法可以解决问题。为此,可以使用一种聚类方法。

当执行FFT时,信号被描述为正弦波之和。频率的幅度可以描述为由least square fit on the signal引起的。因此,如果信号采样不均匀,那么如果要估计傅立叶变换,则解决相同的最小二乘问题可能很有意义。如果应用于均匀采样的信号,则可以归结为相同的结果。

由于信号是离散的,因此您可能希望将其拟合为Dirac combs的总和。减小与狄拉克梳子最接近的狄拉克距离的平方总和似乎更合理。这是一个非线性优化问题,其中狄拉克梳子以其周期和偏移量来描述。这个非线性最小二乘问题可以通过Levenberg-Marquardt algorithm来解决。这是一个利用scipy.optimize.leastsq()函数的python示例。此外,可以如How to compute standard deviation errors with scipy.optimize.least_squares中所示估计估计周期和偏移量上的误差。它也记录在the documentation of curve_fit()Getting standard errors on fitted parameters using the optimize.leastsq method in python

尽管如此,一半的周期或周期的三分也将适合,并且周期的倍数是局部最小值,应通过优化Levenberg-Marquardt algorithm的初始化来避免。为此,可以将事件时间之间的差异进行聚类,聚类的最小值是预期时间段。根据{{​​3}}中的建议,应用了聚类功能Clustering values by their proximity in python (machine learning?)

请注意,该过程可以扩展到多维数据,以查找具有不同基本周期的周期性模式或混合周期性模式。

import numpy as np

from scipy.optimize import least_squares
from scipy.optimize import leastsq

from sklearn.cluster import MeanShift,estimate_bandwidth

ticks=[0,1.1,1.9,3,3.9,6.1]

import scipy
print scipy.__version__


def crudeEstimate():
    # loooking for the period by looking at differences between values :
    diffs=np.zeros(((len(ticks))*(len(ticks)-1))/2)
    k=0
    for i in range(len(ticks)):
        for j in range(i):
            diffs[k]=ticks[i]-ticks[j]
            k=k+1
    #see https://stackoverflow.com/questions/18364026/clustering-values-by-their-proximity-in-python-machine-learning
    X = np.array(zip(diffs,np.zeros(len(diffs))),dtype=np.float)
    bandwidth = estimate_bandwidth(X,quantile=1.0/len(ticks))
    ms = MeanShift(bandwidth=bandwidth,bin_seeding=True)
    ms.fit(X)
    labels = ms.labels_
    cluster_centers = ms.cluster_centers_
    print cluster_centers
    labels_unique = np.unique(labels)
    n_clusters_ = len(labels_unique)

    for k in range(n_clusters_):
        my_members = labels == k
        print "cluster {0}: {1}".format(k,X[my_members,0])
    estimated_period=np.min(cluster_centers[:,0])
    return estimated_period

def disttoDiracComb(x):
    residual=np.zeros((len(ticks)))
    for i in range(len(ticks)):
        mindist=np.inf
        for j in range(len(x)/2):
            offset=x[2*j+1]
            period=x[2*j]
            #print period,offset
            index=np.floor((ticks[i]-offset)/period)
           
            #print 'index',index
            currdist=ticks[i]-(index*period+offset)
            
            if currdist>0.5*period:
                 currdist=period-currdist
                 index=index+1
            #print 'event at ',ticks[i],'not far from index ',index,'(',currdist,')'
            #currdist=currdist*currdist
            #print currdist
            if currdist<mindist:
                 mindist=currdist
        residual[i]=mindist
    #residual=residual-period*period
    #print x,residual
    return residual


estimated_period=crudeEstimate()
print 'crude estimate by clustering :',estimated_period

xp=np.array([estimated_period,0.0])
#res_1 = least_squares(disttoDiracComb,xp,method='lm',xtol=1e-15,verbose=1)


p,pcov,infodict,mesg,ier=leastsq(disttoDiracComb,x0=xp,ftol=1e-18,full_output=True)
#print ' p is ',p,'covariance is ',pcov

# see https://stackoverflow.com/questions/14581358/getting-standard-errors-on-fitted-parameters-using-the-optimize-leastsq-method-i
s_sq = (disttoDiracComb(p)**2).sum()/(len(ticks)-len(p))
pcov=pcov *s_sq

perr = np.sqrt(np.diag(pcov))
#print 'estimated standard deviation on parameter :',perr 

print 'estimated period is ',p[0],' +/- ',1.96*perr[0]
print 'estimated offset is ',p[1],1.96*perr[1]

应用于您的样本,它会打印:

crude estimate by clustering : 0.975
estimated period is  1.0042857141346768  +/-  0.04035792507868619
estimated offset is  -0.011428571139828817  +/-  0.13385206912205957