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