简单/单层感知器算法不起作用

时间:2013-08-17 21:26:08

标签: javascript artificial-intelligence neural-network perceptron

我试图掌握神经网络背后的想法(完全),所以我开始创建自己的simple perceptron算法。

这是我的代码(在JavaScript中):

var lr = 0.1;//learning rate

//Initiate the weights randomly
function initWeights(weights, trainingSets){
    for(var i=0; i<trainingSets[0].in.length; i++){
        weights[i] = Math.random()*2 - 1;
    }
    weights.push(Math.random()*2 - 1); //b
}


//Return the raw activation value for a giving trainingSet
function getSum(weights, trainingSet){
    var sum = 0;
    for(var i=0; i < trainingSet.in.length; i++){
        sum += weights[i]*trainingSet.in[i];
    }
    sum += 1 * weights[weights.length-1];
    return sum;
}

//Activation function
function activate(value){
    return (value >= 0)? 1 : 0;
}

function train(weights, trainingSets){
    var error = 0;
    for(var i=0; i<trainingSets.length; i++){
        var currentSet = trainingSets[i];
        var activationValue = getSum(weights, currentSet);
        var error = currentSet.out - activate(activationValue);
        error += error;
        for(var j=0; j<weights.length-1; j++){
            var deltaW = error * lr * currentSet.in[j];
            weights[j] += deltaW;
        }
        weights[weights.length-1] += error * lr * 1;
    }
    return error/(weights.length);
}

var inp = [
    {in:[1,1], out:1},
    {in:[0,0], out:0},
    {in:[0,1], out:0},
];
var w = [];
initWeights(w, inp);
//for(var j = 0; j < inp.length; j++){
    var error = 1;
    while(error >= 0.01){
        error = train(w, inp);
    }
//}
console.log("===")
var tester = {in:[1,0], out: NaN};
console.log(getSum(w, tester)) //should be negative
console.log("y=("+w[1]+"*x+"+w[2]+")/"+w[1])

结果不一致,(我使用AND算法来学习) 情节应该如下:
http://puu.sh/44eIY/401f63cde7.png
但通常看起来像这样:
http://puu.sh/44eAJ/75488a05eb.png

我确信我在这里错过了一些小事 提前谢谢。

1 个答案:

答案 0 :(得分:1)

您的代码至少有三个问题:

  • 重新声明错误变量,它首先是汇总错误,然后您再次将其声明为每输出神经元错误,失去信息的整个过程
  • 你的停止标准很糟糕 - 它应该是错误的平均绝对值,而不仅仅是错误总和 - 考虑简单的网络,它将标签0的一个训练示例归为{ {1}},它会导致代码中出现否定错误,因此培训会停止,即使它远未结束
  • 训练后,这是不正确的
    1

    你会得到var inp = [ {in:[1,1], out:1}, {in:[0,0], out:0}, {in:[0,1], out:0}, ]; ,这不是感知器的工作方式。它只会在2维平面上找到这样一条线,f( [1,0] ) == 0位于其一侧,[1,1][0,0]位于另一侧。无法保证[0,1][1,0][0,0]位于同一侧,这是预期行为。使用提供的数据,感知器没有理由不使用[0,1]的垂直线,这可以完美地分隔您的数据,但x=0.5。您的训练数据不会“定义”操作,只是一组简单的规则,无数分类器都会遵守这些规则。

    f( [1,0] ) == 1

如评论中所述,如果您使用点(1,0),(0,1)和(1,1)的值训练您的网络,它将自己推断(0,0)的值

function train(weights, trainingSets){
var error = 0;
for(var i=0; i<trainingSets.length; i++){
    var currentSet = trainingSets[i];
    var activationValue = getSum(weights, currentSet);
    var error_current = currentSet.out - activate(activationValue);
    error += Math.abs( error_current );
    for(var j=0; j<weights.length-1; j++){
        var deltaW = error_current * lr * currentSet.in[j];
        weights[j] += deltaW;
    }
    weights[weights.length-1] += error_current * lr * 1;
}
return error/(weights.length);
}

产生

var inp = [
    {in:[1,1], out:1},
    {in:[0,1], out:0},
    {in:[1,0], out:0},
];

var w = [];
initWeights(w, inp);
//for(var j = 0; j < inp.length; j++){
    var error = 1;
    while(error >= 0.01){
        error = train(w, inp);
    }
//}
console.log("===")

var test = [
    {in:[1,1], out:1},
    {in:[0,0], out:0},
    {in:[0,1], out:0},
    {in:[1,0], out:0},
];

for(var i=0; i<test.length; ++i){
 console.log(test[i].in + " out: " +test[i].out + " nn: " + activate(getSum(w, test[i]) ) );
}