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