Javascript 神经网络,梯度下降只找到输出的平均值?

Javascript 神经网络,梯度下降只找到输出的平均值?,javascript,machine-learning,neural-network,backpropagation,conceptual,Javascript,Machine Learning,Neural Network,Backpropagation,Conceptual,这个问题比代码中的问题更具概念性,因此用JS编写这个问题应该不太重要 所以我试着做一个神经网络,我试着训练它做一个简单的任务来测试它——一个或门(或者,实际上,任何逻辑门)。为了简单起见,我在没有任何批处理的情况下使用梯度下降法(批处理对于这个任务来说似乎是不必要的,而且我拥有的不必要的代码越少,调试就越容易) 但是,经过多次迭代后,输出总是收敛到输出的平均值。例如,给定此培训集: [0,0] = 0 [0,1] = 1 [1,0] = 1 [1,1] = 0 无论输入是什么,输出总是在0.5

这个问题比代码中的问题更具概念性,因此用JS编写这个问题应该不太重要

所以我试着做一个神经网络,我试着训练它做一个简单的任务来测试它——一个或门(或者,实际上,任何逻辑门)。为了简单起见,我在没有任何批处理的情况下使用梯度下降法(批处理对于这个任务来说似乎是不必要的,而且我拥有的不必要的代码越少,调试就越容易)

但是,经过多次迭代后,输出总是收敛到输出的平均值。例如,给定此培训集:

[0,0] = 0
[0,1] = 1
[1,0] = 1
[1,1] = 0
无论输入是什么,输出总是在0.5左右收敛。如果培训集为:

[0,0] = 0,
[0,1] = 1,
[1,0] = 1,
[1,1] = 1
输出总是在所有训练输出的平均值0.75左右收敛。这似乎适用于所有输出组合

似乎是这样的,因为无论何时,当它给出输出为0的某个值时,它都会改变权重以接近该值,而无论何时,当它给出输出为1的某个值时,它都会改变权重以接近该值,这意味着随着时间的推移,它将收敛于平均值

以下是反向传播代码(用Javascript编写):

this.backpropigate=函数(数据){
//设置输入
对于(var i=0;i=1;i--){
对于(var j=0;j
这里,NN处于一种结构中,其中每个神经元是一个具有输入、权重和基于输入/权重计算的输出的对象,并且神经元存储在2D“层”数组中,其中x维是层(因此,第一层是输入,第二层是隐藏的,等等)y维度是该层中神经元对象的列表。输入的“数据”以
[数据,正确输出]
的形式给出,类似于
[[0,1],[1]]

而且我的学习率是1,我的隐藏层有2个神经元

我觉得我的反向传播方法一定有一些概念上的问题,因为我已经测试了我代码的其他部分(比如前馈部分),它工作得很好。我尝试使用各种来源,尽管我主要依靠维基百科关于反向传播的文章和它给我的方程式


我知道阅读我的代码可能会让人困惑,尽管我试图让代码尽可能简单易懂,但任何帮助都将不胜感激。

从降低学习率开始,1.0太高了。@MatiasValdenegro当然,我试过了,但变化不大。问题是每次[1,1](应该是1)的输出都会打印出一个列表,它会不断下降,直到达到集合中的平均值0.25。编辑:很抱歉可能会浪费您的时间,但您最初的评论确实有所帮助。这是我第一次使用神经网络,我没有意识到实际创建一个工作系统需要重复多少次。以0.05的学习率,整个训练集需要250000次重复才能使其发挥作用。这是正常的,还是我的程序效率低下?我认为这是两者的混合,因为我还没有实现任何优化/效率。听起来很正常,学习速度和迭代次数是相关的。较小的学习速率需要更多的迭代,但是如果您将学习速率设置得太大,那么学习可能会发散。我建议看一看,因为XOR是NN的一个已知问题。
this.backpropigate = function(data){
    //Sets the inputs
    for(var i = 0; i < this.layers[0].length; i ++){
        if(i < data[0].length){
            this.layers[0][i].output = data[0][i];
        }
        else{
            this.layers[0][i].output = 0;
        }
    }
    this.feedForward(); //Rerun through the NN with the new set outputs
    for(var i = this.layers.length-1; i >= 1; i --){
        for(var j = 0; j < this.layers[i].length; j ++){
            var ref = this.layers[i][j];
            //Calculate the gradients for each Neuron
            if(i == this.layers.length-1){ //Output layer neurons
                var error = ref.output - data[1][j]; //Error
                ref.gradient = error * ref.output * (1 - ref.output);
            }
            else{ //Hidden layer neurons
                var gradSum = 0; //Find sum from the next layer
                for(var m = 0; m < this.layers[i+1].length; m ++){
                    var ref2 = this.layers[i+1][m];
                    gradSum += (ref2.gradient * ref2.weights[j]);
                }
                ref.gradient = gradSum * ref.output * (1-ref.output);
            }
            //Update each of the weights based off of the gradient
            for(var m = 0; m < ref.weights.length; m ++){
                //Find the corresponding neuron in the previous layer
                var ref2 = this.layers[i-1][m];
                ref.weights[m] -= LEARNING_RATE*ref2.output*ref.gradient;
            }
        }
    }
    this.feedForward();
};