感知器 Javascript 不一致
Perceptron Javascript Inconsistencies
构建一个基本的感知器。我训练后的结果非常不一致,即使经过 1000 个时代也是如此。权重似乎调整得当,但模型无法准确预测。将不胜感激第二双眼睛在结构上,努力寻找我哪里出错了。准确率始终达到 60%。
// Perceptron
class Perceptron {
constructor (x_train, y_train, learn_rate= 0.1, epochs=10) {
this.epochs = epochs
this.x_train = x_train
this.y_train = y_train
this.learn_rate = learn_rate
this.weights = new Array(x_train[0].length)
// initialize random weights
for ( let n = 0; n < x_train[0].length; n++ ) {
this.weights[n] = this.random()
}
}
// generate random float between -1 and 1 (for generating weights)
random () {
return Math.random() * 2 - 1
}
// activation function
activation (n) {
return n < 0 ? 0 : 1
}
// y-hat output given an input tensor
predict (input) {
let total = 0
this.weights.forEach((w, index) => { total += input[index] * w }) // multiply each weight by each input vector value
return this.activation(total)
}
// training perceptron on data
fit () {
for ( let e = 0; e < this.epochs; e++) { // epochs loop
for ( let i = 0; i < this.x_train.length; i++ ) { // iterate over each training sample
let prediction = this.predict(this.x_train[i]) // predict sample output
console.log('Expected: ' + this.y_train[i] + ' Model Output: ' + prediction) // log expected vs predicted
let loss = this.y_train[i] - prediction // calculate loss
for ( let w = 0; w < this.weights.length; w++ ) { // loop weights for update
this.weights[w] += loss * this.x_train[i][w] * this.learn_rate // update all weights to reduce loss
}
}
}
}
}
x = [[1, 1, 1], [0, 0, 0], [0, 0, 1], [1, 1, 0], [0, 0, 1]]
y = [1, 0, 0, 1, 0]
p = new Perceptron(x, y, epochs=5000, learn_rate=.1)
已更新:
// Perceptron
module.exports = class Perceptron {
constructor (x_train, y_train, epochs=1000, learn_rate= 0.1) {
// used to generate percent accuracy
this.accuracy = 0
this.samples = 0
this.x_train = x_train
this.y_train = y_train
this.epochs = epochs
this.learn_rate = learn_rate
this.weights = new Array(x_train[0].length)
this.bias = 0
// initialize random weights
for ( let n = 0; n < x_train[0].length; n++ ) {
this.weights[n] = this.random()
}
}
// returns percent accuracy
current_accuracy () {
return this.accuracy/this.samples
}
// generate random float between -1 and 1 (for generating weights)
random () {
return Math.random() * 2 - 1
}
// activation function
activation (n) {
return n < 0 ? 0 : 1
}
// y-hat output given an input tensor
predict (input) {
let total = this.bias
this.weights.forEach((w, index) => { total += input[index] * w }) // multiply each weight by each input vector value
return this.activation(total)
}
// training perceptron on data
fit () {
// epochs loop
for ( let e = 0; e < this.epochs; e++) {
// for each training sample
for ( let i = 0; i < this.x_train.length; i++ ) {
// get prediction
let prediction = this.predict(this.x_train[i])
console.log('Expected: ' + this.y_train[i] + ' Model Output: ' + prediction)
// update accuracy measures
this.y_train[i] === prediction ? this.accuracy += 1 : this.accuracy -= 1
this.samples++
// calculate loss
let loss = this.y_train[i] - prediction
// update all weights
for ( let w = 0; w < this.weights.length; w++ ) {
this.weights[w] += loss * this.x_train[i][w] * this.learn_rate
}
this.bias += loss * this.learn_rate
}
// accuracy post epoch
console.log(this.current_accuracy())
}
}
}
这只是语法错误:)
调换最后两个参数的顺序,像这样:
p = new Perceptron(x, y, learn_rate=.1, epochs=5000)
现在一切正常。
但是,更严重的问题在于你的实现:
你忘记了偏见
使用感知器,您正在尝试学习线性函数,其形式为
y = wx + b
但您目前正在计算的只是
y = wx
如果你想学习的只是单个输入的恒等函数,这很好,就像你的情况一样。但是一旦你开始做一些稍微复杂一点的事情,比如尝试学习 AND 函数,它就无法工作了,它可以这样表示:
y = x1 + x2 - 1.5
如何修复?
非常简单,只需在构造函数中初始化 this.bias = 0
即可。然后,在 predict()
中,您初始化 let total = this.bias
并在 fit()
中,在 inner-most 循环之后添加 this.bias += loss * this.learn_rate
。
构建一个基本的感知器。我训练后的结果非常不一致,即使经过 1000 个时代也是如此。权重似乎调整得当,但模型无法准确预测。将不胜感激第二双眼睛在结构上,努力寻找我哪里出错了。准确率始终达到 60%。
// Perceptron
class Perceptron {
constructor (x_train, y_train, learn_rate= 0.1, epochs=10) {
this.epochs = epochs
this.x_train = x_train
this.y_train = y_train
this.learn_rate = learn_rate
this.weights = new Array(x_train[0].length)
// initialize random weights
for ( let n = 0; n < x_train[0].length; n++ ) {
this.weights[n] = this.random()
}
}
// generate random float between -1 and 1 (for generating weights)
random () {
return Math.random() * 2 - 1
}
// activation function
activation (n) {
return n < 0 ? 0 : 1
}
// y-hat output given an input tensor
predict (input) {
let total = 0
this.weights.forEach((w, index) => { total += input[index] * w }) // multiply each weight by each input vector value
return this.activation(total)
}
// training perceptron on data
fit () {
for ( let e = 0; e < this.epochs; e++) { // epochs loop
for ( let i = 0; i < this.x_train.length; i++ ) { // iterate over each training sample
let prediction = this.predict(this.x_train[i]) // predict sample output
console.log('Expected: ' + this.y_train[i] + ' Model Output: ' + prediction) // log expected vs predicted
let loss = this.y_train[i] - prediction // calculate loss
for ( let w = 0; w < this.weights.length; w++ ) { // loop weights for update
this.weights[w] += loss * this.x_train[i][w] * this.learn_rate // update all weights to reduce loss
}
}
}
}
}
x = [[1, 1, 1], [0, 0, 0], [0, 0, 1], [1, 1, 0], [0, 0, 1]]
y = [1, 0, 0, 1, 0]
p = new Perceptron(x, y, epochs=5000, learn_rate=.1)
已更新:
// Perceptron
module.exports = class Perceptron {
constructor (x_train, y_train, epochs=1000, learn_rate= 0.1) {
// used to generate percent accuracy
this.accuracy = 0
this.samples = 0
this.x_train = x_train
this.y_train = y_train
this.epochs = epochs
this.learn_rate = learn_rate
this.weights = new Array(x_train[0].length)
this.bias = 0
// initialize random weights
for ( let n = 0; n < x_train[0].length; n++ ) {
this.weights[n] = this.random()
}
}
// returns percent accuracy
current_accuracy () {
return this.accuracy/this.samples
}
// generate random float between -1 and 1 (for generating weights)
random () {
return Math.random() * 2 - 1
}
// activation function
activation (n) {
return n < 0 ? 0 : 1
}
// y-hat output given an input tensor
predict (input) {
let total = this.bias
this.weights.forEach((w, index) => { total += input[index] * w }) // multiply each weight by each input vector value
return this.activation(total)
}
// training perceptron on data
fit () {
// epochs loop
for ( let e = 0; e < this.epochs; e++) {
// for each training sample
for ( let i = 0; i < this.x_train.length; i++ ) {
// get prediction
let prediction = this.predict(this.x_train[i])
console.log('Expected: ' + this.y_train[i] + ' Model Output: ' + prediction)
// update accuracy measures
this.y_train[i] === prediction ? this.accuracy += 1 : this.accuracy -= 1
this.samples++
// calculate loss
let loss = this.y_train[i] - prediction
// update all weights
for ( let w = 0; w < this.weights.length; w++ ) {
this.weights[w] += loss * this.x_train[i][w] * this.learn_rate
}
this.bias += loss * this.learn_rate
}
// accuracy post epoch
console.log(this.current_accuracy())
}
}
}
这只是语法错误:)
调换最后两个参数的顺序,像这样:
p = new Perceptron(x, y, learn_rate=.1, epochs=5000)
现在一切正常。
但是,更严重的问题在于你的实现:
你忘记了偏见
使用感知器,您正在尝试学习线性函数,其形式为
y = wx + b
但您目前正在计算的只是
y = wx
如果你想学习的只是单个输入的恒等函数,这很好,就像你的情况一样。但是一旦你开始做一些稍微复杂一点的事情,比如尝试学习 AND 函数,它就无法工作了,它可以这样表示:
y = x1 + x2 - 1.5
如何修复?
非常简单,只需在构造函数中初始化 this.bias = 0
即可。然后,在 predict()
中,您初始化 let total = this.bias
并在 fit()
中,在 inner-most 循环之后添加 this.bias += loss * this.learn_rate
。