神经网络为每个输入返回相同的输出

Posted

技术标签:

【中文标题】神经网络为每个输入返回相同的输出【英文标题】:Neural Network returning same output for every input 【发布时间】:2016-08-13 08:14:47 【问题描述】:

作为项目的一部分,我用 Java 编写了一个简单的人工神经网络。当我开始训练数据(使用我收集的训练集)时,每个 epoch 中的错误计数迅速稳定(准确率约为 30%)然后停止。在测试 ANN 时,任何给定输入的所有输出都完全相同。

我正在尝试输出一个介于 0 和 1 之间的数字(0 将股票分类为下跌股票,1 将股票分类为上涨股票 - 0.4-0.6 应该表示稳定)

当将相同的训练数据添加到 RapidMiner Studios 时,会创建具有更高 (70+%) 准确度的适当 ANN,因此我知道数据集很好。 ANN逻辑一定有问题。

下面是运行和调整权重的代码。任何和所有的帮助表示赞赏!

    public double[] Run(double[] inputs) 
    //INPUTS
    for (int i = 0; i < inputNeurons.length; i++) 
        inputNeurons[i] = inputs[i];
    

    for (int i = 0; i < hiddenNeurons.length; i++) 
        hiddenNeurons[i] = 0;
     //RESET THE HIDDEN NEURONS

    for (int e = 0; e < inputNeurons.length; e++) 
        for (int i = 0; i < hiddenNeurons.length; i++) 
            //Looping through each input neuron connected to each hidden neuron

            hiddenNeurons[i] += inputNeurons[e] * inputWeights[(e * hiddenNeurons.length) + i];
            //Summation (with the adding of neurons)  - Done by taking the sum of each (input * connection weight)
            //The more weighting a neuron has the more "important" it is in decision making
        
    

    for (int j = 0; j < hiddenNeurons.length; j++) 
        hiddenNeurons[j] = 1 / (1 + Math.exp(-hiddenNeurons[j]));
        //sigmoid function transforms the output into a real number between 0 and 1
    

    //HIDDEN
    for (int i = 0; i < outputNeurons.length; i++) 
        outputNeurons[i] = 0;
     //RESET THE OUTPUT NEURONS

    for (int e = 0; e < hiddenNeurons.length; e++) 
        for (int i = 0; i < outputNeurons.length; i++) 
            //Looping through each hidden neuron connected to each output neuron

            outputNeurons[i] += hiddenNeurons[e] * hiddenWeights[(e * outputNeurons.length) + i];
            //Summation (with the adding of neurons) as above
        
    

    for (int j = 0; j < outputNeurons.length; j++) 
        outputNeurons[j] = 1 / (1 + Math.exp(-outputNeurons[j])); //sigmoid function as above
    

    double[] outputs = new double[outputNeurons.length];
    for (int j = 0; j < outputNeurons.length; j++) 
        //Places all output neuron values into an array
        outputs[j] = outputNeurons[j];
    
    return outputs;


public double[] CalculateErrors(double[] targetValues) 
    //Compares the given values to the actual values
    for (int k = 0; k < outputErrors.length; k++) 
        outputErrors[k] = targetValues[k] - outputNeurons[k];
    
    return outputErrors;


    public void tuneWeights() //Back Propagation

    // Start from the end - From output to hidden
    for (int p = 0; p < this.hiddenNeurons.length; p++)     //For all Hidden Neurons
    
        for (int q = 0; q < this.outputNeurons.length; q++)  //For all Output Neurons
        
            double delta = this.outputNeurons[q] * (1 - this.outputNeurons[q]) * this.outputErrors[q];
            //DELTA is the error for the output neuron q
            this.hiddenWeights[(p * outputNeurons.length) + q] += this.learningRate * delta * this.hiddenNeurons[p];
            /*Adjust the particular weight relative to the error
             *If the error is large, the weighting will be decreased
             *If the error is small, the weighting will be increased
             */
        
    

    // From hidden to inps -- Same as above
    for (int i = 0; i < this.inputNeurons.length; i++)       //For all Input Neurons
    
        for (int j = 0; j < this.hiddenNeurons.length; j++)  //For all Hidden Neurons
        
            double delta = this.hiddenNeurons[j] * (1 - this.hiddenNeurons[j]);
            double x = 0;       //We do not have output errors here so we must use extra data from Output Neurons
            for (int k = 0; k < this.outputNeurons.length; k++) 
                double outputDelta = this.outputNeurons[k] * (1 - this.outputNeurons[k]) * this.outputErrors[k];
                //We calculate the output delta again
                x = x + outputDelta * this.hiddenWeights[(j * outputNeurons.length) + k];
                //We then calculate the error based on the hidden weights (x is used to add the error values of all weights)
                delta = delta * x;
            
            this.inputWeights[(i * hiddenNeurons.length) + j] += this.learningRate * delta * this.inputNeurons[i];
            //Adjust weight like above
        
    

【问题讨论】:

如何初始化权重?一开始不都是0吗? 尝试了相同的结果,目前它们在-1和1之间随机初始化 因为如果你用 0 初始化它们,你可能会得到这样的效果(你的网络将简单地停留在这个配置中)。现在可以工作了吗(随机初始化后)? 否:/ 完全相同的结果。我无法理解所有输入如何导致相同的输出 你得到什么样的输出?您是否 100% 认为权重未初始化为 0? 【参考方案1】:

经过长时间的讨论,我认为您可以从以下几点找到问题的答案:

    偏见非常重要。实际上 - 关于神经网络的最流行的 SO 问题之一是关于偏见 :): Role of Bias in Neural Networks 您应该照看自己的学习过程。跟踪您对准确性和验证集的测试并在训练期间使用适当的学习率是很好的。当您知道很容易找到真正的解决方案时,我建议您使用更简单的数据集(例如 - 三角形或正方形 - 然后使用 4 - 5 个隐藏单元)。我还建议您使用以下游乐场:

http://playground.tensorflow.org/#activation=tanh&batchSize=10&dataset=circle&regDataset=reg-plane&learningRate=0.03&regularizationRate=0&noise=0&networkShape=4,2&seed=0.36368&showTestData=false&discretize=false&percTrainData=50&x=true&y=true&xTimesY=false&xSquared=false&ySquared=false&cosX=false&sinX=false&cosY=false&sinY=false&collectStats=false&problem=classification

【讨论】:

以上是关于神经网络为每个输入返回相同的输出的主要内容,如果未能解决你的问题,请参考以下文章

Python 神经网络:运行 10 次迭代,但我得到相同的输出

如何确保 Caffe 分割网络输出大小与输入相同?

145自然语言处理进阶手册--循环神经网络

规则学习网络

网络流24题--负载平衡问题网络流

神经网络训练技巧