我正在尝试将简单的正弦波拟合到数据并应用边界以帮助约束拟合。
我使用的是发布在here上的第二个答案,该答案很好用,但是当我按照惯例应用范围时,例如:
def fit_sin(tt, yy):
import scipy.optimize
import numpy as np
'''
Fit sin to the input time sequence, and return dict of fitting parameters:
"amp", "omega", "phase", "offset", "freq", "period" and "fitfunc"
'''
tt = np.array(tt)
yy = np.array(yy)
ff = np.fft.fftfreq(len(tt), (tt[1]-tt[0])) # assume uniform spacing
Fyy = abs(np.fft.fft(yy))
guess_freq = abs(ff[np.argmax(Fyy[1:])+1]) # excluding the zero frequency "peak", which is related to offset
guess_amp = np.std(yy) * 2.**0.5
guess_offset = np.mean(yy)
guess = np.array([guess_amp, 2.*np.pi*guess_freq, 0., guess_offset])
def sinfunc(t, A, w, p, c): return A * np.sin(w*t + p) + c
boundary = ([-np.inf, -np.inf, -np.pi, -np.inf],[np.inf, np.inf, np.pi, np.inf])
popt, pcov = scipy.optimize.curve_fit(sinfunc, tt, yy, p0=guess, bounds=boundary)
A, w, p, c = popt
f = w/(2.*np.pi)
fitfunc = lambda t: A * np.sin(w*t + p) + c
return {"amp": A, "omega": w, "phase": p, "offset": c, "freq": f, "period": 1./f, "fitfunc": fitfunc, "maxcov": np.max(pcov), "rawres": (guess,popt,pcov)}
我遇到以下错误:
RuntimeError: Optimal parameters not found: The maximum number of function evaluations is exceeded.
如果将边界设置为无穷大,并且将边界线更改为简单,
boundary = ([-np.inf, -np.inf, -np.inf, -np.inf],[np.inf, np.inf, np.inf, np.inf])
该功能有效。
要测试该功能,您可以执行以下操作:
import pylab as plt
N, amp, omega, phase, offset, noise = 500, 1., 2., .5, 4., 3
#N, amp, omega, phase, offset, noise = 50, 1., .4, .5, 4., .2
#N, amp, omega, phase, offset, noise = 200, 1., 20, .5, 4., 1
tt = numpy.linspace(0, 10, N)
tt2 = numpy.linspace(0, 10, 10*N)
yy = amp*numpy.sin(omega*tt + phase) + offset
yynoise = yy + noise*(numpy.random.random(len(tt))-0.5)
res = fit_sin(tt, yynoise)
print( "Amplitude=%(amp)s, Angular freq.=%(omega)s, phase=%(phase)s, offset=%(offset)s, Max. Cov.=%(maxcov)s" % res )
plt.plot(tt, yy, "-k", label="y", linewidth=2)
plt.plot(tt, yynoise, "ok", label="y with noise")
plt.plot(tt2, res["fitfunc"](tt2), "r-", label="y fit curve", linewidth=2)
plt.legend(loc="best")
plt.show()
尤其是我只是试图将拟合的阶段p
限制在-np.pi
和np.pi
之间,其他阶段可以是无穷大。
我在此功能上使用的实际数据是干净的,并且拟合很快且确实准确,但是当数据开始于+/- {{ 1}},它将适合np.pi
淘汰。
我也不能手动捕获它,因为它适合成千上万个数据集,而我正在研究它们之间的相对相位差。
任何帮助表示感谢,谢谢。
答案 0 :(得分:1)
我修复了该问题,对于一个引起麻烦的特定数据集,我的功能是拟合负振幅,然后迫使我的相位值比预期大np.pi
。
对于那些在正弦波拟合方面遇到类似麻烦的人,我将在这里留下这个答案!