Problema
Il percettrone (1958) è il primo algoritmo di apprendimento per un neurone artificiale. Prevede con una funzione a gradino e impara dai propri errori.
Parti con tutti i pesi e il bias a 0. In ogni epoca, scorri gli esempi in ordine e, per ogni esempio x con etichetta y (0 o 1):
- previsione = 1 se x · weights + bias > 0, altrimenti 0
- error = y - previsione (quindi -1, 0 o 1)
- Se error ≠ 0: weights[i] ← weights[i] + learning_rate × error × x[i] per ogni i, e bias ← bias + learning_rate × error
Implementa train_perceptron(samples, labels, learning_rate, epochs).
Input
samples: m esempi con n variabili ciascuno.
labels: Le m etichette, ognuna 0 o 1.
learning_rate, epochs: Il passo e il numero di passate sui dati.
Output
Restituisci i pesi finali seguiti dal bias (n + 1 numeri).
Vincoli
1 ≤ m ≤ 100, 1 ≤ n ≤ 10, 1 ≤ epochs ≤ 100
0 < learning_rate ≤ 1
-10 ≤ ogni variabile ≤ 10
Esempi
Input:
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
Output atteso:
expected = [1.0, 1.0, 1.0]
Input:
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;
Output atteso:
std::vector<double> expected = {1.0, 1.0, 1.0};
Input:
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;
Output atteso:
double[] expected = new double[] {1.0, 1.0, 1.0};
Spiegazione
[0, 0]: z = 0, prevede 0, corretto. [0, 1] e [1, 0]: prevedono anch'essi 0, corretto. [1, 1]: prevede 0 ma l'etichetta è 1, quindi error = 1: i pesi diventano [1, 1] e il bias 1. Risultato: [1, 1, 1].
Input:
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
Output atteso:
expected = [2.0, 1.0, -2.0]
Input:
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;
Output atteso:
std::vector<double> expected = {2.0, 1.0, -2.0};
Input:
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;
Output atteso:
double[] expected = new double[] {2.0, 1.0, -2.0};
Spiegazione
Dopo 10 epoche il percettrone ha imparato la porta AND: con i pesi [2, 1] e il bias -2, solo [1, 1] dà z > 0.
Come affrontarlo
Prova prima da solo, poi apri un suggerimento alla volta.
Suggerimento 1
Processa i sample in ordine a ogni epoch, perché gli aggiornamenti precedenti influenzano le predizioni successive.
Suggerimento 2
Aggiorna solo quando la classe predetta differisce dall’etichetta, e modifica insieme pesi e bias.
Suggerimento 3
La regola di predizione usa un test di segno stretto, quindi uno score pari a zero conta come classe 0.
Complessità attesa
tempo O(epochs × m × n), spazio aggiuntivo O(n)
Riferimenti
Questa sfida è adattata per CodeUtility. Segui la traccia e i vincoli sopra.