Solver - Legen einer durch Gleichung definierten Kurve durch eine Punktwolke nach der Methode der kleinsten Quadrate

    • VB.NET
    • .NET (FX) 4.0

      Solver - Legen einer durch Gleichung definierten Kurve durch eine Punktwolke nach der Methode der kleinsten Quadrate

      Moin Leute,
      im Thread Anpassen einer Funktion an Messdaten mit Hilf eines Solvers habe ich einen Algorithnus gebaut, der 3 Parameter der Gleichung f(x) = lgEta0 - log10(1 + 10 ^ (alpha * (x - lgGP0)) iterativ verbessert.
      Da der Algorithmus an sich von allgemeinem Interesse sein dürfte, poste ich das ganze mal hier.
      Die Punktwolke liegt hier als Text in den Ressourcen, das können natürlich beliebige andere Quellen sein.
      Ablauf:
      • Die Funktion TargetFunction() gibt zu einem gegebenen x-Wert den aktuellen Funktionswert y zurück, der durch das aktuelle Parameterset definiert ist.
      • Die Funktion StandardDeviation() berechnet zum aktuellen Parameterset die Standardabweichung Sigma aller Werte der Punktwolke und der kommunizierenden Werte der Target-Funktion.
      • Dies wird für jeden Parameter 3 Mal mit den Parameterwerten { p - Delta, p, p + Delta } durchgeführt und es werden 3 Sigma-Werte bestimmt.
      • Durch diese 3 Sigma-Werte wird eine Parabel gelegt und deren Minimum als neuer Wert für den Parameter genommen.
      • Das ganze von vorn.
      Das ganze wird so lange durchgeführt, bis die Parameter sich (praktisch) nicht mehr ändern oder die Standardabweichung kleiner als eine Zielgröße ist.
      Der Ablauf wird hier von einem Timer getriggert, da sieht man sehr schön, wie sich die theoretische Kurve an die Sollkurve anschmiegt.
      Wichtig ist die Wahl geeigneter Startwerte, hier funktionieren die Werte 1,1,1 sehr gut.

      Wird bei der Berechnung des Parabelminimums der Bereich +-Delta verlassen, wird dies auf das 1,5-fache der Schrittweite begrenzt.

      Für den "industriellen Einsatz" sollte die Berechnung volldtändig in Double erfolgen, hier wurde Single verwendet, um bei der grafischen Darstellung nicht permanent casten zu müssen.
      Auch ist ein Timer hinderlich, wenn es auf Performance ankommt.

      Theoretisch lassen sich mit dieser Methode beliebige Punktwolken mit beliebig vielen Parametern berechnen, dazu ist allerdings etwas Fingerspitzengefühl erforderlich.
      Wenn in der TargetFunction() durch einen Parameter dividiert wird, ist darauf zu achten, dass dieser Parameter größer als ein Epsilon ist.

      Viel Spaß beim Spielen.
      Solver.zip
      Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
      Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
      Ein guter .NET-Snippetkonverter (der ist verfügbar).
      Programmierfragen über PN / Konversation werden ignoriert!