Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/GaussianClassifier.cpp
Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 1998-2006 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 ** 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 #include "GaussianClassifier.h"
00020 #include "../common_source.h"
00021 
00022 using std::ostringstream;
00023 using namespace Marsyas;
00024 
00025 GaussianClassifier::GaussianClassifier(mrs_string name):MarSystem("GaussianClassifier",name)
00026 {
00027   prev_mode_= "predict";
00028   addControls();
00029 }
00030 
00031 
00032 GaussianClassifier::GaussianClassifier(const GaussianClassifier& a):MarSystem(a)
00033 {
00034   ctrl_mode_ = getctrl("mrs_string/mode");
00035   ctrl_nClasses_ = getctrl("mrs_natural/nClasses");
00036   ctrl_means_ = getctrl("mrs_realvec/means");
00037   ctrl_covars_ = getctrl("mrs_realvec/covars");
00038   prev_mode_ = "predict";
00039 }
00040 
00041 
00042 GaussianClassifier::~GaussianClassifier()
00043 {
00044 }
00045 
00046 
00047 MarSystem*
00048 GaussianClassifier::clone() const
00049 {
00050   return new GaussianClassifier(*this);
00051 }
00052 
00053 void
00054 GaussianClassifier::addControls()
00055 {
00056   addctrl("mrs_string/mode", "train", ctrl_mode_);
00057   setctrlState("mrs_string/mode", true);
00058 
00059   addctrl("mrs_natural/nClasses", 1, ctrl_nClasses_);
00060   setctrlState("mrs_natural/nClasses", true);
00061   addctrl("mrs_realvec/means", realvec(), ctrl_means_);
00062   addctrl("mrs_realvec/covars", realvec(), ctrl_covars_);
00063 }
00064 
00065 
00066 void
00067 GaussianClassifier::myUpdate(MarControlPtr sender)
00068 {
00069   mrs_natural o;
00070   (void) sender;  //suppress warning of unused parameter(s)
00071   MRSDIAG("GaussianClassifier.cpp - GaussianClassifier:myUpdate");
00072 
00073   setctrl("mrs_natural/onSamples", getctrl("mrs_natural/inSamples"));
00074   setctrl("mrs_natural/onObservations", (mrs_natural)3);
00075   setctrl("mrs_real/osrate", getctrl("mrs_real/israte"));
00076 
00077   mrs_natural nClasses = getctrl("mrs_natural/nClasses")->to<mrs_natural>();
00078 
00079   setctrl("mrs_natural/onObservations", (mrs_natural)2 + nClasses);
00080 
00081   mrs_natural mrows = (getctrl("mrs_realvec/means")->to<mrs_realvec>()).getRows();
00082   mrs_natural mcols = (getctrl("mrs_realvec/means")->to<mrs_realvec>()).getCols();
00083   mrs_string mode = getctrl("mrs_string/mode")->to<mrs_string>();
00084 
00085   if (active_) {
00086     // Don't bother resetting anything if this system is inactive.
00087     // This allows us to load an entire .mpl file without incorrectly
00088     // resetting the means and covars a bunch of times.
00089 
00090     if ((nClasses != mrows) || (inObservations_ != mcols))
00091     {
00092       MarControlAccessor acc_means(ctrl_means_);
00093       MarControlAccessor acc_covars(ctrl_covars_);
00094 
00095       realvec& means = acc_means.to<mrs_realvec>();
00096       realvec& covars = acc_covars.to<mrs_realvec>();
00097 
00098       means.create(nClasses, inObservations_);
00099       covars.create(nClasses, inObservations_);
00100       labelSizes_.create(nClasses);
00101     }
00102 
00103     if ((prev_mode_ == "train") && (mode == "predict"))
00104     {
00105 
00106       MarControlAccessor acc_means(ctrl_means_);
00107       MarControlAccessor acc_covars(ctrl_covars_);
00108 
00109       realvec& means = acc_means.to<mrs_realvec>();
00110       realvec& covars = acc_covars.to<mrs_realvec>();
00111 
00112 
00113       for (int l=0; l < nClasses; l++)
00114       {
00115         for (o=0; o < inObservations_; o++)
00116         {
00117           means(l,o) = means(l,o) / labelSizes_(l);
00118           covars(l,o) = covars(l,o) / labelSizes_(l);
00119           covars(l, o) = covars(l,o) - (means(l,o) * means(l,o));
00120           if (covars(l,o) != 0.0)
00121           {
00122             covars(l,o) = (mrs_real)(1.0 / covars(l,o));
00123           }
00124         }
00125       }
00126       prev_mode_ = mode;
00127     }
00128   }
00129 }
00130 
00131 void
00132 GaussianClassifier::myProcess(realvec& in, realvec& out)
00133 {
00134   mrs_natural o,t;
00135   mrs_real v;
00136   mrs_string mode = ctrl_mode_->to<mrs_string>();
00137   mrs_natural nClasses = ctrl_nClasses_->to<mrs_natural>();
00138 
00139   mrs_natural l;
00140   mrs_natural prediction = 0;
00141   mrs_real label;
00142 
00143   mrs_real diff;
00144   mrs_real sq_sum=0.0;
00145 
00146   MarControlAccessor acc_means(ctrl_means_);
00147   MarControlAccessor acc_covars(ctrl_covars_);
00148   realvec& means = acc_means.to<mrs_realvec>();
00149   realvec& covars = acc_covars.to<mrs_realvec>();
00150 
00151 
00152 
00153   // reset
00154   if ((prev_mode_ == "predict") && (mode == "train"))
00155   {
00156     means.setval(0.0);
00157     covars.setval(0.0);
00158     labelSizes_.setval(0.0);
00159   }
00160 
00161   if (mode == "train")
00162   {
00163     for (t = 0; t < inSamples_; t++)
00164     {
00165       label = in(inObservations_-1, t);
00166       if(label>=0) //unlabeled data (i.e. label = -1) should be ignored
00167       {
00168         for (o=0; o < inObservations_-1; o++)
00169         {
00170           v = in(o,t);
00171           means((mrs_natural)label,o) = means((mrs_natural)label,o) + v;
00172           covars((mrs_natural)label,o) = covars((mrs_natural)label,o) + v*v;
00173           out(0,t) = (mrs_real)label;
00174           out(1,t) = (mrs_real)label;
00175           for (int j=0; j < nClasses; j++)
00176           {
00177             out(j,t) = (mrs_real)0;
00178             if (j == label)
00179               out(j,t) = (mrs_real)1;
00180           }
00181         }
00182         labelSizes_((mrs_natural)label) = labelSizes_((mrs_natural)label) + 1;
00183       }
00184     }
00185   }
00186 
00187   if (mode == "predict")
00188   {
00189 
00190     mrs_real min = MAXREAL;
00191 
00192     for (t = 0; t < inSamples_; t++)
00193     {
00194       label = in(inObservations_-1, t);
00195 
00196       for (l=0; l < nClasses; l++)
00197       {
00198         sq_sum = 0.0;
00199 
00200         for (o=0; o < inObservations_-1; o++)
00201         {
00202           v = in(o,t);
00203           diff = (v - means(l,o));
00204           sq_sum += (diff * covars(l,o) * diff);
00205         }
00206 
00207         if (sq_sum < min)
00208         {
00209           min = sq_sum;
00210           prediction = l;
00211         }
00212 
00213         // output the distances in the probability slots
00214         out (2+l, t) = sq_sum;
00215       }
00216       out(0,t) = (mrs_real)prediction;
00217       out(1,t) = (mrs_real)label;
00218     }
00219   }
00220 
00221   prev_mode_ = mode;
00222 }