Back to challenges
Medium 0 solved 0% acceptance

Forward Propagation in a Two-Layer Network

Run inputs through a hidden ReLU layer and a sigmoid output layer.

What you'll learn

  • Chain a hidden layer and an output layer
  • Feed one layer's output into the next
  • Run a full network prediction

Problem

A small neural network has a hidden layer and an output layer. Data flows forward through them:

  1. Hidden layer: h_j = ReLU(inputs · hidden_weights[j] + hidden_biases[j]), where ReLU(z) = max(0, z)
  2. Output layer: y_k = sigmoid(h · output_weights[k] + output_biases[k]), where sigmoid(z) = 1 / (1 + e^(-z))

Implement forward_pass(inputs, hidden_weights, hidden_biases, output_weights, output_biases).

Input

inputs: The n input values.

hidden_weights, hidden_biases: The hidden layer, one row and one bias per hidden neuron.

output_weights, output_biases: The output layer, one row and one bias per output; each row has one weight per hidden neuron.

Output

Return the list of network outputs y.

Constraints

1 ≤ inputs, hidden neurons, outputs ≤ 50

-10 ≤ each value ≤ 10

Examples

Example 1
Input:
inputs = [1.0, 0.5]
hidden_biases = [0.0, 0.5]
output_biases = [0.0]
hidden_weights = [
    [1.0, -2.0],
    [0.5, 1.0]
]
output_weights = [
    [1.0, -1.0]
]

Expected output:
expected = [0.182426]
Input:
std::vector<double> inputs = {1.0, 0.5};
std::vector<double> hidden_biases = {0.0, 0.5};
std::vector<double> output_biases = {0.0};
std::vector<std::vector<double>> hidden_weights = {
    {1.0, -2.0},
    {0.5, 1.0}
};
std::vector<std::vector<double>> output_weights = {
    {1.0, -1.0}
};

Expected output:
std::vector<double> expected = {0.182426};
Input:
double[] inputs = new double[] {1.0, 0.5};
double[] hidden_biases = new double[] {0.0, 0.5};
double[] output_biases = new double[] {0.0};
double[][] hidden_weights = new double[][] {
    new double[] {1.0, -2.0},
    new double[] {0.5, 1.0}
};
double[][] output_weights = new double[][] {
    new double[] {1.0, -1.0}
};

Expected output:
double[] expected = new double[] {0.182426};

Explanation

Hidden: ReLU(1×1 + 0.5×(-2) + 0) = ReLU(0) = 0 and ReLU(1×0.5 + 0.5×1 + 0.5) = 1.5. Output: sigmoid(0×1 + 1.5×(-1) + 0) = sigmoid(-1.5) ≈ 0.182426.

Example 2
Input:
inputs = [2.0]
hidden_biases = [0.0, 0.0]
output_biases = [-1.0, 0.0]
hidden_weights = [
    [1.0],
    [-1.0]
]
output_weights = [
    [0.5, 0.5],
    [-0.5, 2.0]
]

Expected output:
expected = [0.5, 0.268941]
Input:
std::vector<double> inputs = {2.0};
std::vector<double> hidden_biases = {0.0, 0.0};
std::vector<double> output_biases = {-1.0, 0.0};
std::vector<std::vector<double>> hidden_weights = {
    {1.0},
    {-1.0}
};
std::vector<std::vector<double>> output_weights = {
    {0.5, 0.5},
    {-0.5, 2.0}
};

Expected output:
std::vector<double> expected = {0.5, 0.268941};
Input:
double[] inputs = new double[] {2.0};
double[] hidden_biases = new double[] {0.0, 0.0};
double[] output_biases = new double[] {-1.0, 0.0};
double[][] hidden_weights = new double[][] {
    new double[] {1.0},
    new double[] {-1.0}
};
double[][] output_weights = new double[][] {
    new double[] {0.5, 0.5},
    new double[] {-0.5, 2.0}
};

Expected output:
double[] expected = new double[] {0.5, 0.268941};

Explanation

Hidden: ReLU(2) = 2 and ReLU(-2) = 0. Output 1: sigmoid(2×0.5 + 0 - 1) = sigmoid(0) = 0.5. Output 2: sigmoid(2×(-0.5) + 0) = sigmoid(-1) ≈ 0.268941.

How to approach it

Try on your own first, then open one hint at a time.

Hint 1

First compute all hidden activations from the inputs, then use those hidden outputs for the final layer.

Hint 2

Each layer is a batch of dot products plus biases, with ReLU in the hidden layer and sigmoid at the output.

Hint 3

Do not mix original inputs into the second layer; it only sees the hidden layer outputs.

Expected complexity

O(hn + oh) time, O(h + o) extra space

References

This challenge is adapted for CodeUtility. Follow the statement and constraints above.

Learn from others

Community solutions

No published solutions yet. Solve this challenge to share the first one.