Я пытаюсь приспособить простую синусоиду к данным и применяю границы, чтобы помочь ограничить подгонку.
Я использую второй опубликованный ответ здесь , который работает отлично, однако, когда яприменять границы в соответствии с соглашением, например:
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
, остальные могут быть бесконечными.
Фактические данные, на которых я использую эту функцию, чистые, и подгонка быстрая и действительно точная, но иногда она соответствуетфазировать весь цикл «вне шага», когда данные начинаются в +/- np.pi
или около него, они будут соответствовать ему 2*np.pi
вне фазы.
Я не могу поймать это вручную, так как это подходитна многие тысячи наборов данных, и я смотрю на относительную фазу DIFотношения между ними.
Любая помощь приветствуется, спасибо.