trend power lorentzian lmfit law fitting fitter fit curve_fit python scipy curve-fitting

power - Python curve_fit con mĂșltiples variables independientes



scipy gaussian fit (5)

Puede pasar curve_fit una matriz multidimensional para las variables independientes, pero su func debe aceptar lo mismo. Por ejemplo, llamando a esta matriz X y descomprimiéndola en x , y para mayor claridad:

import numpy as np from scipy.optimize import curve_fit def func(X, a, b, c): x,y = X return np.log(a) + b*np.log(x) + c*np.log(y) # some artificially noisy data to fit x = np.linspace(0.1,1.1,101) y = np.linspace(1.,2., 101) a, b, c = 10., 4., 6. z = func((x,y), a, b, c) * 1 + np.random.random(101) / 100 # initial guesses for a,b,c: p0 = 8., 2., 7. print curve_fit(func, (x,y), z, p0)

Da el ajuste:

(array([ 9.99933937, 3.99710083, 6.00875164]), array([[ 1.75295644e-03, 9.34724308e-05, -2.90150983e-04], [ 9.34724308e-05, 5.09079478e-06, -1.53939905e-05], [ -2.90150983e-04, -1.53939905e-05, 4.84935731e-05]]))

El curve_fit de Python calcula los parámetros de mejor ajuste para una función con una sola variable independiente, pero ¿hay alguna manera, usando curve_fit u otra cosa, para ajustar una función con múltiples variables independientes? Por ejemplo:

def func(x, y, a, b, c): return log(a) + b*log(x) + c*log(y)

donde x e y son la variable independiente y nos gustaría ajustar para a, b y c.


Sí, hay: simplemente dele a curve_fit una matriz multidimensional para xData .


Si. Podemos pasar múltiples variables para curve_fit . He escrito un código:

import numpy as np x = np.random.randn(2,100) w = np.array([1.5,0.5]).reshape(1,2) esp = np.random.randn(1,100) y = np.dot(w,x)+esp y = y.reshape(100,)

En el código anterior he generado x un conjunto de datos 2D en forma de (2,100), es decir, hay dos variables con 100 puntos de datos. He ajustado la variable dependiente y con variables independientes x con algo de ruido.

def model_func(x,w1,w2,b): w = np.array([w1,w2]).reshape(1,2) b = np.array([b]).reshape(1,1) y_p = np.dot(w,x)+b return y_p.reshape(100,)

Hemos definido una función modelo que establece una relación entre y & x .
Nota: La forma de salida de la función del modelo o y pronosticada debe ser (longitud de x ,)

popt, pcov = curve_fit(model_func,x,y)

El popt es una matriz numpy 1D que contiene parámetros predichos. En nuestro caso hay 3 parámetros.


Ajuste a un número desconocido de parámetros

En este ejemplo, intentamos reproducir algunos datos medidos measData . En este ejemplo, measData es generado por la función measuredData(x, a=.2, b=-2, c=-.8, d=.1) . Practico, podríamos haber medido measData de alguna manera, por lo que no tenemos idea de cómo se describe matemáticamente. De ahí el ajuste.

polynomFit(inp, *args) mediante un polinomio, que se describe mediante la función polynomFit(inp, *args) . Como queremos probar diferentes órdenes de polinomios, es importante ser flexible en la cantidad de parámetros de entrada. Las variables independientes (x e y en su caso) están codificadas en las ''columnas'' / segunda dimensión de inp .

import numpy as np import matplotlib import matplotlib.pyplot as plt from scipy.optimize import curve_fit def measuredData(inp, a=.2, b=-2, c=-.8, d=.1): x=inp[:,0] y=inp[:,1] return a+b*x+c*x**2+d*x**3 +y def polynomFit(inp, *args): x=inp[:,0] y=inp[:,1] res=0 for order in range(len(args)): print(14,order,args[order],x) res+=args[order] * x**order return res +y inpData=np.linspace(0,10,20).reshape(-1,2) inpDataStr=[''({:.1f},{:.1f})''.format(a,b) for a,b in inpData] measData=measuredData(inpData) fig, ax = plt.subplots() ax.plot(np.arange(inpData.shape[0]), measData, label=''measuered'', marker=''o'', linestyle=''none'' ) for order in range(5): print(27,inpData) print(28,measData) popt, pcov = curve_fit(polynomFit, xdata=inpData, ydata=measData, p0=[0]*(order+1) ) fitData=polynomFit(inpData,*popt) ax.plot(np.arange(inpData.shape[0]), fitData, label=''polyn. fit, order ''+str(order), linestyle=''--'' ) ax.legend( loc=''upper left'', bbox_to_anchor=(1.05, 1)) print(order, popt) ax.set_xticklabels(inpDataStr, rotation=90)

Resultado:


def func(X, a, b, c): x,y = X return np.log(a) + b*np.log(x) + c*np.log(y) # some artificially noisy data to fit x = np.linspace(0.1,1.1,101) y = np.linspace(1.,2., 101) a, b, c = 10., 4., 6. z = func((x,y), a, b, c) * 1 + np.random.random(101) / 100 # initial guesses for a,b,c: p0 = 8., 2., 7. print curve_fit(func, (x,y), z, p0)