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
00103
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
00157 currlayer->at(j)->SetDelta(Layers.back().at(j)->CalcDeriv(Layers.back().at(j)->GetNet())
00158 * (LocDesired.at(j) - LocOutput.at(j)));
00159
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
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
00173 for (size_t i = Layers.size() -2; i >= 1;--i)
00174 {
00175
00176 for (size_t j = 0; j < Layers.at(i-1).size(); ++j)
00177 Layers.at(i-1).at(j)->SetDelta(0.0);
00178
00179 for (tNeuralLayer::iterator currneuron = Layers.at(i).begin(); currneuron < Layers.at(i).end(); ++ currneuron)
00180 {
00181
00182 currneuron->get()->SetDelta(currneuron->get()->GetDelta() *
00183 currneuron->get()->CalcDeriv(currneuron->get()->GetNet()));
00184
00185 for (size_t k = 0; k < currneuron->get()->GetWeights().size(); ++k)
00186 {
00187
00188 currneuron->get()->GetInput().at(k)->SetDelta(currneuron->get()->GetInput().at(k)->GetDelta()
00189 + currneuron->get()->GetWeights().at(k) * currneuron->get()->GetDelta());
00190
00191 correction =alpha * currneuron->get()->GetOldDelta().at(k)+
00192 mu * currneuron->get()->GetInput().at(k)->GetLastOutput() * currneuron->get()->GetDelta();
00193
00194 currneuron->get()->SetWeights().at(k) += correction;
00195
00196 currneuron->get()->SetOldDelta().at(k) = correction;
00197 }
00198
00199 currneuron->get()->SetBias(currneuron->get()->GetBias() + mu * currneuron->get()->GetDelta());
00200 }
00201 }
00202
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
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
00243
00244
00245
00246
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
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
00263
00264
00265
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 }