Skip to content

Instantly share code, notes, and snippets.

@zhoukekestar
Created May 23, 2020 03:55
Show Gist options
  • Save zhoukekestar/d8fdf525eec7f4c7368b1d72185c1fcb to your computer and use it in GitHub Desktop.
Save zhoukekestar/d8fdf525eec7f4c7368b1d72185c1fcb to your computer and use it in GitHub Desktop.
XOR js 实现
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')
}
======== 第 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