NeuralNetwork.cpp

Go to the documentation of this file.
00001 #include "NeuralNetwork.h"
00002 #include "UniformRNG.h"
00003 #include "Adaptors.h"
00004 #include <algorithm>
00005 #include <iostream>
00006 #include <fstream>
00007 using namespace std;
00008 
00009 NeuralNetwork::NeuralNetwork(const int inputsize, const int outputsize):
00010 AdaptiveFilter(inputsize,outputsize),
00011 alpha(0.0),
00012 mu(0.0),
00013 LocInput(inputsize,0.0),
00014 LocOutput(outputsize,0.0),
00015 LocDesired(outputsize,0.0)
00016 {}
00017 
00018 NeuralNetwork::NeuralNetwork(const int inputsize, const int outputsize, 
00019         const double mu_, const ttypeArray &Layersetup, const double maxinit, bool cachedoutput):
00020 AdaptiveFilter(inputsize,outputsize),
00021 alpha(0.0),
00022 mu(mu_),
00023 LocInput(inputsize,0.0),
00024 LocOutput(outputsize,0.0),
00025 LocDesired(outputsize,0.0)
00026 {
00027         SetLayers(Layersetup, cachedoutput);
00028         InitWeights(maxinit,maxinit);
00029 }
00030 
00031 NeuralNetwork::~NeuralNetwork()
00032 {}
00033 
00034 void NeuralNetwork::AdaptFilter(const gplib::rvec &Input, const gplib::rvec &Desired)
00035 {
00036         if (Desired.size() !=LocDesired.size())
00037                 throw CFatalException("Input does not match network geometry !");
00038         copy(Desired.begin(),Desired.end(),LocDesired.begin());
00039         AdaptWeights();
00040         SetEpsilon(Desired - GetFilterOutput());
00041 }
00042 
00043 void NeuralNetwork::CalcOutput(const gplib::rvec &Input, gplib::rvec &Output)
00044 {
00045         if (Input.size() !=LocInput.size())
00046                 throw CFatalException("Input does not match network geometry !");
00047         copy(Input.begin(),Input.end(),LocInput.begin());
00048         CalcOutput();
00049         if (Output.size() != LocOutput.size())
00050                 throw CFatalException("Output does not match network geometry !");
00051         copy(LocOutput.begin(),LocOutput.end(),Output.begin());
00052         SetOutput(Output);
00053 }
00054 
00055 const gplib::rvec &NeuralNetwork::GetWeightsAsVector()
00056 {
00057         size_t size = 0;
00058         for (size_t i = 1; i < Layers.size(); ++i)
00059         {
00060                 for (size_t j = 0; j < Layers.at(i).size(); ++j)
00061                         size += Layers.at(i).at(j)->GetWeights().size();
00062         } 
00063         gplib::rvec temp(size);
00064         size_t currstart = 0;
00065         for (size_t i = 1; i < Layers.size(); ++i)
00066         {
00067                 for (size_t j = 0; j < Layers.at(i).size(); ++j)
00068                 {
00069                         for (size_t k = 0; k < Layers.at(i).at(j)->GetWeights().size(); ++k)
00070                                 temp(currstart+k) = Layers.at(i).at(j)->GetWeights().at(k);
00071                         currstart += Layers.at(i).at(j)->GetWeights().size();
00072                 }
00073         }
00074         WeightsAsVector = temp;
00075         return WeightsAsVector;
00076 }
00077 
00078 void NeuralNetwork::SetLayers(ttypeArray typeArray, bool cachedoutput)
00079 {
00080         tNeuralLayer CurrentLayer;
00081         GeneralLinearCombiner::tinvector inputvector;
00082         
00083         const size_t nlayers = typeArray.size();
00084         LocOutput.assign(typeArray.back().size(),0);
00085         LocDesired.assign(typeArray.back().size(),0);
00086         for (size_t i = 0; i < LocInput.size(); ++i)
00087                 CurrentLayer.push_back(boost::shared_ptr<GeneralNeuron>(new InputNeuron(LocInput.at(i))));
00088         Layers.push_back(CurrentLayer);
00089         CurrentLayer.clear();
00090         cout << "Nlayers: " << nlayers << endl;
00091         for (size_t i = 0; i < nlayers; ++i)
00092         {
00093                 for (size_t j = 0; j < typeArray.at(i).size(); ++j)
00094                 {
00095                         CurrentLayer.push_back(boost::shared_ptr<GeneralNeuron>(new SigmoidalNeuron(typeArray.at(i).at(j),cachedoutput)));
00096                         cout << "Type: " << typeArray.at(i).at(j) << endl;
00097                 }
00098                 cout << "TypeArray Size: " << typeArray.at(i).size() << endl;
00099                 Layers.push_back(CurrentLayer);
00100                 CurrentLayer.clear();
00101         }
00102         //for (int i = 0; i < typeArray.at(0).size(); ++i)
00103         //      Layers.at(0).at(i)->SetInput(inputvector);
00104         cout << "Actual layers: " << Layers.size() << endl;
00105         for (size_t i = 1; i < nlayers+1; ++i)
00106         {
00107                 inputvector.clear();
00108                 const size_t prevsize = Layers.at(i-1).size();
00109                 cout << "Previous layer size: " << prevsize << endl;
00110                 for (size_t j = 0; j < prevsize; ++j)
00111                 {
00112                         inputvector.push_back(Layers.at(i-1).at(j));
00113                 }
00114                 for (size_t j = 0; j < Layers.at(i).size(); ++j)
00115                 {
00116                         Layers.at(i).at(j)->SetInput(inputvector);
00117                         Layers.at(i).at(j)->SetOldDelta().assign(prevsize,0.0);
00118                 }
00119         }       
00120 }
00121 
00122 void NeuralNetwork::InitWeights(const double MaxWeight, const double MaxBias)
00123 {
00124         UniformRNG Random;
00125         for (size_t i = 1; i < Layers.size(); ++i)
00126                 for (size_t j = 0; j < Layers.at(i).size(); ++j)
00127                 {
00128                         for (size_t k = 0; k < Layers.at(i).at(j)->GetWeights().size(); ++k)
00129                         {
00130                                 Layers.at(i).at(j)->SetWeights().at(k) = Random.GetNumber(-MaxWeight,MaxWeight);
00131                                 Layers.at(i).at(j)->SetOldDelta().at(k) = 0.0;
00132                         }
00133                         Layers.at(i).at(j)->SetBias(Random.GetNumber(-MaxBias,MaxBias));
00134                 }
00135 }
00136 
00137 std::vector<double> &NeuralNetwork::CalcOutput()
00138 {
00139         gplib::rvec temp(LocOutput.size());
00140         for (size_t i = 0; i < Layers.back().size(); ++i)
00141         {
00142                 LocOutput.at(i) = Layers.back().at(i)->GetOutput(); 
00143         }
00144         return LocOutput;
00145 }
00146 
00147 void NeuralNetwork::AdaptWeights()
00148 {
00149         tNeuralArray::iterator previouslayer=(Layers.end() - 2);
00150         tNeuralArray::iterator currlayer = (Layers.end() - 1);
00151         double correction = 0.0;
00152         for (size_t i = 0; i < previouslayer->size(); ++i)
00153                 previouslayer->at(i)->SetDelta(0.0);
00154         for (size_t j = 0; j < currlayer->size(); ++j)
00155         {
00156                 // Delta for the last layer depends on the difference between output and reference
00157                 currlayer->at(j)->SetDelta(Layers.back().at(j)->CalcDeriv(Layers.back().at(j)->GetNet()) 
00158                         * (LocDesired.at(j) - LocOutput.at(j)));
00159                 //follow all the weights to update delta for the previous layer
00160                 for (size_t i = 0; i < currlayer->at(j)->GetWeights().size(); ++i)
00161                 { 
00162                         currlayer->at(j)->GetInput().at(i)->SetDelta(currlayer->at(j)->GetInput().at(i)->GetDelta()  
00163                                         + currlayer->at(j)->GetWeights().at(i) * currlayer->at(j)->GetDelta());
00164                         //calculate the correction for the last layer
00165                         correction = alpha * currlayer->at(j)->GetOldDelta().at(i) + 
00166                                         mu * (previouslayer->at(i)->GetLastOutput()) * Layers.back().at(j)->GetDelta();
00167                         currlayer->at(j)->SetWeights().at(i) += correction;
00168                         currlayer->at(j)->SetOldDelta().at(i) =         correction;                     
00169                 }
00170                 currlayer->at(j)->SetBias(Layers.back().at(j)->GetBias() + mu * Layers.back().at(j)->GetDelta());
00171         }
00172         //for all layers but the last and the first one 
00173         for (size_t i = Layers.size() -2; i >= 1;--i)
00174         {
00175                 //initialize delta for previous layer
00176                 for (size_t j = 0; j < Layers.at(i-1).size(); ++j)
00177                         Layers.at(i-1).at(j)->SetDelta(0.0);
00178                 //for all neurons in the current layer
00179                 for (tNeuralLayer::iterator currneuron = Layers.at(i).begin(); currneuron < Layers.at(i).end(); ++ currneuron)
00180                 {
00181                         //multiply delta of current neuron by derivative of activation function
00182                         currneuron->get()->SetDelta(currneuron->get()->GetDelta() * 
00183                                         currneuron->get()->CalcDeriv(currneuron->get()->GetNet()));
00184                         //for all weights of the current neuron
00185                         for (size_t k = 0; k < currneuron->get()->GetWeights().size(); ++k)
00186                         {
00187                                 //propagate delta along the weight to the previous layer
00188                                 currneuron->get()->GetInput().at(k)->SetDelta(currneuron->get()->GetInput().at(k)->GetDelta() 
00189                                         + currneuron->get()->GetWeights().at(k) * currneuron->get()->GetDelta());
00190                                 //calculate the correction for the current layer
00191                                 correction =alpha * currneuron->get()->GetOldDelta().at(k)+
00192                                                         mu * currneuron->get()->GetInput().at(k)->GetLastOutput() * currneuron->get()->GetDelta();
00193                                 //apply weight correction 
00194                                 currneuron->get()->SetWeights().at(k) +=  correction;
00195                                 //store weight correction for feedback loop             
00196                                 currneuron->get()->SetOldDelta().at(k) = correction;
00197                         }
00198                         
00199                         currneuron->get()->SetBias(currneuron->get()->GetBias() + mu * currneuron->get()->GetDelta());
00200                 }
00201         }
00202         //we do not have to consider the first layer, it only gets the input
00203 }
00204 
00205 void NeuralNetwork::PrintWeights(ostream &output)
00206 {
00207         for (size_t i = 1; i < Layers.size(); ++i)
00208         {
00209                 for (size_t j = 0; j < Layers.at(i).size(); ++j)
00210                 {
00211                         copy(Layers.at(i).at(j)->GetWeights().begin(),Layers.at(i).at(j)->GetWeights().end(),ostream_iterator<double>(output," "));
00212                 }
00213         }
00214         output << endl;
00215 }
00216 
00217 void NeuralNetwork::PrintTopology(std::string filename)
00218 {
00219         gplib::rvec WeightVector = GetWeightsAsVector();
00220         const double maxpower = fabs(*max_element(WeightVector.begin(),WeightVector.end(),gplib::absLess<double,double>()));
00221         std::ofstream output(filename.c_str());
00222         output << "digraph network {" << endl;
00223         for (size_t i = 0; i < Layers.front().size(); ++i)
00224         {
00225                 output << "node [shape=point];" << std::endl;
00226                 output << "i"<<i << " -> input"<<i<<";" << std::endl;
00227                 output << "input"<< i << " [shape=circle];"<<std::endl;
00228                 for (size_t j = 0; j < Layers.at(1).size(); ++j)
00229                 {
00230                         output << "input"<< i << " -> n1" << j;
00231                         //output <<  "[label =\" " << Layers.at(1).at(j)->GetWeights().at(i) << " \"]";
00232                         output <<  "[color =\" 0.7 1.0 " << 0.1 + fabs(Layers.at(1).at(j)->GetWeights().at(i))/maxpower << " \"]";
00233                         output << ";" << std::endl;
00234                 }
00235         }
00236         for (size_t i = 1; i < Layers.size()-1; ++i)
00237         {
00238                 output << "{ rank=same;" << std::endl;
00239                 for (size_t j =0; j < Layers.at(i).size(); ++j)
00240                 {
00241                         output << "n" << i << j << " [shape=circle];"<<std::endl;
00242                         //output << "b" << i << j << " [shape=point];"<<std::endl;
00243                         //output << "b" << i << j << " -> n" << i << j;
00244                         //output << "[label =\" " << Layers.at(i).at(j)->GetBias() << " \"] ";
00245                         //output <<  "[color =\" " << Layers.at(1).at(j)->GetBias()/maxpower << " 1.0 1.0\"]";
00246                         //output << ";" << std::endl;
00247                 }
00248                 output << "};" << std::endl;
00249                 for (size_t j =0; j < Layers.at(i).size(); ++j)
00250                 for (size_t k = 0; k < Layers.at(i+1).size(); ++k)
00251                         {
00252                                 output << "n" << i << j << " -> n" << i+1 << k;
00253                                 //output <<  "[label =\" " << Layers.at(i+1).at(k)->GetWeights().at(j) << " \"]";
00254                                 output <<  "[color =\" 0.7 1.0 " <<  0.1 + fabs(Layers.at(i+1).at(k)->GetWeights().at(j))/maxpower << " \"]";
00255                                 output << ";" << std::endl;
00256                         }
00257         }
00258         output << "{ rank=same;" << std::endl;
00259         for (size_t i = 0; i < Layers.back().size(); ++i)
00260         {
00261                 output << "n" << Layers.size()-1 << i << " [shape=circle];"<<std::endl;
00262                 //output << "b" << Layers.size()-1 << i << " -> n" << Layers.size()-1 << i; 
00263                 //output <<  "[color =\" " << Layers.at(Layers.size()-1).at(i)->GetBias()/maxpower << " 1.0 1.0\"]";
00264                 //output <<  "[label =\" " << Layers.at(Layers.size()-1).at(i)->GetBias() << " \"]";
00265                 //output << ";" << std::endl;
00266         }
00267         output << "};" << std::endl;
00268         for (size_t i = 0; i < Layers.back().size(); ++i)
00269         {
00270                 output << "output"<< i << " [shape=point];"<<std::endl;
00271                 for (size_t j =0; j < Layers.at(Layers.size()-1).size(); ++j)
00272                 {
00273                         output << "n" << Layers.size()-1 << j << " -> output" << i << ";" << std::endl;
00274                 }
00275         }
00276         output << "}";
00277 }

Generated on Fri Jul 4 15:30:21 2008 for GPLIB++ by  doxygen 1.5.5