0

我试图(完全)掌握神经网络背后的想法,所以我从创建自己的简单感知器算法开始。

这是我的代码(在 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

我确定我在这里遗漏了一些小东西,
在此先感谢。

4

1 回答 1

1

您的代码至少存在三个问题:

  • 您正在重新声明错误变量,它最初是一个汇总错误,然后您再次将其声明为每个输出神经元错误,这导致整个过程的信息丢失
  • 您的停止标准很糟糕 - 它应该是错误的平均绝对值,而不仅仅是错误的总和 - 考虑简单的网络,它将标签的一个训练示例分类01,它会导致代码中出现错误,因此训练停止,甚至虽然远未结束
  • 这不是真的,在训练后

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

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

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

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

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

生产

1,1 out: 1 nn: 1 
0,0 out: 0 nn: 0 
0,1 out: 0 nn: 0 
1,0 out: 0 nn: 0 
于 2013-08-19T06:41:53.020 回答