Python curve_fit
calcule les paramètres les mieux adaptés pour une fonction avec une seule variable indépendante, mais existe-t-il un moyen, en utilisant curve_fit
ou autre chose, pour s'adapter à une fonction avec plusieurs variables indépendantes? Par exemple:
def func(x, y, a, b, c):
return log(a) + b*log(x) + c*log(y)
où x et y sont la variable indépendante et nous aimerions nous adapter à a, b et c.
Tu peux passer curve_fit
un tableau multidimensionnel pour les variables indépendantes, mais votre func
doit accepter la même chose. Par exemple, appeler ce tableau X
et le décompresser dans x
, y
pour plus de clarté:
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)
Donne l'ajustement:
(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]]))
Oui, il y a: donnez simplement curve_fit
un tableau multidimensionnel pour xData
.
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)
Ajustement à un nombre inconnu de paramètres
Dans cet exemple, nous essayons de reproduire certaines données mesurées measData
. Dans cet exemple, measData
est généré par la fonction measuredData(x, a=.2, b=-2, c=-.8, d=.1)
. Je pratique, nous pourrions avoir mesuré measData
d'une manière - nous n'avons donc aucune idée, comment il est décrit mathématiquement. D'où l'ajustement.
Nous nous ajustons par un polynôme, qui est décrit par la fonction polynomFit(inp, *args)
. Comme nous voulons essayer différents ordres de polynômes, il est important d'être flexible dans le nombre de paramètres d'entrée. Les variables indépendantes (x et y dans votre cas) sont encodées dans la 'colonne'/seconde dimension 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)
Résultat: