Problema
O perceptron (1958) é o primeiro algoritmo de aprendizado para um neurônio artificial. Ele prevê com uma função degrau e aprende com os erros.
Comece com todos os pesos e o viés em 0. Em cada época, percorra os exemplos em ordem e, para cada exemplo x com rótulo y (0 ou 1):
- previsão = 1 se x · weights + bias > 0, senão 0
- error = y - previsão (ou seja, -1, 0 ou 1)
- Se error ≠ 0: weights[i] ← weights[i] + learning_rate × error × x[i] para cada i, e bias ← bias + learning_rate × error
Implemente train_perceptron(samples, labels, learning_rate, epochs).
Entrada
samples: m exemplos com n variáveis cada.
labels: Os m rótulos, cada um 0 ou 1.
learning_rate, epochs: O tamanho do passo e o número de passadas pelos dados.
Saída
Retorne os pesos finais seguidos do viés (n + 1 números).
Restrições
1 ≤ m ≤ 100, 1 ≤ n ≤ 10, 1 ≤ epochs ≤ 100
0 < learning_rate ≤ 1
-10 ≤ cada variável ≤ 10
Exemplos
Entrada:
epochs = 1
labels = [0, 0, 0, 1]
samples = [
[0.0, 0.0],
[0.0, 1.0],
[1.0, 0.0],
[1.0, 1.0]
]
learning_rate = 1.0
Saída esperada:
expected = [1.0, 1.0, 1.0]
Entrada:
long long epochs = 1;
std::vector<long long> labels = {0, 0, 0, 1};
std::vector<std::vector<double>> samples = {
{0.0, 0.0},
{0.0, 1.0},
{1.0, 0.0},
{1.0, 1.0}
};
double learning_rate = 1.0;
Saída esperada:
std::vector<double> expected = {1.0, 1.0, 1.0};
Entrada:
long epochs = 1;
long[] labels = new long[] {0, 0, 0, 1};
double[][] samples = new double[][] {
new double[] {0.0, 0.0},
new double[] {0.0, 1.0},
new double[] {1.0, 0.0},
new double[] {1.0, 1.0}
};
double learning_rate = 1.0;
Saída esperada:
double[] expected = new double[] {1.0, 1.0, 1.0};
Explicação
[0, 0]: z = 0, prevê 0, correto. [0, 1] e [1, 0]: também preveem 0, correto. [1, 1]: prevê 0, mas o rótulo é 1, então error = 1: os pesos viram [1, 1] e o viés vira 1. Resultado: [1, 1, 1].
Entrada:
epochs = 10
labels = [0, 0, 0, 1]
samples = [
[0.0, 0.0],
[0.0, 1.0],
[1.0, 0.0],
[1.0, 1.0]
]
learning_rate = 1.0
Saída esperada:
expected = [2.0, 1.0, -2.0]
Entrada:
long long epochs = 10;
std::vector<long long> labels = {0, 0, 0, 1};
std::vector<std::vector<double>> samples = {
{0.0, 0.0},
{0.0, 1.0},
{1.0, 0.0},
{1.0, 1.0}
};
double learning_rate = 1.0;
Saída esperada:
std::vector<double> expected = {2.0, 1.0, -2.0};
Entrada:
long epochs = 10;
long[] labels = new long[] {0, 0, 0, 1};
double[][] samples = new double[][] {
new double[] {0.0, 0.0},
new double[] {0.0, 1.0},
new double[] {1.0, 0.0},
new double[] {1.0, 1.0}
};
double learning_rate = 1.0;
Saída esperada:
double[] expected = new double[] {2.0, 1.0, -2.0};
Explicação
Depois de 10 épocas o perceptron aprendeu a porta AND: com pesos [2, 1] e viés -2, só [1, 1] dá z > 0.
Como abordar
Tente sozinho primeiro e depois abra uma dica de cada vez.
Dica 1
Processe as amostras em ordem a cada época, porque atualizações anteriores afetam predições posteriores.
Dica 2
Atualize só quando a classe prevista for diferente do rótulo, ajustando pesos e bias juntos.
Dica 3
A regra de predição usa um teste de sinal estrito, então score zero conta como classe 0.
Complexidade esperada
tempo O(epochs × m × n), espaço extra O(n)
Referências
Este desafio foi adaptado para o CodeUtility. Siga o enunciado e as restrições acima.