Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/SOM.cpp
Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 1998-2008 George Tzanetakis <gtzan@cs.uvic.ca>
00003 **
00004 ** This program is free software; you can redistribute it and/or modify
00005 ** it under the terms of the GNU General Public License as published by
00006 ** the Free Software Foundation; either version 2 of the License, or
00007 ** (at your option) any later version.
00008 **
00009 ** This program is distributed in the hope that it will be useful,
00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 3** GNU General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU General Public License
00015 ** along with this program; if not, write to the Free Software
00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 */
00018 
00019 
00020 #include "SOM.h"
00021 #include "../common_source.h"
00022 
00023 using namespace std;
00024 using namespace Marsyas;
00025 
00026 
00027 
00028 #define ALPHA_DEGRADE       0.98
00029 #define NEIGHBOURHOOD_DEGRADE   0.97
00030 
00031 SOM::SOM(mrs_string name):MarSystem("SOM",name)
00032 {
00033   //type_ = "SOM";
00034   //name_ = name;
00035 
00036   addControls();
00037 }
00038 
00039 
00040 SOM::~SOM()
00041 {
00042 }
00043 
00044 
00045 
00046 SOM::SOM(const SOM& a) : MarSystem(a)
00047 {
00048   ctrl_gridmap_ = getctrl("mrs_realvec/grid_map");
00049 }
00050 
00051 
00052 MarSystem*
00053 SOM::clone() const
00054 {
00055   return new SOM(*this);
00056 }
00057 
00058 void
00059 SOM::addControls()
00060 {
00061   addctrl("mrs_string/mode", "train");
00062   addctrl("mrs_natural/nLabels", 1);    // number of feature vectors
00063   setctrlState("mrs_natural/nLabels", true);
00064   addctrl("mrs_natural/grid_width",  10);
00065   setctrlState("mrs_natural/grid_width", true);
00066   addctrl("mrs_natural/grid_height", 10);
00067   setctrlState("mrs_natural/grid_height", true);
00068 
00069   addctrl("mrs_realvec/grid_map", realvec(), ctrl_gridmap_);
00070 
00071   addctrl("mrs_bool/done", false);
00072   setctrlState("mrs_bool/done", true);
00073 
00074   addctrl("mrs_real/alpha", 1.0);
00075   setctrlState("mrs_real/alpha", true);
00076 
00077   addctrl("mrs_real/neigh_std", 1.0);
00078   setctrlState("mrs_real/neigh_std", true);
00079 
00080   addctrl("mrs_real/alpha_decay_init", ALPHA_DEGRADE);
00081   setctrlState("mrs_real/alpha_decay_init", true);
00082 
00083   addctrl("mrs_real/alpha_decay_train", ALPHA_DEGRADE);
00084   setctrlState("mrs_real/alpha_decay_train", true);
00085 
00086   addctrl("mrs_real/neighbourhood_decay_init", NEIGHBOURHOOD_DEGRADE);
00087   setctrlState("mrs_real/neighbourhood_decay_init", true);
00088 
00089   addctrl("mrs_real/neighbourhood_decay_train", NEIGHBOURHOOD_DEGRADE);
00090   setctrlState("mrs_real/neighbourhood_decay_train", true);
00091 
00092   addctrl("mrs_real/std_factor_train", 0.17);
00093   setctrlState("mrs_real/std_factor_train", true);
00094 
00095   addctrl("mrs_real/std_factor_init", 0.17);
00096   setctrlState("mrs_real/std_factor_init", true);
00097 }
00098 
00099 
00100 void
00101 SOM::init_grid_map()
00102 {
00103   //cout << "randomizing***********" << endl;
00104   MarControlAccessor acc_grid(ctrl_gridmap_);
00105   realvec& grid_map = acc_grid.to<mrs_realvec>();
00106   srand(0);
00107 
00108   for (int x=0; x < grid_width_; x++)
00109     for (int y=0; y < grid_height_; y++)
00110       for (int o=0; o < inObservations_ - 3; o++)
00111       {
00112         grid_map(x * grid_height_ + y, o) = randD(1.0);
00113       }
00114 
00115   alpha_ = getctrl("mrs_real/alpha")->to<mrs_real>();
00116   mrs_real std_ = getctrl("mrs_real/std_factor_train")->to<mrs_real>();
00117   neigh_std_ = ((0.5*(grid_width_+grid_height_)) * std_);
00118 
00119 
00120 
00121 }
00122 
00123 
00124 double
00125 SOM::gaussian(double x, double mean, double std, bool scale)
00126 {
00127   if( scale )
00128     return (1.0/(std*sqrt(2.0*PI))) * exp( -(x-mean)*(x-mean)/(2.0*std*std) );
00129 
00130   return exp( -(x-mean)*(x-mean)/(2.0*std*std) );
00131 }
00132 
00133 double
00134 SOM::randD(double max)
00135 {
00136   return max  *  (double)rand() / ((double)(RAND_MAX)+(double)(1.0)) ;
00137 }
00138 
00139 void
00140 SOM::myUpdate(MarControlPtr sender)
00141 {
00142   //cout<<"SOM myUpdate*************"<<endl;
00143   (void) sender;  //suppress warning of unused parameter(s)
00144   MRSDIAG("SOM.cpp - SOM:myUpdate");
00145 
00146   setctrl("mrs_natural/onSamples", getctrl("mrs_natural/inSamples"));
00147   setctrl("mrs_natural/onObservations", (mrs_natural)3);
00148   setctrl("mrs_real/osrate", getctrl("mrs_real/israte"));
00149 
00150   grid_pos_.create(2);
00151 
00152   //defaultUpdate();[!]
00153   inObservations_ = getctrl("mrs_natural/inObservations")->to<mrs_natural>();
00154 
00155   // FIXME This variable is defined but (possibly) unused.
00156   // mrs_natural nlabels = getctrl("mrs_natural/nLabels")->to<mrs_natural>();
00157 
00158   grid_width_ = getctrl("mrs_natural/grid_width")->to<mrs_natural>();
00159   grid_height_ = getctrl("mrs_natural/grid_height")->to<mrs_natural>();
00160 
00161   mrs_natural grid_size = grid_width_ * grid_height_;
00162 
00163   mrs_natural mrows = (getctrl("mrs_realvec/grid_map")->to<mrs_realvec>()).getRows();
00164   mrs_natural mcols = (getctrl("mrs_realvec/grid_map")->to<mrs_realvec>()).getCols();
00165 
00166   mrs_string mode = getctrl("mrs_string/mode")->to<mrs_string>();
00167 
00168   if ((grid_size != mrows) ||
00169       (inObservations_-3 != mcols))
00170   {
00171     if (inObservations_ != 1)
00172     {
00173       MarControlAccessor acc_grid(ctrl_gridmap_);
00174       realvec& grid_map = acc_grid.to<mrs_realvec>();
00175       grid_map.create(grid_size, inObservations_-3);
00176       adjustments_.create(inObservations_-3);
00177 
00178       init_grid_map();
00179     }
00180 
00181   }
00182 }
00183 
00184 void
00185 SOM::find_grid_location(realvec& in, int t)
00186 {
00187   mrs_natural o;
00188   //  int temp;
00189   mrs_real ival;                // input value
00190   mrs_real pval;                // prototype value
00191   mrs_real minDist = MAXREAL;
00192 
00193   MarControlAccessor acc_grid(ctrl_gridmap_);
00194   realvec& grid_map = acc_grid.to<mrs_realvec>();
00195 
00196   for (int x=0; x < grid_width_; x++)
00197     for (int y=0; y < grid_height_; y++)
00198     {
00199       // for each point in the grid
00200       // calculate distance of
00201       // input feature vector to the
00202       // representatitve vector of that position
00203 
00204       mrs_real dist = 0.0;
00205 
00206       for (o=0; o < inObservations_-3; o++)
00207       {
00208         ival = in(o,t);
00209         pval = grid_map(x * grid_height_ + y, o);
00210         dist += (ival - pval) * (ival - pval);
00211         //cout << "dist:" << dist << " ival: " << ival << " pval " << pval <<  " x: " << x << " y: " << y << endl;
00212       }
00213 
00214       if (dist < minDist)
00215       {
00216         minDist = dist;
00217         grid_pos_(0) = x;
00218         grid_pos_(1) = y;
00219       }
00220     }
00221 
00222 
00223 
00224 
00225 }
00226 
00227 
00228 
00229 void
00230 SOM::myProcess(realvec& in, realvec& out)
00231 {
00232   mrs_string mode = getctrl("mrs_string/mode")->to<mrs_string>();
00233 
00234   mrs_natural o,t;
00235   mrs_real geom_dist;
00236   mrs_real geom_dist_gauss;
00237 
00238   int px;
00239   int py;
00240 
00241   MarControlAccessor acc_grid(ctrl_gridmap_);
00242   realvec& grid_map = acc_grid.to<mrs_realvec>();
00243 
00244 
00245   if (mode == "train")
00246   {
00247 
00248     mrs_real dx;
00249     mrs_real dy;
00250     mrs_real adj;
00251 
00252     for (t=0; t < inSamples_; t++)
00253     {
00254 
00255 
00256       px = (int) in(inObservations_-2, t);
00257       py = (int) in(inObservations_-1, t);
00258 
00259 
00260 
00261       if ((px == -1.0)&&(px == -1.0))
00262       {
00263         find_grid_location(in, t);
00264         px = (int) grid_pos_(0);
00265         py = (int) grid_pos_(1);
00266       }
00267       out(0,t) = px;
00268       out(1,t) = py;
00269       out(2,t) = in(inObservations_-3,t);
00270 
00271       for (int x=0; x < grid_width_; x++)
00272         for (int y=0; y < grid_height_; y++)
00273         {
00274           dx = px-x;
00275           dy = py-y;
00276           geom_dist = sqrt((double)(dx*dx + dy*dy));
00277           geom_dist_gauss = gaussian( geom_dist, 0.0, neigh_std_, false);
00278 
00279           // subtract map vector from training data vector
00280           adj = alpha_ * geom_dist_gauss;
00281           for (o=0; o < inObservations_-3; o++)
00282           {
00283             adjustments_(o) = in(o,t) - grid_map(x * grid_height_ + y, o);
00284             adjustments_(o) *= adj;
00285             grid_map(x * grid_height_ + y, o) += adjustments_(o);
00286           }
00287         }
00288     }
00289 
00290     alpha_ *= getctrl("mrs_real/alpha_decay_train")->to<mrs_real>();
00291     neigh_std_ *= getctrl("mrs_real/neighbourhood_decay_train")->to<mrs_real>();
00292 
00293 
00294 
00295   }
00296   if (mode == "init")
00297   {
00298     mrs_real dx;
00299     mrs_real dy;
00300     mrs_real adj;
00301 
00302     mrs_real std_ = getctrl("mrs_real/std_factor_init")->to<mrs_real>();
00303     neigh_std_ = ((0.5*(grid_width_+grid_height_)) * std_);
00304 
00305     for (t=0; t < inSamples_; t++)
00306     {
00307       // no need to find grid locations, just read from the file
00308       px = (int) in( in.getRows() - 2, t);
00309       py = (int) in( in.getRows() - 1, t);
00310       for(int i =0; i < inObservations_ - 3; ++i)
00311       {
00312         grid_map(px * grid_height_ + py, i) = in(i);
00313       }
00314 
00315       for (int x=0; x < grid_width_; x++)
00316         for (int y=0; y < grid_height_; y++)
00317         {
00318           dx = px-x;
00319           dy = py-y;
00320           geom_dist = sqrt((double)(dx*dx + dy*dy));
00321           geom_dist_gauss = gaussian( geom_dist, 0.0, neigh_std_, false);
00322 
00323           // subtract map vector from training data vector
00324           adj = alpha_ * geom_dist_gauss;
00325           for (o=0; o < inObservations_-3; o++)
00326           {
00327             adjustments_(o) = in(o,t) - grid_map(x * grid_height_ + y, o);
00328             adjustments_(o) *= adj;
00329             grid_map(x * grid_height_ + y, o) += adjustments_(o);
00330           }
00331 
00332         }
00333 
00334 
00335     }
00336     //WARNING: UGLY HACK
00337     // Last two rows of init features are x,y locations
00338     // so we want to set all the coresponding rows in the SOM to 0
00339     // to prevent randomness from creaping in.
00340     for (int x=0; x < grid_width_; x++)
00341     {
00342       for (int y=0; y < grid_height_; y++)
00343       {
00344         grid_map(x * grid_height_ + y, grid_map.getCols() - 2) = 0;
00345         grid_map(x * grid_height_ + y, grid_map.getCols() - 1) = 0;
00346         cout << "x: " << x << " y: " << y << endl;
00347       }
00348     }
00349     alpha_ *= getctrl("mrs_real/alpha_decay_init")->to<mrs_real>();
00350     neigh_std_ *= getctrl("mrs_real/neighbourhood_decay_init")->to<mrs_real>();
00351 
00352   }
00353   if (mode == "predict")
00354   {
00355     for (t=0; t < inSamples_; t++)
00356     {
00357       find_grid_location(in, t);
00358       px = (int) grid_pos_(0);
00359       py = (int) grid_pos_(1);
00360 
00361 
00362 
00363       out(0,t) = px;
00364       out(1,t) = py;
00365       out(2,t) = in(inObservations_-3,t);
00366     }
00367   }
00368 
00369 
00370 
00371 
00372 
00373 }
00374 
00375 
00376 
00377 
00378 
00379 
00380 
00381 
00382 
00383 
00384 
00385