Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Partielle Ableitung numerisch berechnen
Aratar
myCSharp.de - Member



Dabei seit:
Beiträge: 126

Themenstarter:

Partielle Ableitung numerisch berechnen

beantworten | zitieren | melden

Guten Abend,

Ich habe gerade versucht die Steigung einer Funktion in einem bestimmten Punkt numerisch zu berechnen. Die mathematischen Grundlagen sind mir klar, an der Umsetzung hackt es aber.

Folgende Formel habe ich verwendet:
(f(x+h) - f(x)) / h

Nun sollte ja h gegen 0 gehen. Deshalb habe ich als kleinstmögliche Zahl die Konstante double.Epsilon verwendet.

Ist x nun aber beispielsweise 2, dann ergibt die Addition:
x + h
2 + double.Epsilon
als Resultat 2.
Das wird wohl daran liegen, dass die Zahl nicht mehr so genau dargestellt werden kann und deshalb gerundet wird. Wie ist es nun aber trotzem möglich, die Steigung so genau wie möglich zu berechnen?

Mfg
Aratar
private Nachricht | Beiträge des Benutzers
Uwe81
myCSharp.de - Member



Dabei seit:
Beiträge: 285
Herkunft: Ludwigshafen

beantworten | zitieren | melden

Hallo!

Math.Epsilon ist die kleinste positive Wert größer als 0. Der ist deutlich zu klein, um damit sinnvoll zu rechnen.

Man muss ein Wert h finden, der so groß ist, dass die Rundungsfehler keine Probleme bereiten, aber so klein, dass das mathematisch exakt genug ist.

Auf der Englischen Wikipedia Numerical differentiation steht dazu ein ganzer Abschnitt unter "Practical considerations using floating point arithmetic".

Im Wesentlichen wird dort h=sqrt(eps) * x vorgeschlagen (wobei ich das in h=sqrt(eps) * max(abs(x),1) abändern würde). Eps ist dabei das Maschinenepsilon und ungefähr 2.2e-16.


Wobei du dir überlegen solltest, symmetrische Differenzen oder Methoden höhrer Ordnung zu verwenden, das ist numerisch besser.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Uwe81 am .
private Nachricht | Beiträge des Benutzers
Cat
myCSharp.de - Member

Avatar #avatar-3070.jpg


Dabei seit:
Beiträge: 790

beantworten | zitieren | melden

Hi Aratar,

Double hat nur eine Genauigkeit von ca. 14-15 Dezimalstellen, d.h. wenn du die Zahl 2 mit z.B. 1E-20 addierst so wird auch wieder 2 rauskommen.
Du müsstest also für h etwa den Wert (x / 1E14) verwenden (oder besser noch 1E13 oder 1E12). Du siehst also, an mathematisch Null (0) wirst du so also nicht rankommen.

Um welche Funktionen handelt es sich denn?
private Nachricht | Beiträge des Benutzers
Aratar
myCSharp.de - Member



Dabei seit:
Beiträge: 126

Themenstarter:

beantworten | zitieren | melden

@Uwe81: Vielen Dank, ich hab es mal so probiert und tatsächlich einen Wert erhalten, der in meinem Fall aber leider eine zu grosse Abweichung aufweist, weshalb ich deinem Tip mit symmetrischen Differenzen und Methoden höherer Ordnung nachgehen werde.

@Cat: Es geht um keinen bestimmten Typ Funktion, was auch der Grund ist, weshalb ich es numerisch lösen möchte.

Mfg
Aratar
private Nachricht | Beiträge des Benutzers
Uwe81
myCSharp.de - Member



Dabei seit:
Beiträge: 285
Herkunft: Ludwigshafen

beantworten | zitieren | melden

Um was für Funktionen geht es denn bei dir? Und wie groß war der Fehler?

Manchmal ist garnicht die numerische Ableitung das Problem, sondern die Funktionsauswertung (hatte das Problem schonmal bei einer schlichten quadratischen Form mit wenigen hunderttausend nicht-null-Einträgen).

Brauchst du denn wirklich die Steigung? Was willst du machen? Auch hier gibt es oftmals bessere Alternativen oder Verfahren, die ohne die Ableitung auskommen. In der Optimierung z.B. ableitungsfreie Verfahren oder, wenn nur die zweite Ableitung nicht berechnet werden kann, LBFGS anstelle von expliziten numerischen zweiten Ableitungen.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Uwe81 am .
private Nachricht | Beiträge des Benutzers
Aratar
myCSharp.de - Member



Dabei seit:
Beiträge: 126

Themenstarter:

beantworten | zitieren | melden

Ich brauche die Ableitung u.a. für das Newton-Raphson-Verfahren.
Der Fehler war nicht wirklich gross, bis auf 6 Nachkommastellen war der Wert richtig, aber wenn es schon andere Verfahren gibt, welche genauer sind ziehe ich diese vor.

Da der Fehler so klein war denke ich nicht, dass es an der Funktionsauswertung lag, das wird wohl einfach die grösstmögliche zu erreichende Genauigkeit sein und mit diesem kleinen Fehler kann ich gut leben.
private Nachricht | Beiträge des Benutzers
Uwe81
myCSharp.de - Member



Dabei seit:
Beiträge: 285
Herkunft: Ludwigshafen

beantworten | zitieren | melden

Zitat
Ich brauche die Ableitung u.a. für das Newton-Raphson-Verfahren.
Da kenne ich mich leider nicht aus, ob es gute ableitungsfreie Alternativen gibt. Rekursive Bisektion ist ja im Mehrdimensionalen untauglich.
Zitat
Der Fehler war nicht wirklich gross, bis auf 6 Nachkommastellen war der Wert richtig, aber wenn es schon andere Verfahren gibt, welche genauer sind ziehe ich diese vor.
Naja, das hängt halt davon ab, wie teuer Funktionsauswertungen sind. Beim Newton-Raphson-Verfahren brauchst du ja sowieso f(x_n). Wenn du nun Symmetrische Differenzen machst, dann benötigst du noch f(x_n - h) und f(x_n + h). Wenn du einseitige Differenzen machst, dann brauchst du nur noch f(x_n + h), weil ja f(x_n) schon berechnet ist.

Für Higher-Order-Methods brauchst du entsprechend noch mehr Funktionsauswertungen.

Ist halt ein Tradeoff: Genauere Differentiation führt zu weniger Iterationen, aber die Kosten einer Iteration steigt.
Zitat
Der Fehler war nicht wirklich gross, bis auf 6 Nachkommastellen war der Wert richtig,

Das hängt natürlich vom Problem und der Größenordnung, in der die Funktionen leben, ab. Aber so für mich scheint ein solcher Fehler im Rahmen des Normalen zu liegen.
private Nachricht | Beiträge des Benutzers