Marsyas
0.6.0-alpha
|
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