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

Treine uma rede neural para resolver o XOR

Junte tudo: treine uma rede sigmoide 2-2-1 com retropropagação até ela aprender o XOR.

O que você vai aprender

  • Treinar uma rede pequena do começo ao fim
  • Ver por que o XOR precisa de uma camada oculta
  • Juntar as passagens para frente e para trás

Problema

Ver original (inglês)

O XOR (ou exclusivo) é o problema clássico que um único neurônio não consegue resolver, mas uma rede com uma camada oculta consegue. Treine uma rede com 2 entradas, 2 neurônios ocultos e 1 saída, todos sigmoides (σ(z) = 1 / (1 + e^(-z))), usando a perda L = (y - target)².

Os dados de treinamento, sempre usados nesta ordem em cada época:

entradatarget
[0, 0]0
[0, 1]1
[1, 0]1
[1, 1]0

Para cada exemplo:

  1. Propagação direta: 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), e delta_j = delta_out × output_weights[j] × a_j × (1 - a_j), usando os pesos antes da atualização deste exemplo
  3. Atualize cada parâmetro com a taxa de aprendizado 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

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

Saída

Depois do treinamento, retorne as previsões y da rede para as entradas [0, 0], [0, 1], [1, 0] e [1, 1], nessa ordem.

Restrições

0 ≤ epochs ≤ 5.000

0 < learning_rate ≤ 5

-2 ≤ cada peso e viés inicial ≤ 2

Exemplos

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

Saída esperada:
expected = [0.482451, 0.436972, 0.494378, 0.452729]
Entrada:
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};

Saída esperada:
std::vector<double> expected = {0.482451, 0.436972, 0.494378, 0.452729};
Entrada:
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};

Saída esperada:
double[] expected = new double[] {0.482451, 0.436972, 0.494378, 0.452729};

Explicação

Com 0 épocas nada é treinado, então o resultado é só a propagação direta com os pesos iniciais: cerca de [0.482, 0.437, 0.494, 0.453]. A rede não treinada dá quase a mesma resposta para toda entrada.

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

Saída esperada:
expected = [0.015727, 0.982119, 0.985515, 0.013682]
Entrada:
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};

Saída esperada:
std::vector<double> expected = {0.015727, 0.982119, 0.985515, 0.013682};
Entrada:
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};

Saída esperada:
double[] expected = new double[] {0.015727, 0.982119, 0.985515, 0.013682};

Explicação

Depois de 2.000 épocas, as previsões ficam em torno de [0.016, 0.982, 0.986, 0.014]: baixas para [0, 0] e [1, 1], altas para [0, 1] e [1, 0]. A rede aprendeu o XOR.

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.