Voltar para os desafios
Difícil 0 resolvidos 0% de aceitação

Backpropagation in a Two-Layer Network

Compute every weight and bias gradient of a network with one sigmoid hidden layer and one sigmoid output.

O que você vai aprender

  • Compute every gradient of a two-layer network
  • Pass error terms backwards through layers
  • Connect math to code step by step

Problema

Ver tradução

Backpropagation applies the chain rule layer by layer, from the output back to the inputs. The network has n inputs, h hidden neurons and one output, all with sigmoid activation (σ(z) = 1 / (1 + e^(-z))):

  • hidden: a_j = σ(inputs · hidden_weights[j] + hidden_biases[j])
  • output: y = σ(a · output_weights + output_bias)
  • loss: L = (y - target)²

Gradients:

  1. delta_out = 2 × (y - target) × y × (1 - y)
  2. Output layer: dL/doutput_weights[j] = delta_out × a_j and dL/doutput_bias = delta_out
  3. delta_j = delta_out × output_weights[j] × a_j × (1 - a_j)
  4. Hidden layer: dL/dhidden_weights[j][i] = delta_j × inputs[i] and dL/dhidden_biases[j] = delta_j

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

Output

Return a matrix with h + 1 rows:

  • Row j (for each hidden neuron j, in order): the n gradients of hidden_weights[j], then the gradient of hidden_biases[j].
  • Last row: the h gradients of output_weights, then the gradient of output_bias.

Restrições

1 ≤ n, h ≤ 20

-5 ≤ each input, weight and bias ≤ 5

0 ≤ target ≤ 1

Exemplos

Exemplo 1
Entrada:
inputs = [1.0]
target = 1.0
output_bias = 0.0
hidden_biases = [0.0]
hidden_weights = [
    [0.0]
]
output_weights = [0.0]

Saída esperada:
expected = [
    [0.0, 0.0],
    [-0.125, -0.25]
]
Entrada:
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};

Saída esperada:
std::vector<std::vector<double>> expected = {
    {0.0, 0.0},
    {-0.125, -0.25}
};
Entrada:
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};

Saída esperada:
double[][] expected = new double[][] {
    new double[] {0.0, 0.0},
    new double[] {-0.125, -0.25}
};

Explicação

a = σ(0) = 0.5 and y = σ(0) = 0.5. delta_out = 2 × (0.5 - 1) × 0.25 = -0.25. Output row: [-0.25 × 0.5, -0.25] = [-0.125, -0.25]. delta_1 = -0.25 × 0 × 0.25 = 0, so the hidden row is [0, 0]: a zero output weight blocks the gradient.

Exemplo 2
Entrada:
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]

Saída esperada:
expected = [
    [0.0625, 0.0, 0.0625],
    [0.0625, 0.0, 0.0625],
    [0.125, 0.125, 0.25]
]
Entrada:
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};

Saída esperada:
std::vector<std::vector<double>> expected = {
    {0.0625, 0.0, 0.0625},
    {0.0625, 0.0, 0.0625},
    {0.125, 0.125, 0.25}
};
Entrada:
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};

Saída esperada:
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}
};

Explicação

Both hidden values are σ(0) = 0.5, so y = σ(0.5 + 0.5 - 1) = 0.5 and delta_out = 2 × 0.5 × 0.25 = 0.25. Output row: [0.125, 0.125, 0.25]. Each delta_j = 0.25 × 1 × 0.25 = 0.0625, giving hidden rows [0.0625, 0, 0.0625] (the second input is 0).

Como abordar

Tente sozinho primeiro e depois abra uma dica de cada vez.

Dica 1

Work backward from the output neuron first, then reuse that signal to compute each hidden neuron's contribution.

Dica 2

You need one delta for the output layer and one delta per hidden neuron, both based on sigmoid derivatives.

Dica 3

Be careful to use each hidden neuron's own output weight when propagating error back to that neuron.

Complexidade esperada

O(hn) time, O(hn) extra space

Referências

Este desafio foi adaptado para o CodeUtility. Siga o enunciado e as restrições acima.

Aprenda com outros

Soluções da comunidade

Ainda não há soluções publicadas. Resolva este desafio para compartilhar a primeira.