// Cechy na wejściu (binarnie):
// - słonecznie: 1 = słonecznie, 0 = niesłonecznie
// - ciepło: 1 = ciepło, 0 = zimno
// - spokojnie: 1 = bezwietrznie, 0 = wietrznie
//
// Cel:
// - "Ładna pogoda" = słonecznie, ciepło, bezwietrznie
// - Etykieta: +1 = ładna, -1 = brzydka
class Perceptron {
constructor(nInputs) {
// Zaczynamy od zerowych wag i bez biasu
this.weights = new Array(nInputs).fill(0);
this.bias = 0;
}
// Funkcja przewidująca
// Wyniki: +1 (ładna) lub -1 (brzydka)
predict(inputs) {
let sum = this.bias;
for (let i = 0; i < this.weights.length; i++) {
sum += this.weights[i] * inputs[i];
}
// Używamy >=0 jako progu
return sum >= 0 ? 1 : -1;
}
// Funkcja ucząca perceptron
// samples - tablica obiektów {inputs: [...], label: +1/-1}
// epochs - liczba przejść przez cały zbiór danych
// lr - współczynnik uczenia (np. 1)
train(samples, epochs = 10, lr = 1) {
for (let epoch = 0; epoch < epochs; epoch++) {
let errors = 0;
for (const s of samples) {
const pred = this.predict(s.inputs);
if (pred !== s.label) {
// Aktualizujemy wagi i bias
for (let i = 0; i < this.weights.length; i++) {
this.weights[i] += lr * s.label * s.inputs[i];
}
this.bias += lr * s.label;
errors++;
}
}
if (errors === 0) break; // perfekcyjnie sklasyfikowane
}
}
}
// Zbiór danych "ładnej pogody" (wszystkie kombinacje 3 bitów)
// Tylko [słonecznie=1, ciepło=1, spokojnie=1] jest "ładne" (+1), wszystkie pozostałe są -1.
const weatherData = [
{ desc: "Pochmurno, zimno, wietrznie", inputs: [0, 0, 0], label: -1 },
{ desc: "Pochmurno, zimno, spokojnie", inputs: [0, 0, 1], label: -1 },
{ desc: "Pochmurno, ciepło, wietrznie", inputs: [0, 1, 0], label: -1 },
{ desc: "Pochmurno, ciepło, spokojnie", inputs: [0, 1, 1], label: -1 },
{ desc: "Słonecznie, zimno, wietrznie", inputs: [1, 0, 0], label: -1 },
{ desc: "Słonecznie, zimno, spokojnie", inputs: [1, 0, 1], label: -1 },
{ desc: "Słonecznie, ciepło, wietrznie", inputs: [1, 1, 0], label: -1 },
{ desc: "Słonecznie, ciepło, spokojnie", inputs: [1, 1, 1], label: 1 }, // jedyny przypadek "ładnej pogody"
];
// Funkcja pomocnicza do wyświetlania wyników
function showPredictions(p, data, title) {
console.log(title);
let correct = 0;
data.forEach((d) => {
const pred = p.predict(d.inputs);
const labelText = d.label === 1 ? "Ładna" : "Brzydka";
const predText = pred === 1 ? "Ładna" : "Brzydka";
const ok = pred === d.label;
if (ok) correct++;
console.log(
`${ok ? "✓" : "✗"} ${d.desc.padEnd(28)} oczekiwane=${labelText.padEnd(9)} przewidziane=${predText}`,
);
});
console.log(`Dokładność: ${((correct / data.length) * 100).toFixed(0)}%\n`);
}
// Inicjalizujemy perceptron i pokazujemy działanie przed treningiem
const p = new Perceptron(3);
showPredictions(
p,
weatherData,
"Przed treningiem (niewytrenowany perceptron):",
);
// Trenujemy perceptron na danych pogodowych
// Użyjemy max 20 epok i współczynnika uczenia 1
p.train(weatherData, 20, 1);
// Pokazujemy działanie po treningu - powinien poprawnie klasyfikować wszystkie przypadki
showPredictions(p, weatherData, "Po treningu (przetrenowany perceptron):");
// Pokazanie nauczonych wag i biasu
console.log(
"Wyuczone wagi:",
p.weights.map((w) => w.toFixed(2)),
"Przesunięcie:",
p.bias.toFixed(2),
);