net.cpp #include #include #include "net.h" #include "layer.h" #include "neuron.h" #include "connection.h" typedef std::shared_ptr pConnectionX; typedef std::vector pConnection; /* It has been shown that the error surface of a backpropagation network with one hidden layer and hidden units has no local minima, if the network is trained with an arbitrary set containing different inputs1 (Yu, 1992). In practice, however, other features of the error surface such as "ravines" and "plateaus" (Baldi and Hornik, 1988) can present difficulty for optimisation. For example, two error functions (from (Gori, 1996)) do not have local minima. However, the function on the left is expected to be more difficult to optimise with gradient descent. For the purposes of this paper, the criterion of interest considered is "the best solution found in a given practical time limit. */ Net::Net() : discount_factor(0.4), goal_amount(100.0), learning_rate(0.5), max_error_tollerance(0.1) { layers.reserve(10); } // Example: // std::vector myTopology; // myTopology.push_back(2); // myTopology.push_back(4); // myTopology.push_back(1); // Net myNet(myTopology); Net::Net(const std::vector& topology) : discount_factor(0.4), goal_amount(100.0), learning_rate(0.5), max_error_tollerance(0.1) { assert(topology.size() > 0); discount_factor = 0.4; goal_amount = 100.0; learning_rate = 0.5; max_error_tollerance = 0.1; layers.reserve(topology.size()); // obtain a time-based seed: //unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); // using built-in random generator: //shuffle (topology.begin(), topology.end(), std::default_random_engine(seed)); //auto engine = std::default_random_engine{}; //std::shuffle(std::begin(topology), std::end(topology), engine); //std::random_shuffle ( topology.begin(), topology.end()); //std::shuffle ( topology.begin(), topology.end() ); for (unsigned int i = 0; isetIndex(i); tmp->setGlobalBias(global_bias); layers.push_back(tmp); } std::cout << "layers size: " << layers.size() << std::endl; for (unsigned int i = 0; i < layers.size(); i++) { std::cout << "layers " << i << " neurons size: " << layers[i]->getSize() << std::endl; } //printOutput(); // Add Bias to input and hidden layers. //layers[1]->addNeuron( //connectAll(); //connectForward(); //printOutput(); } // Connects the "From" Neuron to the "To" Neuron. void Net::connect(const std::vector< std::vector > connections) { //unsigned int connection_idx = 1; int connection_idx = 0; for (unsigned int i = 0; i < connections.size(); i++) { //for (unsigned int j = 0; j < connections[i].size(); j++) //{ int layerFrom = (int)connections[i][0]; int neuronFrom = (int)connections[i][1]; int layerTo = (int)connections[i][2]; int neuronTo = (int)connections[i][3]; double _R = connections[i][4]; pConnectionX tmp(new Connection(layers[layerFrom]->getNeuron(neuronFrom), layers[layerTo]->getNeuron(neuronTo))); tmp->setIndex(connection_idx++); tmp->setQ(0); tmp->setR(_R); layers[layerFrom]->getNeuron(neuronFrom)->addConnectionOut(tmp); layers[layerTo]->getNeuron(neuronTo)->addConnectionIn(tmp); //} } } // Connects the "From" Neuron to the "To" Neuron. void Net::connect(int layerFrom, int neuronFrom, int layerTo, int neuronTo, double _R, int connection_idx) { //unsigned int connection_idx = 1; pConnectionX tmp(new Connection(layers[layerFrom]->getNeuron(neuronFrom), layers[layerTo]->getNeuron(neuronTo))); tmp->setIndex(connection_idx); tmp->setQ(0); tmp->setR(_R); layers[layerFrom]->getNeuron(neuronFrom)->addConnectionOut(tmp); layers[layerTo]->getNeuron(neuronTo)->addConnectionIn(tmp); } // Connects all Neurons to each other. void Net::connectAll() { // assert(layer.size() > 1); // There must be more than 1 neuron to connect. int connection_idx = 0; for (unsigned int i = 0; igetSize(); j++) // For each neuron in Sending Layer. { for (unsigned int k = 0; kgetSize(); l++) // For each neuron in Receiving layer. { pConnectionX tmp(new Connection(layers[i]->getNeuron(j), layers[k]->getNeuron(l))); tmp->setIndex(connection_idx++); layers[i]->getNeuron(j)->addConnectionOut(tmp); layers[k]->getNeuron(l)->addConnectionIn(tmp); //std::cout << "I[" << j << "] connected to H[" << k << "] with Connection IDX=" << connection_idx-1 << std::endl; } } } } } // Connects all Neurons in a layer to all Neurons in the next layer. void Net::connectForward() { unsigned int connection_idx = 0; for (unsigned int i = 0; igetSize(); j++) // how many input neurons in input level. { for (unsigned int k = 0; kgetSize(); k++) // how many neurons in next level. { pConnectionX tmp(new Connection(layers[i]->getNeuron(j), layers[i + 1]->getNeuron(k))); tmp->setIndex(connection_idx++); layers[i]->getNeuron(j)->addConnectionOut(tmp); layers[i + 1]->getNeuron(k)->addConnectionIn(tmp); //std::cout << "I[" << j << "] connected to H[" << k << "] with Connection IDX=" << connection_idx-1 << std::endl; } } } } // Same as connectForward() but code spread out between layers. // Connects all Neurons to Neurons in next layer. void Net::connectForward2() { unsigned int connection_idx = 0; // Create the input to hidden connections. // assert(layers.size() > 1); // There must be more than 1 layers to connect. for (unsigned int i = 0; i