Levenberg-Marquardt-Algorithmus aus AlgLib



  • Hallo zusammen

    ich möchte eine Lorentzfunktion an Messwerte fitten und möchte dazu den Levenberg-Marquardt-Algorithmus einsetzen. Im Netz habe ich dazu die AlgLib gefunden, die verschiedenen Versionen von Levenberg-Marquardt implementiert hat (ich programmiere mit C#). Leider weiß ich einfach nicht wie ich den Levenberg anwenden muss. Im Netz gibt es folgendes Beispiel:

    minlm.lmstate state = new minlm.lmstate();
            minlm.lmreport rep = new minlm.lmreport();
            double[] s = new double[0];
            double x = 0;
            double y = 0;
    
            //
            // Example of solving simple task using FGJ scheme.
            //
            // Function minimized:
            //     F = (x-2*y)^2 + (x-2)^2 + (y-1)^2
            // exact solution is (2,1).
            //
            s = new double[2];
            s[0] = AP.Math.RandomReal()-0.5;
            s[1] = AP.Math.RandomReal()-0.5;
            minlm.minlmfgj(2, 3, ref s, 0.0, 0.001, 0, ref state);
            while( minlm.minlmiteration(ref state) )
            {
                x = state.x[0];
                y = state.x[1];
                if( state.needf )
                {
                    state.f = AP.Math.Sqr(x-2*y)+AP.Math.Sqr(x-2)+AP.Math.Sqr(y-1);
                }
                if( state.needfg )
                {
                    state.f = AP.Math.Sqr(x-2*y)+AP.Math.Sqr(x-2)+AP.Math.Sqr(y-1);
                    state.g[0] = 2*(x-2*y)+2*(x-2)+0;
                    state.g[1] = -(4*(x-2*y))+0+2*(y-1);
                }
                if( state.needfij )
                {
                    state.fi[0] = x-2*y;
                    state.fi[1] = x-2;
                    state.fi[2] = y-1;
                    state.j[0,0] = 1;
                    state.j[0,1] = -2;
                    state.j[1,0] = 1;
                    state.j[1,1] = 0;
                    state.j[2,0] = 0;
                    state.j[2,1] = 1;
                }
            }
            minlm.minlmresults(ref state, ref s, ref rep);
    

    Function minimized ist ja dann in meinem Fall die Lorentz-Funktion. Aber wo kann ich denn jetzt hier die Messwerte angeben, an die gefittet werden soll? Den s-vektor verstehe ich als den Vektor der optimiert werden soll, also das s in F(x,s). minlmfgj werden folgende Parameter übergeben:

    N       -   dimension, N>1
                M       -   number of functions f[i]
                X       -   initial solution, array[0..N-1]
                EpsF    -   stopping criterion. Algorithm stops if
                            |F(k+1)-F(k)| <= EpsF*max{|F(k)|, |F(k+1)|, 1}
                EpsX    -   stopping criterion. Algorithm stops if
                            |X(k+1)-X(k)| <= EpsX*(1+|X(k)|)
                MaxIts  -   stopping criterion. Algorithm stops after MaxIts iterations.
                            MaxIts=0 means no stopping criterion.
    

    Hat schonmal jemand damit gearbeitet und kann mir ein bisschen auf die Sprünge helfen? Das wäre super, ich komme da gerade einfach nicht weiter.



  • Wenn du das obige Beispiel auf einen Satz Messwerte adaptieren willst, müsstest du die Funktion F als Minimierungskriterium (z.B. nach der Summe der kleinsten Quadrate) definieren. Also wenn L(s,x) deine Lorentz-Funktion ist, sowas wie:

    F(s, xi, yi) = ∑( [L(s, xi) - yi]^2, i=0..n)
    http://de.wikipedia.org/wiki/Methode_der_kleinsten_Quadrate

    In der C++ Variante von AlgLib gibts eine Beispiel-Datei namens _demo_minlm_fj2.cpp ...das sollte recht gut zu übertragen sein. Der Levenberg-Marquardt ist "nur" eine multidimensionale, numerische Minimumsuche.

    MfG


Anmelden zum Antworten