问题描述
“任意”是指我没有在适合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