Created
May 23, 2020 03:55
-
-
Save zhoukekestar/d8fdf525eec7f4c7368b1d72185c1fcb to your computer and use it in GitHub Desktop.
XOR js 实现
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var log = console.log; | |
var random = () => { | |
return +(Math.random() * 2 - 1).toFixed(4); | |
}; | |
class Perceptron { | |
constructor({ truthTable, tableName, w1, w2 }) { | |
this.tableName = tableName; | |
this.rate = 0.001; | |
this.loopTimes = 1000000; | |
this.w1 = w1 || [[ random(), random(), random()], [random(), random(), random()]] | |
this.w2 = w2 || [ random(), random(), random() ]; | |
this.truthTable = truthTable; | |
} | |
// 用于校验结果 | |
verify(showlog) { | |
const { truthTable, tableName, w1, w2 } = this; | |
for (var i=0; i<truthTable.length; i++) { | |
var x1 = [ truthTable[i][0], truthTable[i][1], 1 ]; | |
var x2 = [ this.step(x1, w1[0]), this.step(x1, w1[1]), 1]; | |
var y = this.step(x2, w2); | |
if (showlog) { | |
console.log(truthTable[i][0] + ' ' + tableName + ' ' + truthTable[i][1] + ' = ', y, '(', x1, ',', x2, ')' ); | |
} | |
if (y !== truthTable[i][2]) return false; | |
} | |
return true; | |
} | |
step(x, w) { | |
// 正向求和 | |
var result = w[0]*x[0]+w[1]*x[1]+w[2]*x[2]; | |
// 激活函数 | |
if (result >= 0) return 1; | |
else return 0; | |
} | |
training() { // 训练函数 training(truthTable), 其中 truthTable 是目标真值表 | |
const { rate, w1, w2, truthTable, loopTimes } = this; | |
for (var loop=0; loop < loopTimes; loop++) { // 训练次数 | |
var e = 0; | |
// 每轮对于真值表中的每个输入输出配对,都训练一次。 | |
for (var i=0; i < truthTable.length; i++) { | |
// 一层输入值 + basis | |
var x1 = [ truthTable[i][0], truthTable[i][1], 1 ]; | |
// 期望值 | |
var yd = truthTable[i][2]; | |
// 隐藏层 | |
var x2 = [ this.step(x1, w1[0]), this.step(x1, w1[1]), 1]; | |
// 输出结果层 | |
var y = this.step(x2, w2); | |
// 预期差值 | |
e = yd - y; | |
// 反向传播第一层 | |
// 这里的链式求导,还是模糊的状态,为什么是这种形式? | |
w2[0] += rate * x2[0] * e; | |
w2[1] += rate * x2[1] * e; | |
w2[2] += rate * x2[2] * e; | |
// 反向传播第二层 | |
w1[0][0] += rate * x1[0] * e * w2[0]; | |
w1[0][1] += rate * x1[0] * e * w2[1]; | |
w1[0][2] += rate * x1[0] * e * w2[2]; | |
w1[1][0] += rate * x1[1] * e * w2[0]; | |
w1[1][1] += rate * x1[1] * e * w2[1]; | |
w1[1][2] += rate * x1[1] * e * w2[2]; | |
} | |
// 校验通过,则停止训练 | |
if (this.verify()) { | |
return { | |
loop, w1, w2 | |
}; | |
} | |
} | |
// 训练失败 | |
return null; | |
} | |
} | |
function learn(tableName, truthTable, w1, w2) { | |
// 建立感知器物件 | |
var p = new Perceptron({ | |
truthTable, | |
tableName, | |
w1, | |
w2, | |
}); | |
var result = p.training(); // 开始训练 | |
if (result != null) { | |
log(" 学习 %s 函数成功:", tableName); | |
log("loop=", result.loop, ' w1: ', JSON.stringify(result.w1), ' w2: ', JSON.stringify(result.w2)); | |
p.verify(true); | |
} else { | |
log(" 学习 %s 函数失败", tableName); | |
} | |
} | |
var andTable = [ [ 0, 0, 0 ], [ 0, 1, 0 ], [ 1, 0, 0 ], [ 1, 1, 1 ] ]; // AND 函数的真值表 | |
var orTable = [ [ 0, 0, 0 ], [ 0, 1, 1 ], [ 1, 0, 1 ], [ 1, 1, 1 ] ]; // OR 函数的真值表 | |
var xorTable = [ [ 0, 0, 0 ], [ 0, 1, 1 ], [ 1, 0, 1 ], [ 1, 1, 0 ] ]; // XOR 函数的真值表 | |
// 因为失败概览较高,所以,我们尝试多次学习 | |
for (var i = 0; i< 10; i++) { | |
console.log(`======== 第 ${i} 次学习 ========`) | |
// 通过预训练,输入初始状态,加快训练 | |
// learn("and", andTable, [[0.5, 0, 0], [0, 0, 0]], [0.5, 0, -0.5]); | |
learn("and", andTable); | |
learn("or", orTable); | |
learn("xor", xorTable); | |
console.log('\n') | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
======== 第 5 次学习 ======== | |
学习 and 函数成功: | |
loop= 341730 w1: [[0.39963790000397476,33.63402299979549,-0.9887426000058843],[-0.20303059999641215,0.41553599999999374,-0.41543859999487487]] w2: [0.0009000000000003372,-0.0010000000000000763,-0.0005999999999999929] | |
0 and 0 = 0 ( [ 0, 0, 1 ] , [ 0, 0, 1 ] ) | |
0 and 1 = 0 ( [ 0, 1, 1 ] , [ 1, 1, 1 ] ) | |
1 and 0 = 0 ( [ 1, 0, 1 ] , [ 0, 0, 1 ] ) | |
1 and 1 = 1 ( [ 1, 1, 1 ] , [ 1, 0, 1 ] ) | |
学习 or 函数成功: | |
loop= 244 w1: [[0.5519268,-0.06474380000000002,-0.06840439999999995],[-0.49513199999999985,-1.0470319999999997,0.558002]] w2: [0.39760000000000023,-0.5260999999999998,0.13020000000000032] | |
0 or 0 = 0 ( [ 0, 0, 1 ] , [ 0, 1, 1 ] ) | |
0 or 1 = 1 ( [ 0, 1, 1 ] , [ 0, 0, 1 ] ) | |
1 or 0 = 1 ( [ 1, 0, 1 ] , [ 1, 1, 1 ] ) | |
1 or 1 = 1 ( [ 1, 1, 1 ] , [ 1, 0, 1 ] ) | |
学习 xor 函数成功: | |
loop= 696460 w1: [[-0.7513457000000062,0.35677259999999433,0.39457490000601025],[-36.21090990031919,35.48711019926247,-0.06928969999966195]] w2: [-0.000299999999999751,0.001400000000000198,0.00010000000000053716] | |
0 xor 0 = 0 ( [ 0, 0, 1 ] , [ 1, 0, 1 ] ) | |
0 xor 1 = 1 ( [ 0, 1, 1 ] , [ 1, 1, 1 ] ) | |
1 xor 0 = 1 ( [ 1, 0, 1 ] , [ 0, 0, 1 ] ) | |
1 xor 1 = 0 ( [ 1, 1, 1 ] , [ 1, 0, 1 ] ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment