I tried to make simple perceptron for predicting true or false, where 1 means true and false means -1. but my perceptron fails to train itself and instead gives random values.
this is my class perceptron:
function f(x){
//number is in negative it returns -1
if(x<0){
return -1
//number is in positive it returns 1
}else{
return 1
}
}
class Perceptron{
constructor(){
//two weights
this.weights = new Array(2)
//intitializing two random weights
for(let i = 0; i<this.weights.length; i++){
this.weights[i] = Math.random()*2-1
}
}
//prediction
guess(input){
let sum = 0;
for(let i = 0; i<input.length; i++){
sum += this.weights[i]*input[i]//sum of all product of inputs and weights
}
return f(sum)//returns -1 or 1
}
//training data
train(inputs, target){
this.lr = 0.1//learning rate
let guess = this.guess(inputs)//answer comes either 1 or -1
let err = target - guess//calc error
for(let i = 0; i<this.weights.length; i++){
this.weights[i] += err * inputs[i] * this.lr// re adjust the weights
}
}
}
export default Perceptron;
This is my main js:
import Perceptron from "./perceptron.js"
const brain = new Perceptron;
let data = [{
inputx: 1,
inputy: 1,
target: 1
},
{
inputx: 0,
inputy: 1,
target: -1
},
{
inputx: 1,
inputy: 0,
target: -1
},
{
inputx: 0,
inputy: 0,
target: -1
}
]
for(let i = 0; i<data.length; i++){
let inputs = [data[i].inputx, data[i].inputy]
brain.train(inputs, data[i].target)
let guess = brain.guess([1, 0])
console.log(guess)
}
the perceptron does not predict exact data, instead gives random answers. What am i doing wrong here
I put your code in a snippet, so you can run it here.
function f(x) {
//number is in negative it returns -1
if (x < 0) {
return -1
//number is in positive it returns 1
} else {
return 1
}
}
class Perceptron {
constructor() {
//two weights
this.weights = new Array(2)
//intitializing two random weights
for (let i = 0; i < this.weights.length; i++) {
this.weights[i] = Math.random() * 2 - 1
}
}
//prediction
guess(input) {
let sum = 0;
for (let i = 0; i < input.length; i++) {
sum += this.weights[i] * input[i] //sum of all product of inputs and weights
}
return f(sum) //returns -1 or 1
}
//training data
train(inputs, target) {
this.lr = 0.1 //learning rate
const guess = this.guess(inputs) //answer comes either 1 or -1
const err = target - guess //calc error
for (let i = 0; i < this.weights.length; i++) {
this.weights[i] += err * inputs[i] * this.lr // re adjust the weights
}
}
}
const brain = new Perceptron;
let data = [{
inputx: 1,
inputy: 1,
target: 1
},
{
inputx: 0,
inputy: 1,
target: -1
},
{
inputx: 1,
inputy: 0,
target: -1
},
{
inputx: 0,
inputy: 0,
target: -1
}
]
for (let i = 0; i < data.length; i++) {
let inputs = [data[i].inputx, data[i].inputy]
brain.train(inputs, data[i].target)
let guess = brain.guess([1, 0])
console.log(guess)
}
From the code what I see:
Perceptron
initialised with random weights - OKPerceptron
fed with data - OKIf you analyse the guessing function, then you'll see some problems:
guess[1, 1]
: the weights are added up. Likely that their sum is 0+, so the guess will yield a correct answer most of the timeguess[0, 1]
and guess[1, 0]
: only the weight that's paired with the 1
is taken into account (the other is multiplied by 0, then added to the sum); there's a slightly larger chance to yield a 1
than a -1
(that means false guess), but mostly randomguess[0, 0]
is going to be always false
, as it's internal sum (in the guess
function) is going to be always 0, therefore yield a 1
from f(x)
-> target is -1
(false result)The Perceptron works - as it modifies the weights during "learning", but is not going to yield significantly different answers than a random guess would.
function f(x) {
//number is in negative it returns -1
if (x < 0) {
return -1
//number is in positive it returns 1
} else {
return 1
}
}
class Perceptron {
constructor() {
//two weights
this.weights = new Array(2)
//intitializing two random weights
for (let i = 0; i < this.weights.length; i++) {
this.weights[i] = Math.random() * 2 - 1
}
}
//prediction
guess(input) {
let sum = 0;
for (let i = 0; i < input.length; i++) {
// -----------------------
// changed the * to + here
// -----------------------
sum += this.weights[i] + input[i] //sum of all product of inputs and weights
}
return f(sum) //returns -1 or 1
}
//training data
train(inputs, target) {
this.lr = 0.1 //learning rate
const guess = this.guess(inputs) //answer comes either 1 or -1
const err = target - guess //calc error
for (let i = 0; i < this.weights.length; i++) {
this.weights[i] += err * inputs[i] * this.lr // re adjust the weights
}
}
}
const brain = new Perceptron;
let data = [{
inputx: 1,
inputy: 1,
target: 1
},
{
inputx: 0,
inputy: 1,
target: -1
},
{
inputx: 1,
inputy: 0,
target: -1
},
{
inputx: 0,
inputy: 0,
target: -1
}
]
for (let j = 0; j < 1; j++) {
for (let i = 0; i < data.length; i++) {
let inputs = [data[i].inputx, data[i].inputy]
brain.train(inputs, data[i].target)
}
}
let guess = 0
console.log('After 1 round of training:')
guess = brain.guess([1, 1])
console.log(guess)
guess = brain.guess([0, 1])
console.log(guess)
guess = brain.guess([1, 0])
console.log(guess)
guess = brain.guess([0, 0])
console.log(guess)
console.log('Weights:', brain.weights)
for (let j = 0; j < 999; j++) {
for (let i = 0; i < data.length; i++) {
let inputs = [data[i].inputx, data[i].inputy]
brain.train(inputs, data[i].target)
}
}
console.log('After 1000 round of training:')
guess = brain.guess([1, 1])
console.log(guess)
guess = brain.guess([0, 1])
console.log(guess)
guess = brain.guess([1, 0])
console.log(guess)
guess = brain.guess([0, 0])
console.log(guess)
console.log('Weights:', brain.weights)
I changed the guess function
// from this:
sum += this.weights[i] * input[i]
// to this
sum += this.weights[i] + input[i]
and added some more rounds of training. I think the results speak for themselves (run it a couple of times to see the difference in 1 round of training vs. 1000 rounds of training).