2016-10-17 6 views
2

Я выполняю кривую с scipy.optimize.leastsq. Например. для гауссовых:Scipy.optimize - подгонка кривой с фиксированными параметрами

def fitGaussian(x, y, init=[1.0,0.0,4.0,0.1]): 
    fitfunc = lambda p, x: p[0]*np.exp(-(x-p[1])**2/(2*p[2]**2))+p[3] # Target function 
    errfunc = lambda p, x, y: fitfunc(p, x) - y # Distance to the target function 
    final, success = scipy.optimize.leastsq(errfunc, init[:], args=(x, y)) 
    return fitfunc, final 

Теперь я хочу по желанию исправить значения некоторых параметров в подгонке. Я нашел, что предложения должны использовать другой пакет lmfit, которого я хочу избежать, или очень общие, например here. Так как мне нужно решение, которое

  1. работы с Numpy/SciPy (без каких-либо дополнительных пакетов и т.д.)
  2. не зависит от самих параметров,
  3. является гибким, в котором параметры фиксированные или нет,

я придумал следующее, используя условие по каждому из параметров:

def fitGaussian2(x, y, init=[1.0,0.0,4.0,0.1], fix = [False, False, False, False]): 
    fitfunc = lambda p, x: (p[0] if not fix[0] else init[0])*np.exp(-(x-(p[1] if not fix[1] else init[1]))**2/(2*(p[2] if not fix[2] else init[2])**2))+(p[3] if not fix[3] else init[3]) 
    errfunc = lambda p, x, y: fitfunc(p, x) - y # Distance to the target function 
    final, success = scipy.optimize.leastsq(errfunc, init[:], args=(x, y)) 
    return fitfunc, final 

Пока это прекрасно работает, это не практично, не красиво. Итак, мой вопрос: есть ли лучшие способы выполнения кривой в scipy для фиксированных параметров? Или есть обертки, которые уже включают такую ​​фиксацию параметра?

+0

Было бы неплохо иметь эту функциональность в scipy, но я не уверен, существует ли она. Из любопытства, почему вы хотите избежать lmfit? Это очень просто использовать в моем опыте. –

+0

Причина, по которой я хочу избежать других пакетов, заключается в том, что мне нужно будет убедиться, что они правильно установлены на любом из компьютеров, на которых выполняется эта программа. – ImportanceOfBeingErnest

ответ

1

Используя scipy, нет встроенных опций, о которых я знаю. Вы всегда будете работать, как тот, который вы уже сделали.

Если вы согласны использовать пакет обертки, могу ли я рекомендовать свои собственные symfit? Это оболочка до scipy с удобочитаемостью и с меньшим количеством стандартного кода в качестве основных принципов. В symfit, ваша проблема будет решена, как:

from symfit import parameters, variables, exp, Fit, Parameter 

a, b, c, d = parameters('a, b, c, d') 
x, y = variables('x, y') 

model_dict = {y: a * exp(-(x - b)**2/(2 * c**2)) + d} 

fit = Fit(model_dict, x=xdata, y=ydata) 
fit_result = fit.execute() 

Линия a, b, c, d = parameters('a, b, c, d') делает четыре Parameter объекты. Чтобы исправить, например, параметр c к исходному значению, необходимо выполнить следующие действия в любом месте перед вызовом fit.execute():

c.value = 4.0 
c.fixed = True 

Таким образом возможный конечный результат может быть:

from symfit import parameters, variables, exp, Fit, Parameter 

a, b, c, d = parameters('a, b, c, d') 
x, y = variables('x, y') 

c.value = 4.0 
c.fixed = True 

model_dict = {y: a * exp(-(x - b)**2/(2 * c**2)) + d} 

fit = Fit(model_dict, x=xdata, y=ydata) 
fit_result = fit.execute() 

Если вы хотите быть более динамичным в вашем коде, вы может сделать Parameter объектов сразу, используя:

c = Parameter(4.0, fixed=True) 

Для получения дополнительной информации, проверьте документы: http://symfit.readthedocs.io/en/latest/tutorial.html#simple-example