Почему этот персептрон не классифицирует вещи должным образом? - PullRequest
0 голосов
/ 05 февраля 2019

Я пытался построить свой самый первый пример нейронной сети и начал с персептрона с именем 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), все половинные точки корректны только в первой итерации.Что здесь происходит?

Заранее спасибо за любую помощь.

...