JavaScript:简单感知器无法训练

JavaScript: Simple Perceptron fails to train

我尝试制作简单的感知器来预测真假,其中 1 表示真,假表示 -1。 但是我的感知器无法自我训练,而是给出随机值。

这是我的 class 感知器:

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;

这是我的主要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)
}

感知器不会预测准确的数据,而是给出随机答案。我在这里做错了什么

我把你的代码放在一个片段中,所以你可以运行在这里。

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)
}

从代码中我看到:

  1. Perceptron 使用随机权重初始化 - OK
  2. Perceptron 已输入数据 - OK

如果你分析猜测函数,那么你会发现一些问题:

  • guess[1, 1]:权重相加。很可能他们的总和是0+,所以大部分时间猜测都会得出正确答案
  • guess[0, 1]guess[1, 0]:只考虑与1配对的权重(另一个乘以0,然后相加);产生 1 的机会比 -1 稍大(这意味着错误的猜测),但主要是随机的
  • guess[0, 0] 将始终为 false,因为它的内部总和(在 guess 函数中)将始终为 0,因此产生 1来自 f(x) -> 目标是 -1(错误结果)

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++) {
      // -----------------------
      // 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)

我改了猜测函数

// from this:
sum += this.weights[i] * input[i]
// to this
sum += this.weights[i] + input[i]

并增加了更多轮的训练。我认为结果不言自明(运行 几次可以看出 1 轮训练与 1000 轮训练的区别)。