Применение границ к Scipy Optimize Curvefit - PullRequest
0 голосов
/ 08 октября 2018

Я пытаюсь приспособить простую синусоиду к данным и применяю границы, чтобы помочь ограничить подгонку.

Я использую второй опубликованный ответ здесь , который работает отлично, однако, когда яприменять границы в соответствии с соглашением, например:

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отношения между ними.

Любая помощь приветствуется, спасибо.

1 Ответ

0 голосов
/ 08 октября 2018

Я исправил это, для определенного набора данных, вызывающего у меня проблемы, моя функция подбирала отрицательные амплитуды, которые затем заставляли мое значение фазы на np.pi больше, чем ожидалось.

Я оставлю этот ответ здесьдля тех, у кого есть подобные проблемы с синусоидальной установкой!

...