All challenges
Hard 0 solved 0% acceptance

Train a Neural Network to Solve XOR

Combine everything: train a 2-2-1 sigmoid network with backpropagation until it learns XOR.

What you'll learn

  • Train a small network end to end
  • See why XOR needs a hidden layer
  • Put forward and backward passes together

Problem

XOR (exclusive or) is the classic problem a single neuron cannot solve, but a network with one hidden layer can. Train a network with 2 inputs, 2 hidden neurons and 1 output, all sigmoid (σ(z) = 1 / (1 + e^(-z))), using the loss L = (y - target)².

The training data, always used in this order in every epoch:

inputtarget
[0, 0]0
[0, 1]1
[1, 0]1
[1, 1]0

For each example:

  1. Forward: a_j = σ(x₁ × hidden_weights[j][0] + x₂ × hidden_weights[j][1] + hidden_biases[j]), y = σ(a₁ × output_weights[0] + a₂ × output_weights[1] + output_bias)
  2. delta_out = 2 × (y - target) × y × (1 - y), and delta_j = delta_out × output_weights[j] × a_j × (1 - a_j), using the weights before this example's update
  3. Update every parameter with learning rate lr: output_weights[j] -= lr × delta_out × a_j, output_bias -= lr × delta_out, hidden_weights[j][i] -= lr × delta_j × x_i, hidden_biases[j] -= lr × delta_j

Implement train_xor(hidden_weights, hidden_biases, output_weights, output_bias, learning_rate, epochs).

Output

After training, return the network's predictions y for the inputs [0, 0], [0, 1], [1, 0] and [1, 1], in that order.

Constraints

0 ≤ epochs ≤ 5,000

0 < learning_rate ≤ 5

-2 ≤ each starting weight and bias ≤ 2

Examples

Example 1
Input:
epochs = 0
output_bias = 0.0
hidden_biases = [0.0, 0.3]
learning_rate = 1.5
hidden_weights = [
    [0.2, 0.8],
    [0.9, -0.7]
]
output_weights = [-0.6, 0.4]

Expected output:
expected = [0.482451, 0.436972, 0.494378, 0.452729]
Input:
long long epochs = 0;
double output_bias = 0.0;
std::vector<double> hidden_biases = {0.0, 0.3};
double learning_rate = 1.5;
std::vector<std::vector<double>> hidden_weights = {
    {0.2, 0.8},
    {0.9, -0.7}
};
std::vector<double> output_weights = {-0.6, 0.4};

Expected output:
std::vector<double> expected = {0.482451, 0.436972, 0.494378, 0.452729};
Input:
long epochs = 0;
double output_bias = 0.0;
double[] hidden_biases = new double[] {0.0, 0.3};
double learning_rate = 1.5;
double[][] hidden_weights = new double[][] {
    new double[] {0.2, 0.8},
    new double[] {0.9, -0.7}
};
double[] output_weights = new double[] {-0.6, 0.4};

Expected output:
double[] expected = new double[] {0.482451, 0.436972, 0.494378, 0.452729};

Explanation

With 0 epochs nothing is trained, so the result is just the forward pass with the starting weights: about [0.482, 0.437, 0.494, 0.453]. The untrained network gives every input nearly the same answer.

Example 2
Input:
epochs = 2000
output_bias = 0.0
hidden_biases = [0.0, 0.3]
learning_rate = 1.5
hidden_weights = [
    [0.2, 0.8],
    [0.9, -0.7]
]
output_weights = [-0.6, 0.4]

Expected output:
expected = [0.015727, 0.982119, 0.985515, 0.013682]
Input:
long long epochs = 2000;
double output_bias = 0.0;
std::vector<double> hidden_biases = {0.0, 0.3};
double learning_rate = 1.5;
std::vector<std::vector<double>> hidden_weights = {
    {0.2, 0.8},
    {0.9, -0.7}
};
std::vector<double> output_weights = {-0.6, 0.4};

Expected output:
std::vector<double> expected = {0.015727, 0.982119, 0.985515, 0.013682};
Input:
long epochs = 2000;
double output_bias = 0.0;
double[] hidden_biases = new double[] {0.0, 0.3};
double learning_rate = 1.5;
double[][] hidden_weights = new double[][] {
    new double[] {0.2, 0.8},
    new double[] {0.9, -0.7}
};
double[] output_weights = new double[] {-0.6, 0.4};

Expected output:
double[] expected = new double[] {0.015727, 0.982119, 0.985515, 0.013682};

Explanation

After 2,000 epochs the predictions are about [0.016, 0.982, 0.986, 0.014]: low for [0, 0] and [1, 1], high for [0, 1] and [1, 0]. The network has learned XOR.

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.