mlp.h

00001 //-----------------------------------------------------------------------------
00002 // mlp.h
00003 //-----------------------------------------------------------------------------
00004 
00005 #ifndef mlp_h
00006 #define mlp_h
00007 
00008 #include <algorithm>              // generate
00009 #include <cmath>                  // exp
00010 #include <iostream>
00011 #include <iterator>
00012 #include <numeric>
00013 #include <stdexcept>              // invalid_argument
00014 #include <utility>
00015 #include <vector>
00016 #include <utils/eoRNG.h>          // eoRng
00017 #include <utils/rnd_generators.h> // normal_generator
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   // useful typedefs
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   // sigmoid
00064   //---------------------------------------------------------------------------
00065 
00066   real sigmoid(const real& x)
00067   {
00068     return 1.0 / (1.0 + exp(-x));
00069   }
00070 
00071 
00072   //---------------------------------------------------------------------------
00073   // neuron
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   // layer
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   // net
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         // skip forward to pass up opening '<' char
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         // Save the number of inputs, number of outputs, and number of hidden layers
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   // sample
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   // set
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   // euclidean_distance
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       #include <fstream>
00440       std::ofstream file("dist.stat", ios::app);
00441       file << sqrt(sum) << endl;
00442     */
00443     return sqrt(sum);
00444   }
00445 
00446   //---------------------------------------------------------------------------
00447 
00448 } // namespace mlp
00449 
00450 
00451 
00452 #endif // mlp_h
00453 
00454 
00455 // Local Variables:
00456 // mode:C++
00457 // c-file-style: "Stroustrup"
00458 // End:

Generated on Thu Oct 19 05:06:41 2006 for EO by  doxygen 1.3.9.1