ECOCPAK v0.9
|
00001 // Copyright (C) 2011 the authors listed below 00002 // http://ecocpak.sourceforge.net 00003 // 00004 // Authors: 00005 // - Dimitrios Bouzas (bouzas at ieee dot org) 00006 // - Nikolaos Arvanitopoulos (niarvani at ieee dot org) 00007 // - Anastasios Tefas (tefas at aiia dot csd dot auth dot gr) 00008 // 00009 // This file is part of the ECOC PAK C++ library. It is 00010 // provided without any warranty of fitness for any purpose. 00011 // 00012 // You can redistribute this file and/or modify it under 00013 // the terms of the GNU Lesser General Public License (LGPL) 00014 // as published by the Free Software Foundation, either 00015 // version 3 of the License or (at your option) any later 00016 // version. 00017 // (see http://www.opensource.org/licenses for more info) 00018 00019 00022 00023 00024 00050 u32 00051 one_vs_all 00052 ( 00053 const mat& training_samples, 00054 const icolvec& training_labels, 00055 const mat& testing_samples, 00056 const icolvec& testing_labels, 00057 const int decoding_strategy, 00058 const int classifiers_type, 00059 const bool verbose, 00060 ofstream& verbose_output, 00061 double& execution_time 00062 ) 00063 { 00064 // timer object to count execution times 00065 wall_clock timer; 00066 00067 // start timer 00068 timer.tic(); 00069 00070 // number of training samples 00071 const u32 n_training_samples = training_samples.n_rows; 00072 00073 // number of samples attributes 00074 const u32 n_attributes = training_samples.n_cols; 00075 00076 // number of testing samples 00077 const u32 n_testing_samples = testing_samples.n_rows; 00078 00079 // variable to hold the number of classes 00080 u32 n_classes = 0; 00081 00082 // adjust the training samples class labels to start from one 00083 // and count number of classes 00084 const ucolvec tmp_training_labels = process_labels 00085 ( 00086 training_labels, 00087 n_classes 00088 ); 00089 00090 // adjust the testing samples class labels to start from one 00091 const ucolvec tmp_testing_labels = process_labels 00092 ( 00093 testing_labels 00094 ); 00095 00096 // decompose the training samples matrix into ClassData object 00097 vector<ClassData> classes_vector = 00098 create_class_vector 00099 ( 00100 training_samples, 00101 conv_to<icolvec>::from(tmp_training_labels) 00102 ); 00103 00104 // allocate error correcting output codes matrix 00105 imat coding_matrix = -ones<imat>(n_classes, n_classes); 00106 00107 // classifiers vector 00108 vector<Classifier*> classifiers_vector; 00109 00110 // ================================================================ // 00111 // || Training Step || // 00112 // ================================================================ // 00113 00114 // auxuliary column counter 00115 u32 k = 0; 00116 00117 // iterate through number of classes 00118 for(u32 i = 0; i < n_classes; i++) 00119 { 00120 // negative classes data matrix 00121 mat X_neg; 00122 00123 // negative classes vector 00124 vector<ClassData*> neg_classes; 00125 00126 // number of negative examples 00127 u32 n_neg = 0; 00128 00129 // iterate through classes to construct X_neg 00130 for(u32 j = 0; j < n_classes; j++) 00131 { 00132 // if class is considered negative 00133 if(j != i) 00134 { 00135 // append samples of current class to the of X_neg 00136 X_neg = join_cols(X_neg, classes_vector[j].Data()); 00137 00138 // store pointer to current class to temporary vector 00139 neg_classes.push_back(&(classes_vector[j])); 00140 00141 // increase negative samples temporary counter 00142 n_neg += classes_vector[j].Samples(); 00143 } 00144 00145 } 00146 00147 // create and store specific classifier 00148 switch(classifiers_type) 00149 { 00150 // Nearest Class Centroid Classifier 00151 case NCC: 00152 { 00153 Classifier_ncc* tmp = new Classifier_ncc 00154 ( 00155 classes_vector[i].Data(), 00156 X_neg 00157 ); 00158 00159 // update classifier's possitive class pointer 00160 tmp->pos.push_back(&(classes_vector[i])); 00161 00162 // update classifier's negative classes 00163 tmp->neg = neg_classes; 00164 00165 // update classifier's number of possitive samples 00166 tmp->n_pos = classes_vector[i].Samples(); 00167 00168 // update classifier's number of negative samples 00169 tmp->n_neg = n_neg; 00170 00171 // store classifier 00172 classifiers_vector.push_back(tmp); 00173 00174 break; 00175 } 00176 00177 // Fisher Linear Discriminant followed by NCC 00178 case FLDA: 00179 { 00180 Classifier_flda* tmp = new Classifier_flda 00181 ( 00182 classes_vector[i].Data(), 00183 X_neg 00184 ); 00185 00186 // update classifier's possitive class pointer 00187 tmp->pos.push_back(&(classes_vector[i])); 00188 00189 // update classifier's negative classes 00190 tmp->neg = neg_classes; 00191 00192 // update classifier's number of possitive samples 00193 tmp->n_pos = classes_vector[i].Samples(); 00194 00195 // update classifier's number of negative samples 00196 tmp->n_neg = n_neg; 00197 00198 // store classifier 00199 classifiers_vector.push_back(tmp); 00200 00201 break; 00202 } 00203 00204 // Support Vector Machine Classifier 00205 case SVM: 00206 { 00207 Classifier_svm* tmp = new Classifier_svm 00208 ( 00209 classes_vector[i].Data(), 00210 X_neg 00211 ); 00212 00213 // update classifier's possitive class pointer 00214 tmp->pos.push_back(&(classes_vector[i])); 00215 00216 // update classifier's negative classes 00217 tmp->neg = neg_classes; 00218 00219 // update classifier's number of possitive samples 00220 tmp->n_pos = classes_vector[i].Samples(); 00221 00222 // update classifier's number of negative samples 00223 tmp->n_neg = n_neg; 00224 00225 // store classifier 00226 classifiers_vector.push_back(tmp); 00227 00228 break; 00229 } 00230 00231 // AdaBoost Classifier 00232 case ADABOOST: 00233 { 00234 Classifier_adaBoost* tmp = new Classifier_adaBoost 00235 ( 00236 classes_vector[i].Data(), 00237 X_neg 00238 ); 00239 00240 // update classifier's possitive class pointer 00241 tmp->pos.push_back(&(classes_vector[i])); 00242 00243 // update classifier's negative classes 00244 tmp->neg = neg_classes; 00245 00246 // update classifier's number of possitive samples 00247 tmp->n_pos = classes_vector[i].Samples(); 00248 00249 // update classifier's number of negative samples 00250 tmp->n_neg = n_neg; 00251 00252 // store classifier 00253 classifiers_vector.push_back(tmp); 00254 00255 break; 00256 } 00257 00258 // Sum of Error Squares Classifier 00259 case LEAST_SQUARES: 00260 { 00261 Classifier_ls* tmp = new Classifier_ls 00262 ( 00263 classes_vector[i].Data(), 00264 X_neg 00265 ); 00266 00267 // update classifier's possitive class pointer 00268 tmp->pos.push_back(&(classes_vector[i])); 00269 00270 // update classifier's negative classes 00271 tmp->neg = neg_classes; 00272 00273 // update classifier's number of possitive samples 00274 tmp->n_pos = classes_vector[i].Samples(); 00275 00276 // update classifier's number of negative samples 00277 tmp->n_neg = n_neg; 00278 00279 // store classifier 00280 classifiers_vector.push_back(tmp); 00281 00282 break; 00283 } 00284 00285 // Custom Classifier 00286 case CUSTOM_CLASSIFIER: 00287 { 00288 Classifier_custom* tmp = new Classifier_custom 00289 ( 00290 classes_vector[i].Data(), 00291 X_neg 00292 ); 00293 00294 // update classifier's possitive class pointer 00295 tmp->pos.push_back(&(classes_vector[i])); 00296 00297 // update classifier's negative classes 00298 tmp->neg = neg_classes; 00299 00300 // update classifier's number of possitive samples 00301 tmp->n_pos = classes_vector[i].Samples(); 00302 00303 // update classifier's number of negative samples 00304 tmp->n_neg = n_neg; 00305 00306 // store classifier 00307 classifiers_vector.push_back(tmp); 00308 00309 break; 00310 } 00311 00312 default: 00313 { 00314 arma_debug_print("one_vs_all(): Unknown classifier's option"); 00315 } 00316 00317 } 00318 00319 // update ECOC matrix in order to create 1 vs all configuration 00320 coding_matrix(i, k) = 1; 00321 00322 // increase ECOC matrix column counter 00323 k++; 00324 } 00325 00326 // ================================================================ // 00327 // || Testing Step || // 00328 // ================================================================ // 00329 00330 // classification error 00331 double error = 0.0; 00332 00333 // predictions for each sample 00334 uvec predictions; 00335 00336 // confussion matrix 00337 umat confussion; 00338 00339 // number of misclassified samples 00340 u32 n_missed = 0; 00341 00342 // used to hold the number of missclassified testing samples 00343 decode 00344 ( 00345 testing_samples, 00346 tmp_testing_labels, 00347 coding_matrix, 00348 classifiers_vector, 00349 classes_vector, 00350 decoding_strategy, 00351 predictions, 00352 n_missed, 00353 error, 00354 confussion 00355 ); 00356 00357 // if verbose output is activated 00358 if(verbose == true) 00359 { 00360 predictions = join_rows(predictions, tmp_testing_labels); 00361 verbose_output << "* Predictions vs Labels: " << endl << predictions << endl << endl; 00362 verbose_output << "* Coding Matrix: " << endl << coding_matrix << endl << endl; 00363 verbose_output << "* Confusion Matrix: " << endl << confussion << endl; 00364 } 00365 00366 // clean up classifiers vector 00367 for(u32 i = 0; i < classifiers_vector.size(); i++) 00368 { 00369 delete classifiers_vector[i]; 00370 } 00371 00372 // stop timer 00373 execution_time = timer.toc(); 00374 00375 // reset class counter 00376 ClassData::globalIndex = 0; 00377 00378 // return number of misclassified samples 00379 return n_missed; 00380 } 00381 00382 00383