Kubische Regression

Es gibt 23 Antworten in diesem Thema. Der letzte Beitrag () ist von faxe1008.

    Kubische Regression

    Hallo,

    Ich habe mal wieder eine Mathe bezogene Frage:

    Wie kann man anhand von zwei Messpunkten innerhalb einer Reihe von Punkten ( P1 und P2) die Formel einer Quadratischen Regressionskurve berechnen. Für die lineare und expotenzielle ist das kein Problem:

    lineare Regression:
    f(x) = mx+b
    (P1.Y -P2.Y) / (P1.X - P2.X) = m
    P1.Y - m * P1.X = b
    => f(x) = mx + b

    expotenzielle Regression:
    f(x) = a*c^x
    (P2.Y/P1.Y) ^((P2.X - P1.X)^-1) = c
    (P1.Y / (c^P1.X)) = a
    => f(x) = a*c^x

    Wie kann ich nun eine Regressionskurve der Form f(x)= ax^3+bx^2+cx+d berechnen?

    Der Trick mit dem umformen nach einer Variablen und die dann in die Ursprungsgleichung einzusetzen funktioniert (vermutlich) nicht?

    P.S: keine Mathehausaufgabe ich will nur verstehen wie der Rechner das macht.

    8-) faxe1008 8-)
    Hi
    stelle ein Gleichungsystem der Formel
    y = ax^3 + bx^2 +cx+d
    für beide Punkte auf und setze x und y ein. Dannach löst du das Gleichungssystem nach a, b, c und d auf. Allerdings erhältst du bei 2 Gleichungen unendlich viele Lösungen (oder keine, in deinem Fall aber nicht).

    Sollte das doch sein, oder?

    Gruß
    ~blaze~
    Das mit den unendlichen Lösungen ist mir auch aufgefallen.
    Wie kann ich jetzt eine davon heraussuchen?

    Problem:
    y = ax^3+bx^2+cx+d
    d = y - (ax^3+bx^2+cx)

    => y = ax^3+bx^2+cx+(y - (ax^3+bx^2+cx))

    und ab hier dann das Problem:

    (y-(ax^3+bx^2))-(y-(ax^3+bx^2+cx)) / x = c

    so aber hier müsste ich in die linke gleichung wieder das was ich für c rausgekriegt habe wieder für c einsetzen, dass wäre eine Art unendlich Schleife :huh:
    Tipps zu weiterem Vorgehen?

    8-) faxe1008 8-)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „faxe1008“ ()

    Wähle einfach zwei Parameter beliebig oder mehr Eingabewerte. Besser wäre es aber eigentlich, für n Messwerte ein (n-1)-gradiges Polynom aufzustellen. Also wenn du 2 Messwerte hast, legst du halt eine lineare Funktion durch, bei dreien eine quadratische, bei vieren eine kubische, usw. Dann kann der Benutzer durch Angabe weiterer Werte auch eine für ihn passende Annäherung wählen.

    Gruß
    ~blaze~
    Polynom ist eine Summe von Monomen, ein Monom ist sowas:
    a * x^b
    Also eine Beliebige Funktion der Form
    f(x) = a_0 + a_1 * x + a_2 * x^2 + ... a_n + x^n
    Zum Beispiel f(x) = x^2 ist ein Polynom mit Grad 2 und a_0 = 0, a_1 = 0, a_2 = 2: f(x) = a_0 + a_1 * x + a_2 * x^2 = 0 + 0 * x + x^2
    Wenn du jetzt 4 Punkte hast, löst du ein Gleichungssystem mit 4 Unbekannten:
    f(x) = a + b * x + c * x^2 + d * x^3
    y = f(x)
    Sagen wir, du hast folgende Messwerte:
    (0, 4), (1, 3), (2, 5), (3, 7)
    Dann setzt du jetzt für x immer die erste Komponente ein und für y die zweite
    a = 4
    a + b + c + d = 3
    a + 2b + 4c + 8d = 5
    a + 3b + 9c + 27d = 7
    Das löst du dann per Gaussverfahren auf. Aus der 1. Gleichung folgt eben, dass a = 4, usw.
    a = 4
    b + c + d = -1
    b + 2c + 4d = 1/2
    b + 3c + 9d = 1
    --------------------
    a = 4
    b + c + d = -1
    c + 3d = 3/2
    c + 4d = 1/2
    --------------------
    a = 4
    b + c + d = -1
    c + 3d = 3/2
    d = -1
    --------------------
    a = 4
    b + c + d = -1
    c = -3/2
    d = -1
    --------------------
    a = 4
    b = -7/2
    c = -3/2
    d = -1

    Algorithmisch ist's viel einfacher zu lösen. Schau' dir dazu mal den Gaussalgorithmus an. Das beste ist wahrscheinlich, freie Parameter immer im verbleibenden Monom mit dem höchsten Grad zu wählen und = 0 zu setzen.
    Hier noch der Link:
    de.wikipedia.org/wiki/Gau%C3%9Fsches_Eliminationsverfahren
    Führe dir dazu einfach eine Matrix-Klasse ein, die die benötigten Sachen enthält.

    Gruß
    ~blaze~
    Neue Frage:

    Was ist das Gaußverfahren?

    Ich habe das Gefühl im Bildungsplan von BaWü wurde zuviel weggekürzt :thumbdown: :thumbdown: :thumbdown:. Ich komm mir deswegen dauernd wie ein mathematischer analphabet vor wenn irgendwas im Plan fehlt ;(

    Die Idee mit der MAtrix ist interessant aber auch einem Rechner mit einem 64k Assembler wohl schlecht durchführbar (besitzt die möglichkeit nicht) ^^

    8-) faxe1008 8-)
    Das Beispiel oben führt es durch. Ich multipliziere immer Vielfache der anderen Gleichungen auf ein Gleichungssystem und löse es damit von links nach rechts auf. Das, ähm, wäre theoretisch zumindest so vorgesehen. Da ich alle Gleichungen dividieren konnte, ist die Konstante bei allen 1.
    Die erste Gleichung wird ja zu a = 4, da mit x = 0 auch x^2 = 0 und x^3 = 0. Dannach subtrahiere ich Gleichung I von den Gleichungen II- IV, um das a zu eliminieren. Das Gleiche mache ich dann mit den restlichen Gleichungen, also nachdem a eliminiert wurde, wird b eliminiert, etc.

    a = 4 (I)
    a + b + c + d = 3 (II)
    a + 2b + 4c + 8d = 5 (III)
    a + 3b + 9c + 27d = 7 (IV)
    --------------------------
    a = 4 (I') = (I)
    b + c + d = -1 (II') = (II) - (I)
    b + 2c + 4d = 1/2 (III') = ((III) - (I))/2
    b + 3c + 9d = 1 (IV') = ((IV) - (I)) / 3
    --------------------
    a = 4 (I'') = (I')
    b + c + d = -1 (II'') = (II')
    c + 3d = 3/2 (III'') = ((III') - (II')) / 2
    c + 5d = 1/2 (IV'') = (IV') - (III') hier war wohl n Fehler (5 statt 4)
    --------------------
    a = 4
    b + c + d = -1
    c + 3d = 3/2
    d = -1/2
    --------------------
    a = 4
    b + c + d = -1
    c = 3
    d = -1/2
    --------------------
    a = 4
    b = -7/2
    c = 3
    d = -1/2

    Ist nur hier runtergeschrieben, da können schon paar Fehler drin sein.

    Könnte man das irgendwie anders machen? Array o.ä.?

    Gruß
    ~blaze~

    ~blaze~ schrieb:

    Besser wäre es aber eigentlich, für n Messwerte ein (n-1)-gradiges Polynom aufzustellen.
    Das geht vor die Hose, Beispiel: Ausgleichsgerade durch 2 Punkte.
    Das ist keine Regression mehr.
    @faxe1008: Der Grad der Regression bzw. die Kurve, die Du durch die Punkte legst, ist von der Kondition der Messwerte abhängig.
    Sicherlich kann man durch Messpunkte einer linearen Abhängigkeit (z.B. Längenausdehnung über der Temperatur) eine Ausgleichsparabel 3. Grades legen, aber das ist nicht unbedingt sinnvoll.
    Gaußverfahren: numerische Bestimmung der Lösung eines Gleichungssystems mit genau so viel Unbekannten wie Gleichungen, indem die Gleichungen mit geeigneten Faktoren multipliziertr und von anderen Gleichungen subtrahiert werden, um so die Koeffizienten zu eliminieren und final in jeder Gleichung / Zeile je einen (anderen) Koeffizienten stehen zu haben.
    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!
    OK ich habe verstanden woher du a hast (ist ja der y-achsen abschnitt)
    die vorfaktoren vor a,b etc sind die Quadrate etc. der x koordiante oder ?

    diese Zeile ist mir mittlerweile klargeworden:
    a = 4
    b + c + d = -1
    b + 2c + 4d = 1/2
    b + 3c + 9d = 1
    --------------------

    aber durchwelche schritte kommst du darauf:
    a = 4
    b + c + d = -1
    c + 3d = 3/2
    c + 4d = 1/2
    --------------------
    a = 4
    b + c + d = -1
    c + 3d = 3/2
    d = -1
    --------------------
    a = 4
    b + c + d = -1
    c = -3/2
    d = -1
    --------------------
    a = 4
    b = -7/2
    c = -3/2
    d = -1

    und geht das auch ohne die (0,y) koordinate?

    Das mit den Arrays könnte man machen diese liest man so ein : {1,12,45}. die müssen dann halt in einer liste zwischen gespeichert werden um die einzelnen items zu entnehmen.

    Ah halt ich glaub ich hab's:
    c + 3d = 3/2
    c + 4d = 1/2

    1,5 - 3d + 3d = 1,5
    0,5 - 4d + 4d = 0,5
    0,5 - 1,5 = -1
    stimmt das so?

    8-) faxe1008 8-)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „faxe1008“ ()

    Nimm einfach ein Array mit m * n Werten für die n x m-Matrix. Der Wert in Spalte i und Zeile j befindet sich dann halt am Index j * m + i.
    Also alles was ich mache ist, dass ich immer Vielfache der Gleichungen multipliziere, um zur unteren Zeilenstufenform zu gelangen. In Matrixschreibweise wäre das folgendermaßen
    1 0 0 0 | 4
    1 1 1 1 | 3
    1 2 4 8 | 5
    1 3 9 27| 7
    Im ersten Schritt subtrahierst du ein Vielfaches von Zeile 1 von allen nachfolgenden Zeilen, sodass sich für die Zelle 0 ergibt. Dannach machst du das gleiche für b, c und d, sodass folgende Matrix rauskommt:
    1 0 0 0 | 4
    0 1 1 1 | -1
    0 0 1 3 | 3/2
    0 0 0 1 | -1/2

    Dannach machst du das gleiche nochmal, sodass du eine Matrix der Form

    1 0 0 0 | 4
    0 1 0 0 | -7/2
    0 0 1 0 | 3
    0 0 0 1 | -1/2
    erhältst. Die 5. Spalte gibt dir eben einen Vektor an, der die Werte für (a, b, c, d) enthält. Schau' dir den Wikipediaartikel dazu mal an, der ist nicht schlecht.

    @RodFromGermany: Mir ist klar, dass das Verfahren in der Anwendung keinen Sinn macht, da es unwahrscheinlich ist, für eine geringe Menge an Werten eine korrekte Funktion zu finden und weil das Verfahren zur Messwertanalyse nicht taugt. Es sollte allerdings schon verständlich sein und glaube kaum, dass faxe1008 schon mit partiellen Ableitungen und sonst was zurecht kommt, va. wenn's dann noch um die Extremwertbildung und sonst was geht, das hatten wir gerade mal im Studium. Wenn doch, wäre das hier sicher einen Versuch wert: de.wikipedia.org/wiki/Methode_der_kleinsten_Quadrate
    Ich bin in der Hinsicht sicher kein Spezialist, daher hatte ich auch gefragt, ob das das gewünschte ist.

    Gruß
    ~blaze~

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „~blaze~“ ()

    Ähm ich verstehe diese Zeilen nicht so ganz

    1 0 0 0 | 4
    1 b c d | 3
    1 2 4 8 | 5
    1 3 9 27| 7
    Im ersten Schritt subtrahierst du ein Vielfaches von Zeile 1 von allen nachfolgenden Zeilen, sodass sich für die Zelle 0 ergibt. Dannach machst du das gleiche für b, c und d, sodass folgende Matrix rauskommt:
    1 0 0 0 | 4
    0 1 1 1 | -1
    0 0 1 3 | 3/2
    0 0 0 1 | -1/2

    meine Idee dahinter :wacko: :
    erstmal zeile 2,3,4 - Zeile1
    1 0 0 0 | 4
    0 1 1 1 | -1
    0 2 4 8 | 3/2
    0 3 9 27 | -1/2


    1 0 0 0 |
    0 1 1 1 |
    0 2 4 8 |
    0 3 9 27|

    jetzt zeile 3,4 - 2zeile
    1 0 0 0 |
    0 1 1 1 |
    0 0 2 6 |
    0 0 6 24 |

    irgendetwas ist da falsch gelaufen :huh: :wacko:

    klingt jetzt irgendwie faul aber gibt es dafür eine Allgemeine Formel? (mit einem Algorythmus würde ich mich auch zufrieden geben)? das war jetzt mein erster "Versuch" mit Gauß :S

    8-) faxe1008 8-)
    Ich schreibs dir noch mal schrittweise hin. Auf Wikipedia steht der Algorithmus übrigens schön erklärt. Über den hab' ich mal eine Matrix-Invertierung geschrieben.

    1 0 0 0 | 4
    1 1 1 1 | 3
    1 2 4 8 | 5
    1 3 9 27|7
    a eliminieren, also quasi die 1. Zeile von der 2., 3. und 4. mit jeweiligen Vielfachen (sind bei allen 1, da die gesamte 1. Spalte nur aus 1-en besteht) abziehen, sodass nur in der 1. Gleichung das a noch vorkommt:
    1 0 0 0 | 4
    0 1 1 1 | -1
    0 2 4 8 | 1
    0 3 9 27|3
    wie man sieht, kann man Zeile 3 durch 2 dividieren und Zeile 4 durch 3
    1 0 0 0 | 4
    0 1 1 1 |-1
    0 1 2 4 | 1/2
    0 1 3 9 | 1
    jetzt eliminiert man b nach dem gleichen Prinzip
    1 0 0 0 | 4
    0 1 1 1 |-1
    0 0 1 3 | 3/2
    0 0 1 4 | 1
    Zeile 4 konnte man durch 2 Teilen, das hab ich gleich gemacht. Wenn man jetzt c eliminiert erhält man die Matrix
    1 0 0 0 | 4
    0 1 1 1 |-1
    0 0 1 3 | 3/2
    0 0 0 1 | -1/2
    Man will ja eigentlich auf der linken Seite die Identität
    1 0 0 0
    0 1 0 0
    0 0 1 0
    0 0 0 1
    haben, daher wendet man den Algorithmus jetzt quasi rückwärts an. Das hätte man übrigens auch schon vorher machen können.
    1 0 0 0 | 4
    0 1 1 1 |-1
    0 0 1 3 | 3/2
    0 0 0 1 | -1/2
    3 * Zeile 4 von Zeile 3 abziehen:
    1 0 0 0 | 4
    0 1 1 1 | -1
    0 0 1 0 | 3
    0 0 0 1 | -1/2
    usw. bis man die Matrix
    1 0 0 0 | 4
    0 1 0 0 | -7/2
    0 0 1 0 | 3
    0 0 0 1 | -1/2
    erhält.

    Gruß
    ~blaze~

    ~blaze~ schrieb:

    das hatten wir gerade mal im Studium
    Wenn Du Lust und Muße hast, probier Dich mal an einem Ausgleichs-Sinus.
    Das ist eine sehr interessante und dankbare Sache.
    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!
    Hi ich habe deinem Weg mal aurpobiert:

    Beispiel: f(x) = 2+3x-4x^2+2x^3
    Punkte: (1,3) (2,8) (3,29) (4,78)

    Matrix-Rechnung:

    1 1 1 1 | 3
    1 2 4 8 | 8
    1 3 9 27 |29
    1 4 16 64 |78

    1 1 1 1 | 3
    0 1 3 7 | 5
    0 2 8 26 | 26
    0 3 15 63 | 75

    1 1 1 1 | 3
    0 1 3 7 | 5
    0 1 4 13 | 13
    0 1 5 21 | 25

    1 1 1 1 | 3
    0 1 3 7 | 5
    0 0 1 6 | 8
    0 0 2 14 | 20

    1 1 1 1 | 3
    0 1 3 7 | 5
    0 0 1 6 | 8
    0 0 1 7 | 10

    1 1 1 1 | 3
    0 1 3 7 | 5
    0 0 1 6 | 8
    0 0 0 1 | 2

    so jetzt alles wieder in Formel:
    a + b + c + d = 3
    b + 3c + 7d = 5
    c + 6d = 8
    d = 2

    => c = -4
    b = 3
    a = 2
    d = 2

    Es stimmt :thumbsup:

    Wie kann ich das ganze jetzt mit Hilfe eines Intelligenten Algorytmus bewerkstelligen? (Vorzugsweise mit Arrays aber eindimensionale)?
    Linie1 = {1, P1.X, P1.X^2,P1.X ^3} etc...

    8-) faxe1008 8-)
    Stelle die Matrix einfach als Array dar. Wenn du zweidimensionale Arrays hast, könntest du die verwenden, ich bin aber grundsätzlich kein Fan davon. Besser wäre ein Array, das eben n * m Elemente (ist halt die n x m-Matrix) enthält. Den Wert in Zeile i und Spalte j erhältst du dann per i * m + j. Schreibe dir einfach eine Funktion, die das ganze kapselt (oder eine Klasse) und formuliere den Gaussalgorithmus auf der Wikipediaseite um. Der Funktioniert für beliebige Matrizen (notfalls kommt keine Lösung oder unendlich viele Lösungen raus. Unendlich viele sinds, wenn der Rang der Matrix kleiner ist, als die Anzahl der Spalten, keine, wenn er größer ist und eindeutig lösbar ist's sonst).
    Versuch' dich da einfach mal dran', das ist gar nicht so schwer.

    Gruß
    ~blaze~
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Module Module1
    2. Sub Main()
    3. Dim p1_x, p1_y, p2_x, p2_y, p3_x, p3_y, p4_x, p4_y As Double
    4. Console.WriteLine("P1.X:")
    5. p1_x = Console.ReadLine()
    6. Console.WriteLine("P1.Y:")
    7. p1_y = Console.ReadLine()
    8. Console.WriteLine("P2.X:")
    9. p2_x = Console.ReadLine()
    10. Console.WriteLine("P2.Y:")
    11. p2_y = Console.ReadLine()
    12. Console.WriteLine("P3.X:")
    13. p3_x = Console.ReadLine()
    14. Console.WriteLine("P3.Y:")
    15. p3_y = Console.ReadLine()
    16. Console.WriteLine("P4.X:")
    17. p4_x = Console.ReadLine()
    18. Console.WriteLine("P4.Y:")
    19. p4_y = Console.ReadLine()
    20. Dim Zeile1() As Integer = {1, p1_x, p1_x ^ 2, p1_x ^ 3, p1_y}
    21. Dim Zeile2() As Integer = {1, p2_x, p2_x ^ 2, p2_x ^ 3, p2_y}
    22. Dim Zeile3() As Integer = {1, p3_x, p3_x ^ 2, p3_x ^ 3, p3_y}
    23. Dim Zeile4() As Integer = {1, p4_x, p4_x ^ 2, p4_x ^ 3, p4_y}
    24. Zeile2 = Berechne_Array_Shit(Opeator.Subtrahieren, Zeile2, Zeile1)
    25. Zeile3 = Berechne_Array_Shit(Opeator.Subtrahieren, Zeile3, Zeile1)
    26. Zeile4 = Berechne_Array_Shit(Opeator.Subtrahieren, Zeile4, Zeile1)
    27. End Sub
    28. Public Enum Opeator
    29. Subtrahieren
    30. Dividieren
    31. End Enum
    32. Public Function Berechne_Array_Shit(ByVal op As Opeator, ByVal original() As Integer, ByVal abzuziehen() As Integer) As Integer()
    33. Dim returner(4) As Integer
    34. If op = Opeator.Dividieren Then
    35. returner(0) = original(0) / abzuziehen(0)
    36. returner(1) = original(1) / abzuziehen(1)
    37. returner(2) = original(2) / abzuziehen(2)
    38. returner(3) = original(3) / abzuziehen(3)
    39. returner(4) = original(4) / abzuziehen(4)
    40. End If
    41. If op = Opeator.Subtrahieren Then
    42. returner(0) = original(0) - abzuziehen(0)
    43. returner(1) = original(1) - abzuziehen(1)
    44. returner(2) = original(2) - abzuziehen(2)
    45. returner(3) = original(3) - abzuziehen(3)
    46. returner(4) = original(4) - abzuziehen(4)
    47. End If
    48. Return returner
    49. End Function
    50. End Module


    Soweit bin ich.....

    Habe nur ein Problem:

    VB.NET-Quellcode

    1. Private Function Array_ist_teilbar(ByVal arr As Integer(), ByVal numb As Integer()) As Boolean
    2. Dim boller As Boolean = False
    3. For u = 0 To 3
    4. If arr(u) Mod numb <> 0 Then
    5. boller = False
    6. End If
    7. Next
    8. Return boller
    9. End Function


    Ja ich weiß, dass man das Oben auch mit For schleifen lösen könnte weiß ich !
    Der Operator Mod ist nicht für die Typen Integer und eindimesionales Array definiert?

    8-) faxe1008 8-)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „faxe1008“ ()

    Wenn Du ein Feld übergibst, nimm halt einen Index, um auf ein Element zuzugreifen.
    Außerdem kommt da momentan immer False zurück.
    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!