Alle Herausforderungen
Schwierig 0 gelöst 0% Erfolgsquote

Backpropagation in einem zweischichtigen Netz

Berechne alle Gradienten der Gewichte und Biases eines Netzes mit einer verborgenen Sigmoid-Schicht und einer Sigmoid-Ausgabe.

Das lernst du

  • Jeden Gradienten eines zweischichtigen Netzes berechnen
  • Fehlerterme rückwärts durch die Schichten geben
  • Mathematik und Code Schritt für Schritt verbinden

Problem

Backpropagation wendet die Kettenregel Schicht für Schicht an, von der Ausgabe zurück zu den Eingaben. Das Netz hat n Eingaben, h verborgene Neuronen und eine Ausgabe, alle mit Sigmoid-Aktivierung (σ(z) = 1 / (1 + e^(-z))):

  • verborgen: a_j = σ(inputs · hidden_weights[j] + hidden_biases[j])
  • Ausgabe: y = σ(a · output_weights + output_bias)
  • Verlust: L = (y - target)²

Gradienten:

  1. delta_out = 2 × (y - target) × y × (1 - y)
  2. Ausgabeschicht: dL/doutput_weights[j] = delta_out × a_j und dL/doutput_bias = delta_out
  3. delta_j = delta_out × output_weights[j] × a_j × (1 - a_j)
  4. Verborgene Schicht: dL/dhidden_weights[j][i] = delta_j × inputs[i] und dL/dhidden_biases[j] = delta_j

Implementiere backprop_gradients(inputs, hidden_weights, hidden_biases, output_weights, output_bias, target).

Ausgabe

Gib eine Matrix mit h + 1 Zeilen zurück:

  • Zeile j (für jedes verborgene Neuron j, in Reihenfolge): die n Gradienten von hidden_weights[j], dann der Gradient von hidden_biases[j].
  • Letzte Zeile: die h Gradienten von output_weights, dann der Gradient von output_bias.

Einschränkungen

1 ≤ n, h ≤ 20

-5 ≤ jede Eingabe, jedes Gewicht und jeder Bias ≤ 5

0 ≤ target ≤ 1

Beispiele

Beispiel 1
Eingabe:
inputs = [1.0]
target = 1.0
output_bias = 0.0
hidden_biases = [0.0]
hidden_weights = [
    [0.0]
]
output_weights = [0.0]

Erwartete Ausgabe:
expected = [
    [0.0, 0.0],
    [-0.125, -0.25]
]
Eingabe:
std::vector<double> inputs = {1.0};
double target = 1.0;
double output_bias = 0.0;
std::vector<double> hidden_biases = {0.0};
std::vector<std::vector<double>> hidden_weights = {
    {0.0}
};
std::vector<double> output_weights = {0.0};

Erwartete Ausgabe:
std::vector<std::vector<double>> expected = {
    {0.0, 0.0},
    {-0.125, -0.25}
};
Eingabe:
double[] inputs = new double[] {1.0};
double target = 1.0;
double output_bias = 0.0;
double[] hidden_biases = new double[] {0.0};
double[][] hidden_weights = new double[][] {
    new double[] {0.0}
};
double[] output_weights = new double[] {0.0};

Erwartete Ausgabe:
double[][] expected = new double[][] {
    new double[] {0.0, 0.0},
    new double[] {-0.125, -0.25}
};

Erläuterung

a = σ(0) = 0.5 und y = σ(0) = 0.5. delta_out = 2 × (0.5 - 1) × 0.25 = -0.25. Ausgabezeile: [-0.25 × 0.5, -0.25] = [-0.125, -0.25]. delta_1 = -0.25 × 0 × 0.25 = 0, also ist die verborgene Zeile [0, 0]: Ein Ausgabegewicht von null blockiert den Gradienten.

Beispiel 2
Eingabe:
inputs = [1.0, 0.0]
target = 0.0
output_bias = -1.0
hidden_biases = [0.0, 0.0]
hidden_weights = [
    [0.0, 1.0],
    [0.0, -1.0]
]
output_weights = [1.0, 1.0]

Erwartete Ausgabe:
expected = [
    [0.0625, 0.0, 0.0625],
    [0.0625, 0.0, 0.0625],
    [0.125, 0.125, 0.25]
]
Eingabe:
std::vector<double> inputs = {1.0, 0.0};
double target = 0.0;
double output_bias = -1.0;
std::vector<double> hidden_biases = {0.0, 0.0};
std::vector<std::vector<double>> hidden_weights = {
    {0.0, 1.0},
    {0.0, -1.0}
};
std::vector<double> output_weights = {1.0, 1.0};

Erwartete Ausgabe:
std::vector<std::vector<double>> expected = {
    {0.0625, 0.0, 0.0625},
    {0.0625, 0.0, 0.0625},
    {0.125, 0.125, 0.25}
};
Eingabe:
double[] inputs = new double[] {1.0, 0.0};
double target = 0.0;
double output_bias = -1.0;
double[] hidden_biases = new double[] {0.0, 0.0};
double[][] hidden_weights = new double[][] {
    new double[] {0.0, 1.0},
    new double[] {0.0, -1.0}
};
double[] output_weights = new double[] {1.0, 1.0};

Erwartete Ausgabe:
double[][] expected = new double[][] {
    new double[] {0.0625, 0.0, 0.0625},
    new double[] {0.0625, 0.0, 0.0625},
    new double[] {0.125, 0.125, 0.25}
};

Erläuterung

Beide verborgenen Werte sind σ(0) = 0.5, also y = σ(0.5 + 0.5 - 1) = 0.5 und delta_out = 2 × 0.5 × 0.25 = 0.25. Ausgabezeile: [0.125, 0.125, 0.25]. Jedes delta_j = 0.25 × 1 × 0.25 = 0.0625, was die verborgenen Zeilen [0.0625, 0, 0.0625] ergibt (die zweite Eingabe ist 0).

Referenzen

Diese Aufgabe wurde für CodeUtility angepasst. Beachte die oben genannten Vorgaben und Einschränkungen.

Von anderen lernen

Community-Lösungen

Noch keine veröffentlichten Lösungen. Löse die Aufgabe und teile als Erster eine Lösung.