La résolution des équations non linéaires en python
J'ai 4 non-linéaire des équations à trois inconnues X
, Y
, et Z
que je veux résoudre les. Les équations sont de la forme:
F(m) = X^2 + a(m)Y^2 + b(m)XYcosZ + c(m)XYsinZ
...où a
, b
et c
sont des constantes qui dépendent de chaque valeur de F
dans les quatre équations.
Quelle est la meilleure façon de résoudre ce problème?
- Juste pour info: Il est plus courant d'utiliser x, y, et z pour les variables indépendantes (c'est à dire les personnes connues, dans ce cas), et a, b, c pour les paramètres du modèle que vous essayez de résoudre. Quand j'ai lu votre équation, j'étais sur le point de dire "mais c'est linéaire" (c'est en fonction de a, b et c). Je sais que c'est idiot d'ergoter sur la terminologie, mais comme il est actuellement libellé, beaucoup de gens sont susceptibles de mal lu votre question. (Bon, question claire, cependant. +1)
- Aussi, il est possible de linéariser cette. Je suis taper une réponse, mais je n'ai pas le temps de la finir à l'instant. Si personne ne répond, dans l'intervalle, je vais finir ma réponse et de le publier dans une heure ou deux (j'espère que quelqu'un d'autre ne me battre pour elle). Bonne chance!
- Le plus paresseux façon (mais plus facile à mettre en œuvre, je pense) est de précalculer pour n (disons 10) les valeurs de chaque paramètre (donc 1000 combinaisons au total), et de voir quelle combinaison des scores plus proche de zéro, et de zoomer autour de cette zone. Qui devrait fonctionner assez facilement pour la plupart des types d'équations, vous donnent une idée de où chercher, mais il y a plusieurs manières de fantaisie qui permettront de travailler plus rapidement et(/ou) plus précis.
scipy.optimize.brute
fait exactement ce que vous décrivez: docs.scipy.org/doc/scipy/reference/generated/.... Gardez à l'esprit que vous avez besoin de chercher un 3D de l'espace des paramètres dans ce cas. C'est simple, mais très efficace. Cela dit, si il fonctionne, il fonctionne. Si il y a beaucoup de locaux minimia et les gammes de paramètres sont bien connues, il peut être une bonne approche.- Vrai, mais la 3D est encore assez facile, et un autre avantage de la force brutale est que vous obtenez une idée de la errorbars sur votre solution. (Cela dit, dès que vous allez au-delà de la 3D, de la force brute devient désespéré)
- Pouvez-vous utiliser les sympy solveur pour ce faire?
Vous devez vous connecter pour publier un commentaire.
Il y a deux façons de le faire.
Installation
Donc, si je comprends bien votre question, vous savez F, a, b, et c à 4 points de vue différents, et que vous souhaitez inverser pour les paramètres du modèle X, Y et Z. Nous avons 3 inconnues et 4 les données observées points, donc le problème est surdéterminé. Donc, nous allons être dans la résolution de la méthode des moindres carrés sens.
Il est plus courant d'utiliser l'inverse de la terminologie dans ce cas, nous allons donc retourner votre équation de autour de. Au lieu de:
Écrivons:
Où nous savons
F
,X
,Y
, etZ
à 4 points différents (par exempleF_0, F_1, ... F_i
).Nous sommes juste en changeant les noms des variables, pas l'équation elle-même. (C'est plus pour mon aise de penser que quoi que ce soit d'autre.)
Linéaire De La Solution
Il est possible de linéariser cette équation. Vous pouvez facilement résoudre pour
a^2
,b^2
,a b cos(c)
, eta b sin(c)
. Pour rendre cela un peu plus facile, nous allons reclasser les choses encore une fois:Maintenant l'équation est beaucoup plus simple:
F_i = d + e X_i + f Y_i + g Z_i
. Il est facile de faire un linéaire des moindres carrés inversion pourd
,e
,f
, etg
. Nous pouvons alors obtenira
,b
, etc
à partir de:Bien, nous allons écrire ça sous forme de matrice. Nous allons traduire 4 observations de (le code, nous allons écrire vont prendre n'importe quel nombre d'observations, mais nous allons garder le béton à l'instant):
Dans:
Ou:
F = G * m
(je suis un geophysist, nous utilisons donc desG
pour les "Fonctions de Green" etm
pour "les Paramètres du Modèle". Habituellement, nous utiliserionsd
pour les "données" au lieu deF
, en tant que bien.)En python, ce serait traduit:
Non-linéaire de la Solution
Vous pouvez également résoudre ce à l'aide de
scipy.optimize
, comme @Joe suggéré. Le plus accessible de la fonction dansscipy.optimize
estscipy.optimize.curve_fit
qui utilise un Levenberg-Marquardt méthode par défaut.De Levenberg-Marquardt est une "escalade" de l'algorithme de bien, il va de descente, dans ce cas, mais le terme est utilisé de toute façon). Dans un sens, vous faire une estimation initiale des paramètres du modèle (tous ceux que, par défaut, dans
scipy.optimize
) et de suivre la pente deobserved - predicted
dans votre espace de paramètre descente vers le bas.Mise en garde: la Cueillette de la droite non-linéaire de la méthode d'inversion, estimation initiale, et le réglage des paramètres de la méthode est très bien un "dark art". Vous ne l'apprendre par le faire, et il y a beaucoup de situations où les choses ne fonctionnent pas correctement. De Levenberg-Marquardt est une bonne méthode si votre paramètre de l'espace est assez lisse (ce qui devrait être). Il y a beaucoup d'autres (y compris les algorithmes génétiques, réseaux de neurones, etc, en plus de méthodes plus courantes comme le recuit simulé) qui sont mieux dans d'autres situations. Je ne vais pas plonger dans la partie ici.
Il y est une commune de la chasse aux sorcières que certains d'optimisation des boîtes à outils d'essayer de corriger pour que
scipy.optimize
n'essayez pas de poignée. Si vos paramètres du modèle ont une amplitude différente (par exemple,a=1, b=1000, c=1e-8
), vous aurez besoin de redimensionner les choses de sorte qu'ils sont de même importance. Sinonscipy.optimize
s '"escalade" des algorithmes (comme LM) de ne pas calculer avec précision de l'estimation du gradient local, et donnera sauvagement des résultats inexacts. Pour l'instant, je suis en supposant quea
,b
, etc
relativement similaire des grandeurs. Aussi, sachez que presque tous les non-linéaires méthodes, vous devrez faire une estimation initiale, et sont sensibles à cette supposition. Je pars it out ci-dessous (il suffit de passer dans lep0
kwarg àcurve_fit
) car la valeur par défauta, b, c = 1, 1, 1
est une assez précise deviner poura, b, c = 3, 2, 1
.Avec les mises en garde de la route,
curve_fit
s'attend à être passé d'une fonction, d'un ensemble de points où les observations ont été faites (comme un seulndim x npoints
tableau), et les valeurs observées.Donc, si nous écrire la fonction comme ceci:
Nous aurons besoin pour l'envelopper d'accepter légèrement différents arguments avant de les passer à
curve_fit
.En un mot:
Stand-alone Exemple des deux méthodes:
Pour vous donner la pleine mise en œuvre, voici un exemple qui
Vous voudrez probablement utiliser scipy solveurs non linéaires, ils sont vraiment facile: http://docs.scipy.org/doc/scipy/reference/optimize.nonlin.html