Я занимаюсь разработкой приложения для нейронной сети, но у меня возникает проблема, когда я пытаюсь распечатать вывод обратной связи: консоль показывает это значение:
Выход всегда 1 1 1 1 1
Я использую 3 слоя, состоящие из 2500 входных узлов, 1800 скрытых узлов и 5 выходных узлов.
В качестве функции активации я использую сигмовидный бинарный файл, вес для тестирования установлен на 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;
}
}
}
Это neuron.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);
Я не проверял твой код, но …
Нет, вы не можете использовать фиксированный вес таким образом. Каждый узел в вашем скрытом слое будет получать все больше и больше значений по мере увеличения количества входных данных. Сигмоид будет масштабировать большие значения до 1.
Думаю об этом:
Допустим, у вас есть 100 входов, каждый из которых имеет «случайное» входное значение 0,1. Для простоты давайте просто забудем обо всем остальном. Поскольку ваши веса постоянны 0,5, все узлы в скрытом слое получат одно и то же значение, которое состоит из «сигмоидальной» суммы каждого входного * веса, то есть сигма (0,1 * 0,5 * 100) = сигма (5) -> ~ 1
Таким образом, чем больше у вас положительных входных данных с постоянными положительными весами, тем ближе все значения скрытых слоев к 1.
Других решений пока нет …