std.autodiff — automatische Differenzierung
Ableitungen ohne Handrechnung und ohne Differenzenquotient: Rückwärtsmodus auf einem Band, das alle Gradienten in einem Durchlauf liefert.
→ Mathematik-Units · std.numeric · std.mathx · std.ml
import std.autodiff;
Schicht 2, hängt an std.mathx. 53 Funktionen. Alle Beispiele mit lyxc 1.0.21A übersetzt und ausgeführt.
Was das löst
Für eine Ableitung gibt es sonst drei Wege, und alle drei haben einen Haken:
| Weg | Haken |
|---|---|
| Von Hand ableiten | fehleranfällig, und bei jeder Änderung der Funktion neu |
| Differenzenquotient | verliert die Hälfte der Stellen; die Schrittweite ist ein Kompromiss |
| Symbolisch | die Ausdrücke wachsen explosionsartig |
Automatische Differenzierung rechnet die Ableitung mit, während der Wert entsteht — exakt bis auf Rundung, ohne Schrittweite, ohne wachsende Ausdrücke.
Das Band
Beim Rückwärtsmodus wird jede Rechenoperation auf einem Band vermerkt. Ist der Wert fertig, läuft AdBackward das Band rückwärts ab und verteilt die Ableitungen — alle Gradienten in einem Durchgang, unabhängig von der Zahl der Variablen.
unit main;
import std.io;
import std.string;
import std.autodiff;
fn ZF(t: pchar, v: f64): void { Print(t); PrintF64(v); }
fn main(): int64 {
// f(x, y) = x^2 * y + sin(x) bei x = 2, y = 3
var t: int64 := AdTapeNew(256);
var x: int64 := AdVar(t, 2.0);
var y: int64 := AdVar(t, 3.0);
var x2: int64 := AdSquare(t, x);
var p: int64 := AdMul(t, x2, y);
var s: int64 := AdSin(t, x);
var f: int64 := AdAdd(t, p, s);
ZF("f(2,3) : ", AdValue(t, f));
AdBackward(t, f);
ZF("df/dx : ", AdGrad(t, x));
ZF("df/dy : ", AdGrad(t, y));
Print("Bandlaenge : "); PrintLn(IntToStr(AdTapeCount(t)));
AdTapeFree(t);
return 0;
}
f(2,3) : 12.909297
df/dx : 11.583853
df/dy : 4.000000
Bandlaenge : 6
Nachgerechnet: f(2,3) = 4·3 + sin(2) = 12,909297. Die Ableitungen sind df/dx = 2xy + cos(x) = 12 + cos(2) = 11,583853 und df/dy = x² = 4 — beide auf allen gezeigten Stellen getroffen.
Das Band hat sechs Einträge — zwei Variablen und vier Operationen. Genau das ist der Speicherbedarf, und er wächst mit der Zahl der Operationen, nicht mit der Zahl der Variablen.
Vorwärts oder rückwärts
Die Wahl hängt am Verhältnis von Eingaben zu Ausgaben.
Der Rückwärtsmodus liefert die Ableitungen einer Ausgabe nach allen Eingaben in einem Durchlauf. Bei einer Verlustfunktion mit tausend Parametern ist das genau richtig — ein Durchlauf, tausend Gradienten. Der Preis ist das Band: jede Operation wird gespeichert.
Der Vorwärtsmodus über Dualzahlen liefert umgekehrt die Ableitungen aller Ausgaben nach einer Eingabe. Er braucht kein Band und ist bei wenigen Eingaben billiger — für die Ableitung einer Funktion einer Veränderlichen, wie sieNumNewtonbraucht, ist er die richtige Wahl.
Der Bandspeicher
<WRAP alert>
AdTapeNew(capacity) legt die Größe fest. Reicht sie nicht, schlagen weitere Operationen fehl. AdTapeCount und AdTapeCapacity geben den Stand; AdTapeReset leert das Band, ohne neu zu reservieren — der richtige Weg in einer Trainingsschleife, statt für jeden Schritt ein neues Band anzulegen.
AdTapeFree gehört dazu.
</WRAP>
Funktionsübersicht
| Gruppe | Funktionen |
|---|---|
| Band | AdTapeNew · AdTapeFree · AdTapeReset · AdTapeCount · AdTapeCapacity |
| Knoten | AdVar (abzuleiten) · AdConst (fest) · AdValue |
| Grundrechenarten | AdAdd · AdSub · AdMul · AdDiv · AdNeg · AdAddConst · AdMulConst |
| Elementar | AdSquare · AdSqrt · AdExp · AdLog · AdPowConst · AdRecip · AdAbs |
| Winkelfunktionen | AdSin · AdCos · AdTan |
| Neuronale Netze | AdTanh · AdSigmoid · AdRelu · AdMax · AdMin |
| Auswerten | AdBackward · AdGrad |
Der Unterschied zwischen AdVar und AdConst ist der Punkt. Nur nach AdVar-Knoten wird abgeleitet; AdConst geht als feste Zahl ein. Wer einen Parameter versehentlich als AdConst anlegt, bekommt für ihn den Gradienten null — kein Fehler, nur ein Netz, das an dieser Stelle nicht lernt.
AdAbs,AdRelu,AdMaxundAdMinsind an einer Stelle nicht differenzierbar. Beix = 0hat der Betrag keine Ableitung; die Umsetzung wählt dort einen der einseitigen Werte. Das ist die übliche Festlegung und in der Praxis unschädlich — es lohnt aber zu wissen, dass der Gradient genau am Knick eine Konvention ist und kein mathematischer Wert.
Zusammenspiel
- std.numeric nimmt die Ableitung entgegen:
NumNewton(f, df, …)wird mit einer autodiff-gerechneten Ableitung sowohl schnell als auch exakt — stattNumNewtonNum, das sie numerisch schätzt. - Die Aktivierungsfunktionen
AdTanh,AdSigmoidundAdRelusind da, weil das der Fall ist, für den der Rückwärtsmodus gebaut wurde: eine skalare Verlustfunktion über viele Gewichte.
Letzte Aktualisierung: 2026-08-16 · alle Beispiele mit lyxc 1.0.21A übersetzt und ausgeführt; Wert und beide partielle Ableitungen gegen die von Hand gerechneten Ausdrücke geprüft.
