00001 #include "NeuralNetwork.h"
00002 #include "UniformRNG.h"
00003 #include "Adaptors.h"
00004 #include "FatalException.h"
00005 #include <algorithm>
00006 #include <iostream>
00007 #include <fstream>
00008
00009 using namespace std;
00010
00011 namespace gplib
00012 {
00013 NeuralNetwork::NeuralNetwork(const int inputsize, const int outputsize) :
00014 AdaptiveFilter(inputsize, outputsize), alpha(0.0), mu(0.0), LocInput(
00015 inputsize, 0.0), LocOutput(outputsize, 0.0), LocDesired(outputsize,
00016 0.0)
00017 {
00018 }
00019
00020 NeuralNetwork::NeuralNetwork(const int inputsize, const int outputsize,
00021 const double mu_, const ttypeArray &Layersetup, const double maxinit,
00022 bool cachedoutput) :
00023 AdaptiveFilter(inputsize, outputsize), alpha(0.0), mu(mu_), LocInput(
00024 inputsize, 0.0), LocOutput(outputsize, 0.0), LocDesired(outputsize,
00025 0.0)
00026 {
00027 SetLayers(Layersetup, cachedoutput);
00028 InitWeights(maxinit, maxinit);
00029 }
00030
00031 NeuralNetwork::~NeuralNetwork()
00032 {
00033 }
00034
00035 void NeuralNetwork::AdaptFilter(const gplib::rvec &Input,
00036 const gplib::rvec &Desired)
00037 {
00038 if (Desired.size() != LocDesired.size())
00039 throw FatalException("Input does not match network geometry !");
00040 copy(Desired.begin(), Desired.end(), LocDesired.begin());
00041 AdaptWeights();
00042 SetEpsilon(Desired - GetFilterOutput());
00043 }
00044
00045 void NeuralNetwork::CalcOutput(const gplib::rvec &Input,
00046 gplib::rvec &Output)
00047 {
00048 if (Input.size() != LocInput.size())
00049 throw FatalException("Input does not match network geometry !");
00050 copy(Input.begin(), Input.end(), LocInput.begin());
00051 CalcOutput();
00052 if (Output.size() != LocOutput.size())
00053 throw FatalException("Output does not match network geometry !");
00054 copy(LocOutput.begin(), LocOutput.end(), Output.begin());
00055 SetOutput(Output);
00056 }
00057
00058 const gplib::rvec &NeuralNetwork::GetWeightsAsVector()
00059 {
00060 size_t size = 0;
00061 for (size_t i = 1; i < Layers.size(); ++i)
00062 {
00063 for (size_t j = 0; j < Layers.at(i).size(); ++j)
00064 size += Layers.at(i).at(j)->GetWeights().size();
00065 }
00066 gplib::rvec temp(size);
00067 size_t currstart = 0;
00068 for (size_t i = 1; i < Layers.size(); ++i)
00069 {
00070 for (size_t j = 0; j < Layers.at(i).size(); ++j)
00071 {
00072 for (size_t k = 0; k < Layers.at(i).at(j)->GetWeights().size(); ++k)
00073 temp(currstart + k) = Layers.at(i).at(j)->GetWeights().at(k);
00074 currstart += Layers.at(i).at(j)->GetWeights().size();
00075 }
00076 }
00077 WeightsAsVector = temp;
00078 return WeightsAsVector;
00079 }
00080
00081 void NeuralNetwork::SetLayers(ttypeArray typeArray, bool cachedoutput)
00082 {
00083 tNeuralLayer CurrentLayer;
00084 GeneralLinearCombiner::tinvector inputvector;
00085
00086 const size_t nlayers = typeArray.size();
00087 LocOutput.assign(typeArray.back().size(), 0);
00088 LocDesired.assign(typeArray.back().size(), 0);
00089 for (size_t i = 0; i < LocInput.size(); ++i)
00090 CurrentLayer.push_back(boost::shared_ptr<GeneralNeuron>(
00091 new InputNeuron(LocInput.at(i))));
00092 Layers.push_back(CurrentLayer);
00093 CurrentLayer.clear();
00094 cout << "Nlayers: " << nlayers << endl;
00095 for (size_t i = 0; i < nlayers; ++i)
00096 {
00097 for (size_t j = 0; j < typeArray.at(i).size(); ++j)
00098 {
00099 CurrentLayer.push_back(boost::shared_ptr<GeneralNeuron>(
00100 new SigmoidalNeuron(typeArray.at(i).at(j), cachedoutput)));
00101 }
00102 Layers.push_back(CurrentLayer);
00103 CurrentLayer.clear();
00104 }
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,
00123 const double MaxBias)
00124 {
00125 UniformRNG Random;
00126 for (size_t i = 1; i < Layers.size(); ++i)
00127 for (size_t j = 0; j < Layers.at(i).size(); ++j)
00128 {
00129 for (size_t k = 0; k < Layers.at(i).at(j)->GetWeights().size(); ++k)
00130 {
00131 Layers.at(i).at(j)->SetWeights().at(k) = Random.GetNumber(
00132 -MaxWeight, MaxWeight);
00133 Layers.at(i).at(j)->SetOldDelta().at(k) = 0.0;
00134 }
00135 Layers.at(i).at(j)->SetBias(Random.GetNumber(-MaxBias, MaxBias));
00136 }
00137 }
00138
00139 std::vector<double> &NeuralNetwork::CalcOutput()
00140 {
00141 gplib::rvec temp(LocOutput.size());
00142 for (size_t i = 0; i < Layers.back().size(); ++i)
00143 {
00144 LocOutput.at(i) = Layers.back().at(i)->GetOutput();
00145 }
00146 return LocOutput;
00147 }
00148
00149 void NeuralNetwork::AdaptWeights()
00150 {
00151 tNeuralArray::iterator previouslayer = (Layers.end() - 2);
00152 tNeuralArray::iterator currlayer = (Layers.end() - 1);
00153 double correction = 0.0;
00154 for (size_t i = 0; i < previouslayer->size(); ++i)
00155 previouslayer->at(i)->SetDelta(0.0);
00156 for (size_t j = 0; j < currlayer->size(); ++j)
00157 {
00158
00159 currlayer->at(j)->SetDelta(Layers.back().at(j)->CalcDeriv(
00160 Layers.back().at(j)->GetNet()) * (LocDesired.at(j)
00161 - LocOutput.at(j)));
00162
00163 for (size_t i = 0; i < currlayer->at(j)->GetWeights().size(); ++i)
00164 {
00165 currlayer->at(j)->GetInput().at(i)->SetDelta(
00166 currlayer->at(j)->GetInput().at(i)->GetDelta()
00167 + currlayer->at(j)->GetWeights().at(i) * currlayer->at(
00168 j)->GetDelta());
00169
00170 correction = alpha * currlayer->at(j)->GetOldDelta().at(i) + mu
00171 * (previouslayer->at(i)->GetLastOutput())
00172 * Layers.back().at(j)->GetDelta();
00173 currlayer->at(j)->SetWeights().at(i) += correction;
00174 currlayer->at(j)->SetOldDelta().at(i) = correction;
00175 }
00176 currlayer->at(j)->SetBias(Layers.back().at(j)->GetBias() + mu
00177 * Layers.back().at(j)->GetDelta());
00178 }
00179
00180 for (size_t i = Layers.size() - 2; i >= 1; --i)
00181 {
00182
00183 for (size_t j = 0; j < Layers.at(i - 1).size(); ++j)
00184 Layers.at(i - 1).at(j)->SetDelta(0.0);
00185
00186 for (tNeuralLayer::iterator currneuron = Layers.at(i).begin(); currneuron
00187 < Layers.at(i).end(); ++currneuron)
00188 {
00189
00190 currneuron->get()->SetDelta(currneuron->get()->GetDelta()
00191 * currneuron->get()->CalcDeriv(currneuron->get()->GetNet()));
00192
00193 for (size_t k = 0; k < currneuron->get()->GetWeights().size(); ++k)
00194 {
00195
00196 currneuron->get()->GetInput().at(k)->SetDelta(
00197 currneuron->get()->GetInput().at(k)->GetDelta()
00198 + currneuron->get()->GetWeights().at(k)
00199 * currneuron->get()->GetDelta());
00200
00201 correction
00202 = alpha * currneuron->get()->GetOldDelta().at(k)
00203 + mu
00204 * currneuron->get()->GetInput().at(k)->GetLastOutput()
00205 * currneuron->get()->GetDelta();
00206
00207 currneuron->get()->SetWeights().at(k) += correction;
00208
00209 currneuron->get()->SetOldDelta().at(k) = correction;
00210 }
00211
00212 currneuron->get()->SetBias(currneuron->get()->GetBias() + mu
00213 * currneuron->get()->GetDelta());
00214 }
00215 }
00216
00217 }
00218
00219 void NeuralNetwork::PrintWeights(ostream &output)
00220 {
00221 for (size_t i = 1; i < Layers.size(); ++i)
00222 {
00223 for (size_t j = 0; j < Layers.at(i).size(); ++j)
00224 {
00225 copy(Layers.at(i).at(j)->GetWeights().begin(), Layers.at(i).at(
00226 j)->GetWeights().end(), ostream_iterator<double> (output,
00227 " "));
00228 }
00229 }
00230 output << endl;
00231 }
00232
00233 void NeuralNetwork::PrintTopology(std::string filename)
00234 {
00235 gplib::rvec WeightVector = GetWeightsAsVector();
00236 const double maxpower = std::abs(*max_element(WeightVector.begin(),
00237 WeightVector.end(), gplib::absLess<double, double>()));
00238 std::ofstream output(filename.c_str());
00239 output << "digraph network {" << endl;
00240 for (size_t i = 0; i < Layers.front().size(); ++i)
00241 {
00242 output << "node [shape=point];" << std::endl;
00243 output << "i" << i << " -> input" << i << ";" << std::endl;
00244 output << "input" << i << " [shape=circle];" << std::endl;
00245 for (size_t j = 0; j < Layers.at(1).size(); ++j)
00246 {
00247 output << "input" << i << " -> n1" << j;
00248
00249 output << "[color =\" 0.7 1.0 " << 0.1 + std::abs(
00250 Layers.at(1).at(j)->GetWeights().at(i)) / maxpower
00251 << " \"]";
00252 output << ";" << std::endl;
00253 }
00254 }
00255 for (size_t i = 1; i < Layers.size() - 1; ++i)
00256 {
00257 output << "{ rank=same;" << std::endl;
00258 for (size_t j = 0; j < Layers.at(i).size(); ++j)
00259 {
00260 output << "n" << i << j << " [shape=circle];" << std::endl;
00261
00262
00263
00264
00265
00266 }
00267 output << "};" << std::endl;
00268 for (size_t j = 0; j < Layers.at(i).size(); ++j)
00269 for (size_t k = 0; k < Layers.at(i + 1).size(); ++k)
00270 {
00271 output << "n" << i << j << " -> n" << i + 1 << k;
00272
00273 output << "[color =\" 0.7 1.0 " << 0.1 + std::abs(
00274 Layers.at(i + 1).at(k)->GetWeights().at(j)) / maxpower
00275 << " \"]";
00276 output << ";" << std::endl;
00277 }
00278 }
00279 output << "{ rank=same;" << std::endl;
00280 for (size_t i = 0; i < Layers.back().size(); ++i)
00281 {
00282 output << "n" << Layers.size() - 1 << i << " [shape=circle];"
00283 << std::endl;
00284
00285
00286
00287
00288 }
00289 output << "};" << std::endl;
00290 for (size_t i = 0; i < Layers.back().size(); ++i)
00291 {
00292 output << "output" << i << " [shape=point];" << std::endl;
00293 for (size_t j = 0; j < Layers.at(Layers.size() - 1).size(); ++j)
00294 {
00295 output << "n" << Layers.size() - 1 << j << " -> output" << i
00296 << ";" << std::endl;
00297 }
00298 }
00299 output << "}";
00300 }
00301 }