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

时间:2017-07-30 20:32:15

标签: javascript machine-learning neural-network backpropagation conceptual

这个问题比代码更具概念性,所以用JS编写这个问题并不重要。

所以我试图建立一个神经网络,并通过尝试训练它来做一个简单的任务来测试它 - 一个OR门(或者,实际上,只是任何逻辑门)。为了简单起见,我没有使用Gradient Descent而没有任何批次(批处理对于这项任务来说似乎没有用,而且我所用的代码越少,就越容易调试)。

然而,在多次迭代之后,输出总是收敛到输出的平均值。例如,鉴于此培训集:

[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 = 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();
};

这里,NN处于这样的结构中,其中每个神经元是具有输​​入,权重和基于输入/权重计算的输出的对象,并且神经元存储在2D&#39;层中。 ; x维是图层的数组(因此,第一层是输入,第二层是隐藏等),y维是该层内部的Neuron对象的列表。 &#39;数据&#39;输入的格式为[data,correct-output],如[[0,1],[1]]

我的LEARNING_RATE也是1,隐藏的图层有2个神经元。

我觉得我的反向传播方法一定存在一些概念问题,因为我已经测试了我的代码的其他部分(比如feedForward部分),并且它工作正常。我尝试使用各种来源,但我主要依靠关于反向传播的维基百科文章以及它给我的方程式。

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

0 个答案:

没有答案