Límites de ajuste de curva de optimización de Scipy

¿Hay alguna manera en que pueda proporcionar límites para el ajuste de curva optimizado de Scipy?

Mi ejemplo

def optimized_formula(x, m_1, m_2, y_1, y_2, ratio_2): return (log(x[0]) * m_1 + m_2)*((1 - x[1]/max_age)*(1-ratio_2)) + ((log(x[1]) * y_1 + y_2)*(x[1]/max_age)*ratio_2) popt, pcov = optimize.curve_fit(optimized_formula, usage_and_age, prices) 

x [0] es age y max_age es una constante. Teniendo esto en cuenta, a medida que x [0] se acerca al máximo, x [1] / max_age se acerca a 1.

¿Es posible proporcionar una restricción / límite mediante el cual x [1] / max_age> 0.3 y x [1] / max_age <0.7 y otras restricciones como m_1 0, etc.?

Como se sugiere en otra respuesta, podría usar lmfit para este tipo de problemas. Por lo tanto, agrego un ejemplo sobre cómo usarlo en caso de que alguien también esté interesado en este tema.

Digamos que tienes un conjunto de datos de la siguiente manera:

 xdata = np.array([177.,180.,183.,187.,189.,190.,196.,197.,201.,202.,203.,204.,206.,218.,225.,231.,234., 252.,262.,266.,267.,268.,277.,286.,303.]) ydata = np.array([0.81,0.74,0.78,0.75,0.77,0.81,0.73,0.76,0.71,0.74,0.81,0.71,0.74,0.71, 0.72,0.69,0.75,0.59,0.61,0.63,0.64,0.63,0.35,0.27,0.26]) 

y desea ajustar un modelo a los datos que se ven así:

 model = n1 + (n2 * x + n3) * 1./ (1. + np.exp(n4 * (n5 - x))) 

con las restricciones que

 0.2 < n1 < 0.8 -0.3 < n2 < 0 

Usando lmfit (versión 0.8.3) lmfit el siguiente resultado:

 n1: 0.26564921 +/- 0.024765 (9.32%) (init= 0.2) n2: -0.00195398 +/- 0.000311 (15.93%) (init=-0.005) n3: 0.87261892 +/- 0.068601 (7.86%) (init= 1.0766) n4: -1.43507072 +/- 1.223086 (85.23%) (init=-0.36379) n5: 277.684530 +/- 3.768676 (1.36%) (init= 274) 

introduzca la descripción de la imagen aquí

Como puede ver, el ajuste reproduce muy bien los datos y los parámetros están en los rangos solicitados.

Aquí está el código completo que reproduce la ttwig con algunos comentarios adicionales:

 from lmfit import minimize, Parameters, Parameter, report_fit import numpy as np xdata = np.array([177.,180.,183.,187.,189.,190.,196.,197.,201.,202.,203.,204.,206.,218.,225.,231.,234., 252.,262.,266.,267.,268.,277.,286.,303.]) ydata = np.array([0.81,0.74,0.78,0.75,0.77,0.81,0.73,0.76,0.71,0.74,0.81,0.71,0.74,0.71, 0.72,0.69,0.75,0.59,0.61,0.63,0.64,0.63,0.35,0.27,0.26]) def fit_fc(params, x, data): n1 = params['n1'].value n2 = params['n2'].value n3 = params['n3'].value n4 = params['n4'].value n5 = params['n5'].value model = n1 + (n2 * x + n3) * 1./ (1. + np.exp(n4 * (n5 - x))) return model - data #that's what you want to minimize # create a set of Parameters # 'value' is the initial condition # 'min' and 'max' define your boundaries params = Parameters() params.add('n1', value= 0.2, min=0.2, max=0.8) params.add('n2', value= -0.005, min=-0.3, max=10**(-10)) params.add('n3', value= 1.0766, min=-1000., max=1000.) params.add('n4', value= -0.36379, min=-1000., max=1000.) params.add('n5', value= 274.0, min=0., max=1000.) # do fit, here with leastsq model result = minimize(fit_fc, params, args=(xdata, ydata)) # write error report report_fit(params) xplot = np.linspace(min(xdata), max(xdata), 1000) yplot = result.values['n1'] + (result.values['n2'] * xplot + result.values['n3']) * \ 1./ (1. + np.exp(result.values['n4'] * (result.values['n5'] - xplot))) #plot results try: import pylab pylab.plot(xdata, ydata, 'k+') pylab.plot(xplot, yplot, 'r') pylab.show() except: pass 

EDITAR:

Si usa la versión 0.9.x necesita ajustar el código en consecuencia; marque aquí qué cambios se han realizado de 0.8.3 a 0.9.x.

Nota: Nuevo en la versión 0.17 de SciPy

Supongamos que desea ajustar un modelo a los datos que se parecen a esto:

 y=a*t**alpha+b 

y con la restricción de alfa

 0 

Mientras que otros parámetros a y b permanecen libres. Entonces deberíamos usar la opción de límites de Optimize.curve_fit:

 import numpy as np from scipy.optimize import curve_fit def func(t, a,alpha,b): return a*t**alpha+b param_bounds=([-np.inf,0,-np.inf],[np.inf,2,np.inf]) popt, pcov = optimize.curve_fit(func, xdata,ydata,bounds=param_bounds) 

La fuente esta aqui

Pruebe el módulo lmfit ( http://lmfit.github.io/lmfit-py/ ). Agrega una forma de fijar o establecer límites en los parámetros para muchas de las rutinas de optimización en scipy.optimize, incluidos los mínimos cuadrados, y proporciona muchas herramientas para facilitar el ajuste.

Dado que curve_fit() utiliza un enfoque de mínimos cuadrados, es posible que desee ver scipy.optimize.fmin_slsqp() , que permite realizar optimizaciones restringidas. Revisa este tutorial sobre cómo usarlo.