单层感知器算法不起作用

我正在努力全面理解神经网络的概念,因此我从创建自己的简单感知器算法开始。

这是我的代码(用JavaScript编写):

var lr = 0.1;//学习率//随机初始化权重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}//返回给定训练集的原始激活值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;}//激活函数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)) //应为负值console.log("y=("+w[1]+"*x+"+w[2]+")/"+w[1])

结果并不一致(我使用的是AND算法进行学习)。
图表应该看起来像这样:
http://puu.sh/44eIY/401f63cde7.png
但通常看起来像这样:
http://puu.sh/44eAJ/75488a05eb.png

我确定这里遗漏了一些小细节,
提前感谢您的帮助。


回答:

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

  • 重新声明了error变量,最初它被设计为一个总和误差,然后你再次声明它为每个输出神经元的误差,这导致了关于整个过程的信息丢失
  • 你的停止标准不好 – 它应该是误差的平均绝对值,而不仅仅是误差的总和 – 考虑一个简单的网络,它将一个标签为0的训练样本分类为1,这将在你的代码中导致误差,因此训练停止,尽管它远未结束
  • 训练后使用

    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]位于另一侧。没有保证[1,0][0,0][0,1]位于同一侧,这是预期的行为。使用提供的数据,感知器没有理由不使用x=0.5的垂直线,这完美地分隔了你的数据,但f( [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 

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注