Я пытался построить свой самый первый пример нейронной сети и начал с персептрона с именем brain
в моем коде.Он пытается классифицировать некоторые случайные точки выше или ниже линии x = y.
Здесь у меня есть множество точек, случайно сгенерированных классом Point
, а массив points
- это мои известные тренировочные данные.Функция train
в основном обучает персептрон по щелчку мыши и показывает его догадки по черной точке, если она неправильная, и по белой точке, если она правильная.
Вот мой код:
var canvas = document.querySelector("canvas");
var c = canvas.getContext("2d");
canvas.height = innerHeight;
canvas.width = canvas.height;
var width = canvas.width;
var height = canvas.height;
//The activation function
const sign = (n) => {
if (n > 0) return 1;
else return -1;
}
class Perceptron {
// a constructor with n number of weights
constructor (n) {
this.weights = new Array(n);
this.lr = 0.1 //Learning rate
//Initialize the weights randomly
for (var i = 0; i < this.weights.length; i++) {
this.weights[i] = Math.random() * -2 + 1;
}
//Calculate weighted sum
this.sum = 0;
this.guess = (inputs) => {
for (var i = 0; i < this.weights.length; i++) {
this.sum += this.weights[i] * inputs[i];
}
return sign(this.sum);
}
this.train = (inputs, target) => {
var guess = this.guess(inputs);
var error = target - guess;
//Tune the weights
for (var i = 0; i < this.weights.length; i++) {
this.weights[i] += error * inputs[i] * this.lr;
}
}
}
}
class Point {
constructor () {
this.x = Math.random() * width;
this.y = Math.random() * height;
if (this.x > this.y) {
this.label = 1;
} else {
this.label = -1;
}
this.show = () => {
if (this.label == 1) {
c.fillStyle = 'tomato';
} else {
c.fillStyle = 'dodgerblue';
}
c.beginPath();
c.arc(this.x, this.y, 8, 0, Math.PI * 2, false);
c.fill();
}
}
}
var points = []; //Our known training data
var brain = new Perceptron(2);
//Fill points array
for (var i = 0; i < 100; i++) {
points.push(new Point());
}
const training = () => {
for (var i = 0; i < points.length; i++) {
let input = [points[i].x, points[i].y];
let target = points[i].label;
brain.train(input, target);
let guess = brain.guess(input);
if (guess == target) {
c.fillStyle = '#fff';
} else {
c.fillStyle = '#000';
}
c.beginPath();
c.arc(points[i].x, points[i].y, 4, 0, Math.PI * 2, false);
c.fill();
}
}
window.addEventListener('click', (event) => {
training();
})
const drawLine = () => {
c.beginPath();
c.moveTo(0, 0);
c.lineTo(width, height);
c.stroke();
}
const animate = () => {
// requestAnimationFrame(animate);
c.clearRect(0, 0, width, height);
drawLine();
for (var i = 0; i < points.length; i++) {
points[i].show();
}
// train();
}
animate();
Проблема в том, что он правильно классифицирует только половину точек выше или ниже линии x = y, а другая половина остается совершенно неверной.Что здесь не так?
Также я заметил, что когда я изменяю var error = target - guess;
на var error = guess - target;
(в train
методе класса Perceptron
), все половинные точки корректны только в первой итерации.Что здесь происходит?
Заранее спасибо за любую помощь.