- 注:这是this question的后续内容 *
用户Nick奥德尔给出了a great answer来解决curve_fit不能很好地拟合正常曲线的问题-事实证明,相对于频率的目标函数并不“好”,并且有很多局部最小值与全局最小值相距甚远。为了解决这个问题,你应该首先使用FFT来近似频率,然后将其作为你的初始猜测。这是可行的,因为它将优化器定位在全局最优值附近,所以它不会在其他地方“丢失”。
现在,我有另一个数据集,这次是一个阻尼正弦曲线。我试图使用相同的FFT技巧来获得一个良好的曲线拟合,但我得到的只是一条直线。
我的代码是在this pastebin中给出的(正如你所看到的,我发现optimize.basinhopping
工作得很好,但我希望有一个更好的版本)。
没有长数据列表的代码:
ydata=[float(_) for _ in ydata.strip().splitlines()]
from scipy.optimize import curve_fit as cf
import numpy as np
from matplotlib import pyplot as plt
from scipy.optimize import basinhopping as bh
xdata=np.arange(0.05,500.01,0.05)
def damped_sin_fun(x,a,b,c,d,e):
return a*(np.exp(-x/e))*np.sin(b*x+c)+d
fft = np.fft.fft(ydata - np.array(ydata).mean())
timestep = xdata[1] - xdata[0]
freq = np.fft.fftfreq(len(fft), d=timestep)
largest_component = np.abs(fft).argmax()
phase_guess = np.angle(fft[largest_component]) * freq[largest_component]
initial_frequency_guess = freq[largest_component] * 2 * np.pi
p_opt,p_cov=cf(damped_sin_fun,xdata,ydata, p0=[0.05, initial_frequency_guess, np.pi/2 ,np.mean(ydata),2.3])
print(initial_frequency_guess)
print(p_opt)
#print(((damped_sin_fun(xdata,*p_opt)-ydata)**2).mean())
optimize=bh(lambda args: ((damped_sin_fun(xdata,*args)-ydata)**2).mean(), [0.05, initial_frequency_guess, np.pi/2 ,np.mean(ydata),2.3]).x
plt.plot(xdata,damped_sin_fun(xdata,*p_opt))
plt.xlim((0,10))
#plt.plot(xdata,damped_sin_fun(xdata,*optimize))
#plt.plot(xdata,ydata, 'r.-', ms=1)
plt.show()
字符串
1条答案
按热度按时间oprakyz71#
我会通过将Y分解为三个信号来解决这个问题:指数项,常数项和正弦项。
字符串
然后,我将分别适合每三个之前组合它们。
为了拟合指数项,你不能只将它拟合到信号上,因为你还不知道正弦参数应该是什么。但是,你可以做的是选择一个指数项,它使信号的标准差沿着信号是恒定的。一旦信号沿着其长度具有恒定的幅度,就可以使用上一个问题中描述的过程来拟合正弦波。
在开始编写代码之前,我想特别注意这一部分:
型
说明:不可能找到每个点的标准差,我做的是在一个滚动窗口中计算标准差,窗口大小为100。(这是以样本为单位,而不是时间为单位。)对于在100个样本之前的点,它使用向后填充。这是一个有点随意的参数,但我发现
samples_per_window
的值在20到1000之间工作得相当好。拟合指数项的完整代码:
型
下面是指数项(蓝色)与目标项(橙子)的关系图。
的数据
(Note:这里的Y轴是对数的。在半对数图上,任何指数项都是直线。然而,目标不是直的。这意味着这个问题中的衰减不是严格的指数衰减。)
接下来,拟合常数项。
型
接下来,拟合正弦项。通过重新排列方程
y = exp * sine + constant
,我们可以得到正弦项本身。型
剧情:
的数据
这并没有完全消除标准差的变化,但已经足够接近了。
接下来,拟合正弦项。
型
接下来,所有的术语都可以组合在一起。
型
你可以运行另一个曲线拟合来同时调整所有参数。这与独立解的结果非常相似,但略有不同。
型
这让你很不爽