神经网络输出始终为 1

Posted

技术标签:

【中文标题】神经网络输出始终为 1【英文标题】:Neural network output is always 1 【发布时间】:2012-11-09 10:26:13 【问题描述】:

我正在开发一个神经网络应用程序,但是当我尝试打印前馈的输出时出现问题:控制台显示此值:

输出总是1 1 1 1 1

我使用 3 层,包括 2500 个输入节点、1800 个隐藏节点和 5 个输出节点。 我使用 sigmoid 二进制作为激活函数,测试权重固定为 0.5。

当我尝试使用一个非常简单的架构(2 个输入,3 个隐藏,1 个输出)时,它运行良好,但是现在有这么多节点,我无法手动计算输出,所以我不知道是否结果是真还是假。

我的代码是错误的,还是我不能给出一个固定的重量?我只想做一个前馈,不做反向传播,输入是从0到1的随机数。

这是network.cpp:

#include <stdio.h>
#include <iostream>
#include "network.h"
#include "neuron.h"

using namespace std;

layer::layer(int numberOfNeuron,int numberOfInput,int numberOfOutput):
neuron_layer(numberOfNeuron)

    for(int i=0;i<numberOfNeuron;i++)
    
        neuron_layer[i] = new neuron(numberOfInput,numberOfOutput);
    

layer::~layer()




int layer::get_number_of_neuron()

    return neuron_layer.size();


network::network(int layerNumber,int hiddenNeuronNumber):
    layer_network(layerNumber)

    this->layer_numbers = layerNumber;
    for(int i=0;i<layerNumber;i++)
    
        if(i==0)
        
            layer_network[i] = new layer(2500,5,hiddenNeuronNumber);
        
        else if(i==1)
        
            layer_network[i] = new layer(hiddenNeuronNumber,2500,5);
        
        else if(i==2)
        
            layer_network[i] = new layer(5,hiddenNeuronNumber,1);
        
    
    cout<<endl<<"Input layer : "<<layer_network[0]->get_number_of_neuron()<<endl;
    cout<<"Hidden layer : "<<layer_network[1]->get_number_of_neuron()<<endl;
    cout<<"Output layer : "<<layer_network[2]->get_number_of_neuron()<<endl;


network::~network()



void network::init_input_layer(int inputNeuronNumber,int hiddenNeuronNumber)

    for(int i=0;i<inputNeuronNumber;i++)
    
        for(int j=0;j<hiddenNeuronNumber;j++)
        
            layer_network[0]->neuron_layer[i]->outputs[j]->weights = 0.5f;
        
    


void network::init_hidden_layer(int inputNeuronNumber,int hiddenNeuronNumber,int outputNeuronNumber)

    for(int i=0;i<hiddenNeuronNumber;i++)
    
        for(int j=0;j<inputNeuronNumber;j++)
        
            layer_network[1]->neuron_layer[i]->inputs[j]->weights = layer_network[0]->neuron_layer[j]->outputs[i]->weights;
        
    
    for(int k=0;k<hiddenNeuronNumber;k++)
    
        for(int l=0;l<outputNeuronNumber;l++)
        
            layer_network[1]->neuron_layer[k]->outputs[l]->weights = 0.5f;
        
    


void network::init_ouput_layer(int hiddenNeuronNumber,int outputNeuronNumber)

    for(int i=0;i<outputNeuronNumber;i++)
    
        for(int j=0;j<hiddenNeuronNumber;j++)
        
            layer_network[2]->neuron_layer[i]->inputs[j]->weights = layer_network[1]->neuron_layer[j]->inputs[i]->weights;
        
    

这是神经元.cpp:

#include "neuron.h"
#include <stdio.h>
#include <iostream>

using namespace std;

synapse::synapse()



synapse::~synapse()



neuron::neuron(int numberOfInput,int numberOfOutput):
inputs(numberOfInput),outputs(numberOfOutput)

    for(int i=0;i<numberOfInput;i++)
    
        inputs[i] = new synapse();
    
    for(int i=0;i<numberOfOutput;i++)
    
        outputs[i] = new synapse();
    

neuron::~neuron()



int neuron::get_input_size()

    int input_length;
    input_length=(int) inputs.size();
    return input_length;


int neuron::get_output_size()

    int output_length;
    output_length=(int) outputs.size();
    return output_length;



void neuron::input_fire()

    output_value = inputs[0]->activation_values;
    for(int i=0;i<get_output_size();i++)
    
        outputs[i]->activation_values = output_value;
    


void neuron::fire()

    output_value = 0.0f;
    for(int i=0;i<get_input_size();i++)
    
        output_value+=(inputs[i]->activation_values)*(inputs[i]->weights);
    
    //cout<<endl<<"Before Sigmoid"<<output_value;
    output_value = 1.0f / (1.0f+ exp(-output_value));
    //cout<<" After Sigmoid"<<output_value;
    for(int i=0;i<get_output_size();i++)
    
        outputs[i]->activation_values = output_value;
    


我认为我不需要发布 neuron.h 和 network.h 因为它们都只包含声明。我在.cpp 中定义函数。这就是我创建对象的方式:

srand (time(NULL));
float inputTest[2500];
network test(3,1800);
test.init_network(1800);
for(int i=0;i<2500;i++)

    inputTest[i]=(float)rand()/(float)RAND_MAX;

test.feedforward(inputTest);

【问题讨论】:

您的日志显示为output -&gt; hidden 1 1 1 1 1 - 这是否意味着输出权重都是1-s?尝试较小的结构(从您提到的 2-3-1 及以上开始),看看网络是否饱和。还可以考虑使用一些众所周知且经过验证的实现。 output -> hidden 1 1 1 1 1 表示隐藏层的所有输出都是1,我想这可能是我出错的地方。我尝试创建一个较小的结构,并且效果很好我已经通过手动计算检查了结果 【参考方案1】:

我没有检查您的代码,但是... 不,你不能像那样使用固定重量。随着输入量的增加,隐藏层中的每个节点都会获得越来越大的值。 Sigmoid 会将较大的值缩放为 1。

想一想: 假设您有 100 个输入,每个输入的“随机”输入值为 0.1。为简单起见,让我们忘记其他一切。由于您的权重是恒定的 0.5,因此隐藏层中的所有节点将获得相同的值,该值由每个输入*权重的“sigmoided”总和组成,即 sigm(0.1*0.5*100) = sigm(5) -> ~ 1

因此,具有恒定正权重的正输入越多,所有隐藏层的输出就越接近 1。

【讨论】:

以上是关于神经网络输出始终为 1的主要内容,如果未能解决你的问题,请参考以下文章

训练时 Keras 神经网络精度始终为 0

多输出 Keras 的回归损失函数

LocationManager:是不是始终启用“网络”提供程序?

神经网络结果始终相同

神经网络的输出维度为2,怎么取

始终检查 Cocoa 中的网络可达性