我首先生成一个虚拟余弦波周期的样本
from math import *
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
fs = 1000 # Sampling rate (Hz)
T = .1 # Length of collection (s)
windowlength = int(fs*T) # Number of samples
f0 = 10 # Fundamental frequency of our wave (Hz)
wave = [0]*windowlength
for x in range(windowlength):
wave[x] = cos(2*pi*f0*x/fs)
t = np.linspace(0,T,int(fs*T)) # This will be our x-axis for plotting
然后,我尝试将这些样本拟合为一个函数,并改编scipy提供的官方示例中的代码:https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html
# Define function to fit
def sinefit(x, A, ph, f):
return A * np.sin(2*pi*f * x + ph)
# Call curve_fit
popt,cov = curve_fit(sinefit, t, wave, p0=[1,np.pi/2,10])
# Plot the result
plt.plot(t, wave, 'b-', label='data')
plt.plot(t, sinefit(t, *popt), 'r-', label='fit')
print("[Amplitude,phase,frequency]")
print(popt)
这给了我popt = [1.,1.57079633,9.9]和情节
我的问题是:为什么我的频率不正常?我用余弦波的确切参数初始化了curve_fit函数,因此LM算法的第一次迭代难道不应该意识到残差为零并且已经得出正确答案了吗?振幅和相位似乎都是这种情况,但是频率太低了0.1Hz。
我希望这是一个愚蠢的编码错误,因为原始波形和拟合在图中清楚地排列了起来。我还确认了在整个样本中它们之间的差异为零。如果它们确实异相.1 Hz,则在我的100ms窗口中将有3.6度的相移。
任何想法都将不胜感激!
答案 0 :(得分:1)
问题是您的数组t
不正确。 t
中的最后一个值为0.1,但是采样周期为1 / fs = 0.001,t
中的最后一个值应为0.099。也就是说,这100个样本的时间为[0,0.001,0.002,...,0.098,0.099]。
您可以使用任一方法正确创建t
t = np.linspace(0, T, int(fs*T), endpoint=False)
或
t = np.arange(windowlength)/fs # Use float(fs) if you are using Python 2