trend power lorentzian lmfit law fitting fitter fit curve_fit python scipy gaussian

python - power - scipy gaussian fit



scipy.optimize.curve_fit no puede ajustarse a la curva gaussiana sesgada desplazada (2)

Intento ajustar una curva gaussiana sesgada y desplazada usando la función curve_fit de scipy , pero me parece que bajo ciertas condiciones la adaptación es bastante pobre, a menudo me da una línea recta o casi exacta.

El código a continuación se deriva de la documentación curve_fit . El código proporcionado es un conjunto arbitrario de datos para fines de prueba, pero muestra el problema bastante bien.

import numpy as np from scipy.optimize import curve_fit import matplotlib.pyplot as plt import math as math import scipy.special as sp #def func(x, a, b, c): # return a*np.exp(-b*x) + c def func(x, sigmag, mu, alpha, c,a): #normal distribution normpdf = (1/(sigmag*np.sqrt(2*math.pi)))*np.exp(-(np.power((x-mu),2)/(2*np.power(sigmag,2)))) normcdf = (0.5*(1+sp.erf((alpha*((x-mu)/sigmag))/(np.sqrt(2))))) return 2*a*normpdf*normcdf + c x = np.linspace(0,100,100) y = func(x, 10,30, 0,0,1) yn = y + 0.001*np.random.normal(size=len(x)) popt, pcov = curve_fit(func, x, yn,) #p0=(9,35,0,9,1)) y_fit= func(x,popt[0],popt[1],popt[2],popt[3],popt[4]) plt.plot(x,yn) plt.plot(x,y_fit)

El problema parece aparecer cuando cambio el gaussiano demasiado lejos de cero (usando mu ). Intenté dar valores iniciales, incluso aquellos idénticos a mi función original, pero no resuelve el problema. Para un valor de mu=10 , curve_fit funciona perfectamente, pero si uso mu>=30 ya no se ajusta a los datos.


Dar puntos de partida para la minimización a menudo funciona de maravilla. Intente darle al minimizer información sobre la posición del máximo y el ancho de la curva:

popt, pcov = curve_fit(func, x, yn, p0=(1./np.std(yn), np.argmax(yn) ,0,0,1))

Cambiar esta única línea en su código con sigma=10 y mu=50 produce


Puede llamar a curve_fit muchas veces con una conjetura inicial aleatoria y elegir los parámetros con un error mínimo.

import numpy as np from scipy.optimize import curve_fit import matplotlib.pyplot as plt import math as math import scipy.special as sp def func(x, sigmag, mu, alpha, c,a): #normal distribution normpdf = (1/(sigmag*np.sqrt(2*math.pi)))*np.exp(-(np.power((x-mu),2)/(2*np.power(sigmag,2)))) normcdf = (0.5*(1+sp.erf((alpha*((x-mu)/sigmag))/(np.sqrt(2))))) return 2*a*normpdf*normcdf + c x = np.linspace(0,100,100) y = func(x, 10,30, 0,0,1) yn = y + 0.001*np.random.normal(size=len(x)) results = [] for i in xrange(50): p = np.random.randn(5)*10 try: popt, pcov = curve_fit(func, x, yn, p) except: pass err = np.sum(np.abs(func(x, *popt) - yn)) results.append((err, popt)) if err < 0.1: break err, popt = min(results, key=lambda x:x[0]) y_fit= func(x, *popt) plt.plot(x,yn) plt.plot(x,y_fit) print len(results)