Operatoren Error sum?

dreckKopf

Mitglied
Was berechnet das?

Java:
    private static double calc(double... ds) {
    double squaredErrorSum = 0.0;
    double weightSum = 0.0;
    int valueCount = ds.length;

    for (int t = 0; t < valueCount; t++) {
      double error = ds[t];
      double weight = t + 1.0;
      squaredErrorSum += weight * error * error;
      weightSum += weight;
    }
    return squaredErrorSum / weightSum;
  }
 
Das Quadrat eines Mittelwerts von Fehlern mit Gewichtung.
Formel Mittelwert = (x1 + x2 + .. xn)/n.
Hier werden die Fehler aber gewichtet.
(e1*1+e2*2+e3*3)/(1+2+3)
Das bedeutet der erste Fehlerwert zählt einfach der 2te Fehlerwert zweifach usw.
Da die Abweichung aber auch negativ sein kann wird der Fehler zuvor quadriert damit sich negative und positive Fehler in der Summe nicht gegenseitig aufheben.
 
So weit bin ich:
Eine Loss Function (Verlustfunktion oder Kostenfunktion) misst die Abweichung zwischen den Vorhersagen eines künstlichen neuronalen Netzes (ANN) und den tatsächlichen Zielwerten. Sie liefert eine einzelne Zahl (den Fehlerwert), die dem Netz signalisiert, wie schlecht oder gut es aktuell performt.

Ziel des gesamten Lernprozesses ist es, diesen Fehlerwert durch Anpassung der Gewichte im Netz so nah wie möglich an 0 zu bringen.
 
Anhand dieser Bewertung müsste man dann die Gewichtungen und bias der Knoten wiederholt einstellen und wieder prüfen - dein Gehirn lernt. Zumindest verstehe ich das grad so. Wie man das alles umsetzt muss ich mir aber auch erst noch erarbeiten - das Thema ist neu für mich. ☕
 
Zuletzt bearbeitet:
Ziel des gesamten Lernprozesses ist es, diesen Fehlerwert durch Anpassung der Gewichte im Netz so nah wie möglich an 0 zu bringen.
Nein, Ziel ist, ein ideales Lernplateau zu erreichen und dann abzubrechen. Ein ideales Lernplateau liegt zwischen +Infinity (kein Lernen, unterfüttert) und 0 (1:1-Kopie der Wiedergabe des Gelernten, überfüttert). Es gibt dafür keinen festen Wert. Man muss sich den Verlauf ansehen, also den Gradienten der Lernfehler, und dann die bestmögliche Trainingsepoche auswählen...

Beispiele:
Training: Wenn es regnet, ist die Straße nass.
Prompt: Wenn es nicht regnet, dann?
Antwort bei Überfütterung: Dann ist die Straße trocken.
Antwort bei idealem Lernplateau: Dann ist die Straße wahrscheinlich trocken. Sie kann aber auch nass sein, wenn es kürzlich geregnet hat.

Der Rest ist aber richtig...
 
Noch schlimmer wäre es aber, wenn auf die Frage: "Es hat nicht geregnet, ist die Straße nass?", geantwortet würde: "Die Straße ist nass.", dann wäre die KI überfüttert und halluziniert. 😬
 
Nen intelligentes künstliches Gehirn würde bei solch einer Frage die Gegenfrage stellen ob der Fragesteller halluziniert.👊😃

Aber das Konzept ist erstmal jetzt klar soweit 😸
 
Zuletzt bearbeitet:
Jedenfalls, was ich sagen wollte, gilt die Closed-World Assumption (CWA) im Allgemeinen bei Implikationen bzw. bei der Umkehrung von Implikation (wenn nicht A, dann auch nicht B) nicht... Das sollte ein ANN also erkennen bzw. lernen... Das Regen-Straße-Nass-Szenario war hierbei nur ein Beispiel, worunter sich alle etwas vorstellen können.
 
Gut das du das erwähnst. Die Prinzipien von CWA (nicht zu verwechseln mit Convolutional Weight Vector) und OWA(Open-World Assumption) sind sehr interessant.
 
Zuletzt bearbeitet:
Ja, besonders interessant ist, dass in der Logik bzw. Aussagenlogik aus: Wenn A, dann B, i.d.R. nicht automatisch: Wenn nicht A, dann nicht B (Kontraposition), folgt - aber hingegen: Wenn nicht B, dann nicht A, schon...

A -> B
¬A v B (Implikationsauflösung oder Materiale Implikation)
B v ¬A (Kommutativgesetz)
¬B -> ¬A (Modus Tollens)

qed

Richtig spannend wird es, politische Reden oder Vorträge auf Widersprüchlichkeit hin zu untersuchen... also das, was allgemein hin nicht sofort wahrgenommen wird, aber wenigstens schön klingt.
 
Convolutional Weight Array bzw. Convolutional Weight Vector in einem ANN

Ja, so ergibt die Abkürzung im ANN-Kontext Sinn: bei Convolutional Layers spricht man praktisch von Gewichten/Kernels/Filtern, also z.B. einem Weight Array oder Tensor. „Vector“ passt je nach Darstellung auch, wenn man die Gewichte flach zieht.

Nur zur Trennung der Begriffe: CWA als Closed-World Assumption kommt eher aus Logik/Wissensrepräsentation, während Convolutional Weights aus neuronalen Netzen kommen. Gleiche Abkürzung, völlig andere Baustelle — daher besser beim ersten Auftreten einmal ausschreiben, sonst redet man schnell aneinander vorbei.
 
Ja gut beschrieben. Closed-World Assumption macht für mich im ANN Bereich auch Sinn - wie das Regenbeispiel zeigt. Es sind aber wie du auch sagst völlig verschiedene Dinge - aber beide für ANN-Programmierung wichtig.
 
Hier vermengt sich gerade viel... Meine ursprüngliche Frage ist schon beantwortet... War nur auf diesen Schnipsel gestoßen und konnte ihn nicht richtig zuordnen... Inzwischen weiß ich es aber.
 
Edit: Hab das Gefühl, der Login/Logout ist im Moment gestört... das Forum meldet mich nach kurzer Zeit immer automatisch ab... Wäre gut, wenn das mal (zeitnah) angegangen werden würde
 
Habe keine Probleme.
Schreib das mal den sitecheck-bereich oder in die plauderecke. Bin schon nen halbes Jahrhundert kein Admin mehr.
 
Zuletzt bearbeitet:
Was berechnet das?

Java:
    private static double calc(double... ds) {
    double squaredErrorSum = 0.0;
    double weightSum = 0.0;
    int valueCount = ds.length;

    for (int t = 0; t < valueCount; t++) {
      double error = ds[t];
      double weight = t + 1.0;
      squaredErrorSum += weight * error * error;
      weightSum += weight;
    }
    return squaredErrorSum / weightSum;
  }
Unabhängig von dem, was es berechnet (das Quadrieren betont große Werte, und spätere Elemente im Array bekommen höhere Gewichte), finde ich hier drei Sachen ein bisschen komisch und ich vermute, etwas ins Blaue geraten, dass das nicht wirklich aus Produktivcode stammt:

1. Mir fehlt hier eine Ausnahme, wenn ds keine Elemente hat. Kann man machen, wenn man weiß, dass die Arrays immer übergeben werden und niemals leer sind. In Bibliothekscode, aber eher ungewöhnlich. Außerdem, wenn das Array keine Elemente hat, bekommen wir eine Division durch Null, was bei Fließkommazahlen zu NaN führt. Kann man machen, aber ich glaube, Ausnahmen sind geläufiger.
2. double weightSum = (double) valueCount * (valueCount + 1) / 2.0; kann man direkt berechnen, dafür braucht man nicht die Addition weightSum += weight;. (Simple Gaußsche Summenformel.)
3. Je nachdem, wie groß die Elemente in dem Array sind, könnte es hier durch die Genauigkeit von double zu Verlusten kommen, weil einfach Summen verschiedener Größenordnungen gebildet werden. Das Overflow beim Quadrieren ist noch ein anderes Thema, aber dafür müssen die Zahlen schon wirklich sehr groß sein. Der Algorithmus funktioniert also nur dann gut, wenn man genau weiß, in welchem Größenbereich die Array-Elemente sind.
 
Simple Gaußsche Summenformel
Interessant, stimmt, hier ein JS-Schnippsel:

Javascript:
const n = 20;
let weightSum = 0;
for (let t = 0; t < n; t++) {
  weightSum += t + 1;
}
console.log(weightSum);
console.log((n * (n + 1)) / 2.0);

Der Index wird ja einfach nur um 1 verschoben ist damit Äquivalent zu: for (let t = 1; t <= n; t++) {weightSum += t;}

das Quadrieren betont große Werte, und spätere Elemente im Array bekommen höhere Gewichte
Was zur Folge hätte, dass das Training eher abgebrochen (Early Stop) würde, wenn sich der Score nicht weiter verbessert.
 
1. Mir fehlt hier eine Ausnahme, wenn ds keine Elemente hat. Kann man machen, wenn man weiß, dass die Arrays immer übergeben werden und niemals leer sind. In Bibliothekscode, aber eher ungewöhnlich. Außerdem, wenn das Array keine Elemente hat, bekommen wir eine Division durch Null, was bei Fließkommazahlen zu NaN führt. Kann man machen, aber ich glaube, Ausnahmen sind geläufiger.
2. double weightSum = (double) valueCount * (valueCount + 1) / 2.0; kann man direkt berechnen, dafür braucht man nicht die Addition weightSum += weight;. (Simple Gaußsche Summenformel.)
3. Je nachdem, wie groß die Elemente in dem Array sind, könnte es hier durch die Genauigkeit von double zu Verlusten kommen, weil einfach Summen verschiedener Größenordnungen gebildet werden. Das Overflow beim Quadrieren ist noch ein anderes Thema, aber dafür müssen die Zahlen schon wirklich sehr groß sein. Der Algorithmus funktioniert also nur dann gut, wenn man genau weiß, in welchem Größenbereich die Array-Elemente sind.

Deine Annahmen sind leider falsch... Alle.

1. NaN ist im Kontext ausdrücklich erwünscht, wenn es keine Argumente gibt.

2. weightSum gesondert zu berechnen, ist ineffizienter. Vergleiche dazu:

Java:
  private static double calc(double... ds) {
    double squaredErrorSum = 0.0;
    double weightSum = 0.0;
    int valueCount = ds.length;

    for (int t = 0; t < valueCount; t++) {
      double error = ds[t];
      double weight = t + 1.0;
      squaredErrorSum += weight * error * error;
      weightSum += weight;
    }
    return squaredErrorSum / weightSum;
  }

mit

Java:
  private static double calc(double... ds) {
    double squaredErrorSum = 0.0;
    int valueCount = ds.length;

    for (int t = 0; t < valueCount; t++) {
      double error = ds[t];
      squaredErrorSum += (t + 1.0) * error * error;
    }
    return squaredErrorSum / ((double) valueCount * (valueCount + 1) / 2.0);
  }

(weight, also t+1.0, muss ohnehin in jedem Durchlauf berechnet werden... Ziehe gerne auch Byte-Code heran und zähle die konkreten Instruktionen.)

3. Die Anzahl liegt immer zwischen 0 und 500... Also nichts, was Rundungsfehler jedweder Art hervorrufen würde.

Darüber hinaus kann man sich den null-Check auch sparen, da die Methode private ist... Also keine Library-Funktion.

Kritik ist immer schön, setzt aber voraus, dass man es auch besser kann, als das zu Kritisierende.
 

Zurück
Oben