00001
00002
00003
00004
00005 #ifndef mlp_h
00006 #define mlp_h
00007
00008 #include <algorithm>
00009 #include <cmath>
00010 #include <iostream>
00011 #include <iterator>
00012 #include <numeric>
00013 #include <stdexcept>
00014 #include <utility>
00015 #include <vector>
00016 #include <utils/eoRNG.h>
00017 #include <utils/rnd_generators.h>
00018 #include <vecop.h>
00019
00020
00021
00022 namespace mlp
00023 {
00024 using namespace std;
00025
00026 typedef double real;
00027 typedef std::vector<real> vector;
00028 }
00029
00030
00031 namespace std {
00032 ostream& operator<<(ostream& os, const mlp::vector& v)
00033 {
00034 ostream_iterator<mlp::real> oi(os, " ");
00035 copy(v.begin(), v.end(), oi);
00036 return os;
00037 }
00038
00039 istream& operator>>(istream& is, mlp::vector& v)
00040 {
00041 for (mlp::vector::iterator vi = v.begin() ; vi != v.end() ; vi++) {
00042 is >> *vi;
00043 }
00044 return is;
00045 }
00046 }
00047
00048 namespace mlp
00049 {
00050 using namespace std;
00051
00052
00053
00054
00055
00056
00057 const real max_real = std::numeric_limits<real>::max();
00058 const real min_real = std::numeric_limits<real>::min();
00059
00060
00061
00062
00063
00064
00065 real sigmoid(const real& x)
00066 {
00067 return 1.0 / (1.0 + exp(-x));
00068 }
00069
00070
00071
00072
00073
00074
00075 struct neuron
00076 {
00077 real bias;
00078 vector weight;
00079
00080 neuron(const unsigned& num_inputs = 0): weight(num_inputs) {}
00081
00082 void reset()
00083 {
00084 normal_generator<real> rnd(1.0);
00085 bias = rnd();
00086 generate(weight.begin(), weight.end(), rnd);
00087 }
00088
00089 real operator()(const vector& input) const
00090 {
00091 return sigmoid(bias + weight * input);
00092 }
00093
00094 unsigned length() const { return weight.size() + 1; }
00095
00096 void normalize()
00097 {
00098 real n = sqrt(bias * bias + weight * weight);
00099 bias /= n;
00100 weight /= n;
00101 }
00102
00103 void desaturate()
00104 {
00105 bias = -5.0 + 10.0 / (1.0 + exp(bias / -5.0));
00106
00107 for (vector::iterator w = weight.begin(); w != weight.end(); ++w)
00108 *w = -5.0 + 10.0 / (1.0 + exp(*w / -5.0));
00109 }
00110
00111 void perturb_num(double &num, double magnitude) {
00112 double scale = max(num, 0.05) * magnitude;
00113 double perturbation = scale * (rng.uniform() - 0.5);
00114 num += perturbation;
00115 }
00116
00117 void perturb(double magnitude = 0.3, double probability = 1.0)
00118 {
00119
00120 for (vector::iterator w = weight.begin(); w != weight.end(); ++w)
00121 if ( probability >= 1.0 || rng.uniform() < probability)
00122 perturb_num(*w, magnitude);
00123 if ( probability >= 1.0 || rng.uniform() < probability)
00124 perturb_num(bias, magnitude);
00125 }
00126 };
00127 }
00128
00129 namespace std {
00130
00131 ostream& operator<<(ostream& os, const mlp::neuron& n)
00132 {
00133 return os << n.bias << " " << n.weight;
00134 }
00135
00136 istream& operator>>(istream& is, mlp::neuron& n)
00137 {
00138 return is >> n.bias >> n.weight;
00139 }
00140
00141 }
00142
00143 namespace mlp {
00144
00145
00146
00147
00148
00149 class layer: public std::vector<neuron>
00150 {
00151 public:
00152 layer(const unsigned& num_inputs = 0, const unsigned& num_neurons = 0):
00153 std::vector<neuron>(num_neurons, neuron(num_inputs)) {}
00154
00155 void reset()
00156 {
00157 normal_generator<real> rnd(1.0);
00158 for(iterator n = begin(); n != end(); ++n)
00159 n->reset();
00160 }
00161
00162 vector operator()(const vector& input) const
00163 {
00164 vector output(size());
00165
00166 for(unsigned i = 0; i < output.size(); ++i)
00167 output[i] = (*this)[i](input);
00168
00169 return output;
00170 }
00171
00172 unsigned length() const { return front().length() * size(); }
00173
00174 void normalize()
00175 {
00176 for(iterator n = begin(); n != end(); ++n)
00177 n->normalize();
00178 }
00179
00180 void desaturate()
00181 {
00182 for(iterator n = begin(); n != end(); ++n)
00183 n->desaturate();
00184 }
00185
00186 void perturb(double magnitude = 0.3, double probability = 1.0)
00187 {
00188 for(iterator n = begin(); n != end(); ++n)
00189 n->perturb();
00190 }
00191
00192 };
00193
00194 }
00195
00196 namespace std {
00197
00198 ostream& operator<<(ostream& os, const mlp::layer& l)
00199 {
00200 ostream_iterator<mlp::neuron> oi(os, " ");
00201 copy(l.begin(), l.end(), oi);
00202 return os;
00203 }
00204
00205 istream& operator>>(istream& is, mlp::layer& l)
00206 {
00207 for (mlp::layer::iterator li = l.begin() ; li != l.end() ; li++) {
00208 is >> *li;
00209 }
00210 return is;
00211 }
00212
00213 }
00214
00215 namespace mlp {
00216
00217
00218
00219
00220
00221
00222 class net: public std::vector<layer>
00223 {
00224 public:
00225 net(const unsigned& num_inputs = 0,
00226 const unsigned& num_outputs = 0,
00227 const std::vector<unsigned>& hidden = std::vector<unsigned>())
00228 {
00229 init(num_inputs,num_outputs,hidden);
00230 }
00231
00232
00233 net(istream &is) {
00234 load(is);
00235 }
00236
00238 virtual ~net() {};
00239
00240 void load(istream &is) {
00241 unsigned num_inputs;
00242 unsigned num_outputs;
00243 unsigned num_hidden_layers;
00244
00245 is >> num_inputs >> num_outputs >> num_hidden_layers;
00246
00247 std::vector<unsigned> layer_sizes;
00248 for (unsigned i=0; i<num_hidden_layers;i++) {
00249 unsigned layer_size;
00250 is >> layer_size;
00251 layer_sizes.push_back(layer_size);
00252 }
00253 unsigned check_outputs;
00254 is >> check_outputs;
00255 assert (check_outputs == num_outputs);
00256 init (num_inputs,num_outputs,layer_sizes);
00257
00258 char c=' ';
00259 while (c!='<' && !is.eof()) { is >> c;}
00260 for (iterator l =begin() ; l != end(); l++) {
00261 is >> *l;
00262 }
00263 do { is >> c; } while (c == ' ' && !is.eof());
00264 assert(c == '>');
00265 }
00266
00267 void init( unsigned num_inputs,
00268 unsigned num_outputs,
00269 const std::vector<unsigned>& hidden ) {
00270 clear();
00271 switch(hidden.size())
00272 {
00273 case 0:
00274 push_back(layer(num_inputs, num_outputs));
00275 break;
00276 default:
00277 push_back(layer(num_inputs, hidden.front()));
00278 for (unsigned i = 0; i < hidden.size() - 1; ++i)
00279 push_back(layer(hidden[i], hidden[i + 1]));
00280 push_back(layer(hidden.back(), num_outputs));
00281 break;
00282 }
00283 }
00284
00285 void reset()
00286 {
00287 normal_generator<real> rnd(1.0);
00288 for(iterator l = begin(); l != end(); ++l)
00289 l->reset();
00290 }
00291
00292 virtual vector operator()(const vector& input) const ;
00293
00294 unsigned winner(const vector& input) const
00295 {
00296 vector tmp = (*this)(input);
00297 return (max_element(tmp.begin(), tmp.end()) - tmp.begin());
00298 }
00299
00300 void save(ostream &os) const {
00301
00302 os << num_inputs() << "\n" << num_outputs() << "\n" << num_hidden_layers() << "\n";
00303 for(const_iterator l = begin(); l != end(); ++l)
00304 os << l->size() << " ";
00305 os << "\n";
00306 os << *this;
00307 os << "\n";
00308 }
00309
00310 unsigned num_inputs() const { return front().front().length() - 1; }
00311 unsigned num_outputs() const { return back().size(); }
00312 unsigned num_hidden_layers() const {
00313 signed s = (signed) size() -1;
00314 return (s<0) ? 0 : s ;
00315 }
00316
00317
00318 unsigned length()
00319 {
00320 unsigned sum = 0;
00321
00322 for(iterator l = begin(); l != end(); ++l)
00323 sum += l->length();
00324
00325 return sum;
00326 }
00327
00328 void normalize()
00329 {
00330 for(iterator l = begin(); l != end(); ++l)
00331 l->normalize();
00332 }
00333
00334 void desaturate()
00335 {
00336 for(iterator l = begin(); l != end(); ++l)
00337 l->desaturate();
00338 }
00339
00340 void perturb(double magnitude = 0.3, double probability = 1.0)
00341 {
00342 for(iterator l = begin(); l != end(); ++l)
00343 l->perturb();
00344 }
00345 };
00346
00347 #ifndef NO_MLP_VIRTUALS
00348 vector net::operator()(const vector& input) const
00349 {
00350 vector tmp = input;
00351
00352 for(const_iterator l = begin(); l != end(); ++l)
00353 tmp = (*l)(tmp);
00354
00355 return tmp;
00356 }
00357 #endif
00358
00359
00360
00361
00362
00363
00364 struct sample
00365 {
00366 vector input, output;
00367
00368 sample(unsigned input_size = 0, unsigned output_size = 0):
00369 input(input_size), output(output_size) {}
00370 };
00371
00372 istream& operator>>(istream& is, sample& s)
00373 {
00374 return is >> s.input >> s.output;
00375 }
00376
00377 ostream& operator<<(ostream& os, const sample& s)
00378 {
00379 return os << s.input << " " << s.output;
00380 }
00381
00382
00383
00384
00385
00386
00387 class set: public std::vector<sample>
00388 {
00389 public:
00390 set(unsigned input_size = 0, unsigned output_size = 0,
00391 unsigned num_samples = 0):
00392 std::vector<sample>(num_samples, sample(input_size, output_size)) {}
00393
00394 set(istream& is) : std::vector<sample>(0, sample(0, 0)) {
00395 clear();
00396 load(is);
00397 }
00398
00399 void load(istream &is) {
00400 unsigned input_size, output_size;
00401 is >> input_size >> output_size;
00402 sample samp(input_size, output_size);;
00403 while (is >> samp) { push_back(samp); }
00404 }
00405
00406 void save(ostream &os) const {
00407 os << front().input.size() << " " << front().output.size() << endl;
00408 copy(begin(), end(), ostream_iterator<sample>(os,"\n"));
00409 }
00410 };
00411
00412 ostream& operator<<(ostream& os, const set& s)
00413 {
00414 os << "<" << endl;
00415 for (unsigned i = 0; i < s.size(); ++i)
00416 os << s[i] << endl;
00417 return os << ">";
00418 }
00419
00420
00421
00422
00423
00424 real euclidean_distance(const net& n1, const net& n2)
00425 {
00426 real sum = 0;
00427
00428 for(net::const_reverse_iterator l1 = n1.rbegin(), l2 = n2.rbegin();
00429 l1 != n1.rend() && l2 != n2.rend(); ++l1, ++l2)
00430 for(layer::const_iterator n1 = l1->begin(), n2 = l2->begin();
00431 n1 != l1->end() && n2 != l2->end(); ++n1, ++n2)
00432 {
00433 real b = n1->bias - n2->bias;
00434 vector w = n1->weight - n2->weight;
00435 sum += b * b + w * w;
00436 }
00437
00438
00439
00440
00441
00442 return sqrt(sum);
00443 }
00444
00445
00446
00447 }
00448
00449
00450
00451 #endif // mlp_h
00452
00453
00454
00455
00456
00457