2015-06-20 2 views
2

Я работаю над очень простой нервной сетью, чтобы практиковать свои навыки программирования. Имеются 3 категории:Выход нейронной сети имеет одинаковые значения каждый раз

  • Neural :: Net; строит сеть, подает вперед входные значения (на данный момент нет обратного распространения)
  • Neural :: Neuron; имеет характеристики нейрона (индекс, мощность, вес и т. д.)
  • Neural :: Connection; структурно-подобный класс, который рандомизирует вес и удерживает выход, дельта-вес и т. д.

Программа очень простая: я создаю сеть с двумя скрытыми слоями и рандомизированными весами, а затем прошу ее подавать вперед одинаковые входные значения.

Моя проблема: ожидается, что после каждого прогона программа будет иметь разные выходные значения, но вывод всегда будет одинаковым. Я пробовал размещать маркеры повсюду, чтобы понять, почему он вычисляет одно и то же снова и снова, но я не могу погладить ошибку.

Вот код:

#include <iostream> 
#include <cassert> 
#include <cstdlib> 
#include <vector> 
#include "ConsoleColor.hpp" 

using namespace std; 

namespace Neural { 
    class Neuron; 
    typedef vector<Neuron> Layer; 

    // ******************** Class: Connection ******************** // 
    class Connection { 
    public: 
     Connection(); 
     void setOutput(const double& outputVal) { myOutputVal = outputVal; } 
     void setWeight(const double& weight) { myDeltaWeight = myWeight - weight; myWeight = weight; } 
     double getOutput(void) const { return myOutputVal; } 
     double getWeight(void) const { return myWeight; } 
    private: 
     static double randomizeWeight(void) { return rand()/double(RAND_MAX); } 
     double myOutputVal; 
     double myWeight; 
     double myDeltaWeight; 
    }; 

    Connection::Connection() { 
     myOutputVal = 0; 
     myWeight = Connection::randomizeWeight(); 
     myDeltaWeight = myWeight; 
     cout << "Weight: " << myWeight << endl; 
    } 

    // ******************** Class: Neuron ************************ // 
    class Neuron { 
    public: 
     Neuron(); 
     void setIndex(const unsigned int& index) { myIndex = index; } 
     void setOutput(const double& output) { myConnection.setOutput(output); } 
     unsigned int getIndex(void) const { return myIndex; } 
     double getOutput(void) const { return myConnection.getOutput(); } 
     void feedForward(const Layer& prevLayer); 
     void printOutput(void) const; 

    private: 
     inline static double transfer(const double& weightedSum); 
     Connection myConnection; 
     unsigned int myIndex; 
    }; 

    Neuron::Neuron() : myIndex(0), myConnection() { } 
    double Neuron::transfer(const double& weightedSum) { return 1/double((1 + exp(-weightedSum))); } 
    void Neuron::printOutput(void) const { cout << "Neuron " << myIndex << ':' << myConnection.getOutput() << endl; } 
    void Neuron::feedForward(const Layer& prevLayer) { 
     // Weight sum of the previous layer's output values 
     double weightedSum = 0; 
     for (unsigned int i = 0; i < prevLayer.size(); ++i) { 
      weightedSum += prevLayer[i].getOutput()*myConnection.getWeight(); 
      cout << "Neuron " << i << " from prevLayer has output: " << prevLayer[i].getOutput() << endl; 
      cout << "Weighted sum: " << weightedSum << endl; 
     } 
     // Transfer function 
     myConnection.setOutput(Neuron::transfer(weightedSum)); 
     cout << "Transfer: " << myConnection.getOutput() << endl; 
    } 

    // ******************** Class: Net *************************** // 
    class Net { 
    public: 
     Net(const vector<unsigned int>& topology); 
     void setTarget(const vector<double>& targetVals); 
     void feedForward(const vector<double>& inputVals); 
     void backPropagate(void); 
     void printOutput(void) const; 
    private: 
     vector<Layer> myLayers; 
     vector<double> myTargetVals; 

    }; 
    Net::Net(const vector<unsigned int>& topology) : myTargetVals() { 
     assert(topology.size() > 0); 
     for (unsigned int i = 0; i < topology.size(); ++i) { // Creating the layers 
      myLayers.push_back(Layer(((i + 1) == topology.size()) ? topology[i] : topology[i] + 1)); // +1 is for bias neuron 
      // Setting each neurons index inside layer 
      for (unsigned int j = 0; j < myLayers[i].size(); ++j) { 
       myLayers[i][j].setIndex(j); 
      } 
      // Console log 
      cout << red; 
      if (i == 0) { 
       cout << "Input layer (" << myLayers[i].size() << " neurons including bias neuron) created." << endl; 
       myLayers[i].back().setOutput(1); 
      } 
      else if (i < topology.size() - 1) { 
       cout << "Hidden layer " << i << " (" << myLayers[i].size() << " neurons including bias neuron) created." << endl; 
       myLayers[i].back().setOutput(1); 
      } 
      else { cout << "Output layer (" << myLayers[i].size() << " neurons) created." << endl; } 
      cout << white; 
     } 
    } 
    void Net::setTarget(const vector<double>& targetVals) { assert(targetVals.size() == myLayers.back().size()); myTargetVals = targetVals; } 
    void Net::feedForward(const vector<double>& inputVals) { 
     assert(myLayers[0].size() - 1 == inputVals.size()); 
     for (unsigned int i = 0; i < inputVals.size(); ++i) { // Setting input vals to input layer 
      cout << yellow << "Setting input vals..."; 
      myLayers[0][i].setOutput(inputVals[i]); // myLayers[0] is the input layer 
      cout << "myLayer[0][" << i << "].getOutput()==" << myLayers[0][i].getOutput() << white << endl; 
     } 
     for (unsigned int i = 1; i < myLayers.size() - 1; ++i) { // Updating hidden layers 
      for (unsigned int j = 0; j < myLayers[i].size() - 1; ++j) { // - 1 because bias neurons do not have input 
       cout << "myLayers[" << i << "].size()==" << myLayers[i].size() << endl; 
       cout << green << "Updating neuron " << j << " inside layer " << i << white << endl; 
       myLayers[i][j].feedForward(myLayers[i - 1]); // Updating the neurons output based on the neurons of the previous layer 
      } 
     } 
     for (unsigned int i = 0; i < myLayers.back().size(); ++i) { // Updating output layer 
      cout << green << "Updating output neuron " << i << ": " << white << endl; 
      const Layer& prevLayer = myLayers[myLayers.size() - 2]; 
      myLayers.back()[i].feedForward(prevLayer); // Updating the neurons output based on the neurons of the previous layer 
     } 
    } 
    void Net::printOutput(void) const { 
     for (unsigned int i = 0; i < myLayers.back().size(); ++i) { 
      cout << blue; myLayers.back()[i].printOutput(); cout << white; 
     } 
    } 
    void Net::backPropagate(void) { 

    } 
} 

int main(int argc, char* argv[]) { 
    vector<unsigned int> myTopology; 
    myTopology.push_back(3); 
    myTopology.push_back(4); 
    myTopology.push_back(2); 
    myTopology.push_back(2); 

    cout << myTopology.size() << endl << endl; // myTopology == {3, 4, 2 ,1} 

    vector<double> myTargetVals= {0.5,1}; 
    vector<double> myInputVals= {1, 0.5, 1}; 

    Neural::Net myNet(myTopology); 
    myNet.feedForward(myInputVals); 
    myNet.printOutput(); 

    return 0; 
} 

Edit: Я понял, что смещение нейрона во входном слое был правильно установлен на выходе 1, а те, в скрытых слоях установлены в 0, и я установил, что. Но выходы остаются одинаковыми при каждом запуске. Я сделал математику на листе бумаги и все получилось. Вот вывод (цветовой код для ясности):

Console log

Я ожидал, что значения, чтобы быть случайными, как и весы. Разве это не так? Я запутался.

ответ

0

Я нашел свою ошибку. Я думал, что rand() автоматически инициализировал свое семя. Я знал, что это глупо. Я добавил srand(time(NULL)); в начале программы, и теперь он работает так, как должен.

Смежные вопросы