我试图建立我的第一个神经网络示例,并从代码中名为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
方法中)时,它仅在第一次迭代中得到了所有正确的半点。这是怎么回事?
在此先感谢您的帮助。