web-dev-qa-db-fra.com

Python curve_fit avec plusieurs variables indépendantes

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.

39
rferdinand

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]]))
47
xnx

Oui, il y a: donnez simplement curve_fit un tableau multidimensionnel pour xData.

0
Marcus Müller
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)
0
Abhishek Kumar

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:

enter image description here

0
Markus Dutschke