Ajustement d'un seul paramètre d'une fonction avec de nombreux paramètres en python
En python, j'ai une fonction qui a beaucoup de paramètres. Je veux adapter cette fonction à un ensemble de données, mais en utilisant un seul paramètre, le reste des paramètres que je veux fournir par moi-même. Voici un exemple:
def func(x,a,b):
return a*x*x + b
for b in xrange(10):
popt,pcov = curve_fit(func,x1,x2)
En cela, je veux que le montage soit fait uniquement pour a
et le paramètre b
prend la valeur de la variable de boucle. Comment cela peut-il être fait?
4 réponses
, Vous pouvez envelopper func
dans un lambda, comme suit:
def func(x,a,b):
return a*x*x + b
for b in xrange(10):
popt,pcov = curve_fit(lambda x, a: func(x, a, b), x1, x2)
Un lambda est une fonction anonyme, qui en Python ne peut être utilisée que pour des fonctions simples d'une ligne. Fondamentalement, il est normalement utilisé pour réduire la quantité de code lorsque vous n'avez pas besoin d'attribuer un nom à la fonction. Une description plus détaillée est donnée dans la documentation officielle: http://docs.python.org/tutorial/controlflow.html#lambda-forms
Dans ce cas, un lambda est utilisé pour corriger l'un des arguments de func
. La fonction nouvellement créée n'accepte que deux arguments: x
et a
, alors que b
est fixé à la valeur tirée de la variable locale b
. Cette nouvelle fonction est ensuite passée dans curve_fit
comme argument.
Au lieu d'utiliser la fonction lambda qui pourrait être moins intuitive à digérer, je recommande de spécifier le paramètre scikit curve_fit bounds
qui forcera votre paramètre à être recherché dans des limites personnalisées.
Tout ce que vous avez à faire est de laisser votre variable un se déplacer entre -inf et +inf et votre variable b entre (b - epsilon) et (b + epsilon)
Dans votre exemple:
epsilon = 0.00001
def func(x,a,b):
return a*x*x + b
for b in xrange(10):
popt,pcov = curve_fit(func,x1,x2, bounds=((-np.inf,b-epsilon), (np.inf,b+epsilon))
Il y a une option plus simple si vous êtes prêt/capable de modifier la fonction d'origine.
Redéfinissez votre fonction comme:
def func(x,a):
return a*x*x + b
Ensuite, vous pouvez simplement le mettre dans la boucle pour le paramètre b:
for b in xrange(10):
popt,pcov = curve_fit(func, x1, x2)
Mise en garde: la fonction doit être définie dans le même script dans lequel elle est appelée pour que cela fonctionne.
Une meilleure approche utiliserait lmfit
, qui fournit une interface de niveau supérieur pour l'ajustement de la courbe. Parmi les autres fonctionnalités, Lmfit fait des paramètres d'ajustement des objets de première classe qui peuvent avoir des limites OU être explicitement fixés (entre autres fonctionnalités).
En utilisant lmfit, ce problème peut être résolu comme:
from lmfit import Model
def func(x,a,b):
return a*x*x + b
# create model
fmodel = Model(func)
# create parameters -- these are named from the function arguments --
# giving initial values
params = fmodel.make_params(a=1, b=0)
# fix b:
params['b'].vary = False
# fit parameters to data with various *static* values of b:
for b in range(10):
params['b'].value = b
result = fmodel.fit(ydata, params, x=x)
print(": b=%f, a=%f+/-%f, chi-square=%f" % (b, result.params['a'].value,
result.params['a'].stderr,
result.chisqr))