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 00049 u32 00050 one_vs_one 00051 ( 00052 const mat& training_samples, 00053 const icolvec& training_labels, 00054 const mat& testing_samples, 00055 const icolvec& testing_labels, 00056 const int decoding_strategy, 00057 const int classifiers_type, 00058 const bool verbose, 00059 ofstream& verbose_output, 00060 double& execution_time 00061 ) 00062 { 00063 // timer object to count execution times 00064 wall_clock timer; 00065 00066 // start timer 00067 timer.tic(); 00068 00069 // number of training samples 00070 const u32 n_training_samples = training_samples.n_rows; 00071 00072 // number of samples attributes 00073 const u32 n_attributes = training_samples.n_cols; 00074 00075 // number of testing samples 00076 const u32 n_testing_samples = testing_samples.n_rows; 00077 00078 // variable to hold the number of classes 00079 u32 n_classes = 0; 00080 00081 // vector to hold number of samples per class 00082 ucolvec n_samples_per_class; 00083 00084 // adjust the training samples class labels to start from one 00085 // and count number of classes 00086 const ucolvec tmp_training_labels = process_labels 00087 ( 00088 training_labels, 00089 n_classes 00090 ); 00091 00092 // adjust the testing samples class labels to start from one 00093 const ucolvec tmp_testing_labels = process_labels(testing_labels); 00094 00095 // decompose the training samples matrix into ClassData object 00096 vector<ClassData> classes_vector = 00097 create_class_vector 00098 ( 00099 training_samples, 00100 conv_to<icolvec>::from(tmp_training_labels) 00101 ); 00102 00103 // declare empty classifiers vector 00104 // vector<Classifier*> classifiers_vector; 00105 00106 // allocate error correcting output codes matrix 00107 imat coding_matrix = zeros<imat> 00108 ( 00109 n_classes, 00110 (n_classes * (n_classes - 1)) / 2 00111 ); 00112 00113 // classifiers vector 00114 vector<Classifier*> classifiers_vector; 00115 00116 // ================================================================ // 00117 // || Training Step || // 00118 // ================================================================ // 00119 00120 // auxuliary column counter 00121 u32 k = 0; 00122 00123 // start training of (K * (K - 1) / 2) classifiers, where K = number 00124 // of classes 00125 for(u32 i = 0; i < n_classes; i++) 00126 { 00127 for(u32 j = i+1; j < n_classes; j++) 00128 { 00129 switch(classifiers_type) 00130 { 00131 // Nearest Class Centroid Classifier 00132 case NCC: 00133 { 00134 Classifier_ncc* tmp = new Classifier_ncc 00135 ( 00136 classes_vector[i].Data(), 00137 classes_vector[j].Data() 00138 ); 00139 00140 // update classifier's class objects 00141 tmp->pos.push_back(&(classes_vector[i])); 00142 tmp->neg.push_back(&(classes_vector[j])); 00143 00144 // update classifier's number of possitive and negative 00145 // samples 00146 tmp->n_pos = classes_vector[i].Samples(); 00147 tmp->n_neg = classes_vector[j].Samples(); 00148 00149 // store classifier 00150 classifiers_vector.push_back(tmp); 00151 00152 break; 00153 } 00154 00155 // Fisher Linear Discriminant followed by NCC 00156 case FLDA: 00157 { 00158 Classifier_flda* tmp = new Classifier_flda 00159 ( 00160 classes_vector[i].Data(), 00161 classes_vector[j].Data() 00162 ); 00163 00164 // update classifier's class objects 00165 tmp->pos.push_back(&(classes_vector[i])); 00166 tmp->neg.push_back(&(classes_vector[j])); 00167 00168 // update classifier's number of possitive and negative 00169 // samples 00170 tmp->n_pos = classes_vector[i].Samples(); 00171 tmp->n_neg = classes_vector[j].Samples(); 00172 00173 // store classifier 00174 classifiers_vector.push_back(tmp); 00175 00176 break; 00177 } 00178 00179 // Support Vector Machine Classifier 00180 case SVM: 00181 { 00182 Classifier_svm* tmp = new Classifier_svm 00183 ( 00184 classes_vector[i].Data(), 00185 classes_vector[j].Data() 00186 ); 00187 00188 // update classifier's class objects 00189 tmp->pos.push_back(&(classes_vector[i])); 00190 tmp->neg.push_back(&(classes_vector[j])); 00191 00192 // update classifier's number of possitive and negative 00193 // samples 00194 tmp->n_pos = classes_vector[i].Samples(); 00195 tmp->n_neg = classes_vector[j].Samples(); 00196 00197 // store classifier 00198 classifiers_vector.push_back(tmp); 00199 00200 break; 00201 } 00202 00203 // AdaBoost Classifier 00204 case ADABOOST: 00205 { 00206 Classifier_adaBoost* tmp = new Classifier_adaBoost 00207 ( 00208 classes_vector[i].Data(), 00209 classes_vector[j].Data() 00210 ); 00211 00212 // update classifier's class objects 00213 tmp->pos.push_back(&(classes_vector[i])); 00214 tmp->neg.push_back(&(classes_vector[j])); 00215 00216 // update classifier's number of possitive and negative 00217 // samples 00218 tmp->n_pos = classes_vector[i].Samples(); 00219 tmp->n_neg = classes_vector[j].Samples(); 00220 00221 // store classifier 00222 classifiers_vector.push_back(tmp); 00223 00224 break; 00225 } 00226 00227 // Sum of Error Squares Classifier 00228 case LEAST_SQUARES: 00229 { 00230 Classifier_ls* tmp = new Classifier_ls 00231 ( 00232 classes_vector[i].Data(), 00233 classes_vector[j].Data() 00234 ); 00235 00236 // update classifier's class objects 00237 tmp->pos.push_back(&(classes_vector[i])); 00238 tmp->neg.push_back(&(classes_vector[j])); 00239 00240 // update classifier's number of possitive and negative 00241 // samples 00242 tmp->n_pos = classes_vector[i].Samples(); 00243 tmp->n_neg = classes_vector[j].Samples(); 00244 00245 // store classifier 00246 classifiers_vector.push_back(tmp); 00247 00248 break; 00249 } 00250 00251 // Custom Classifier 00252 case CUSTOM_CLASSIFIER: 00253 { 00254 Classifier_custom* tmp = new Classifier_custom 00255 ( 00256 classes_vector[i].Data(), 00257 classes_vector[j].Data() 00258 ); 00259 00260 // update classifier's class objects 00261 tmp->pos.push_back(&(classes_vector[i])); 00262 tmp->neg.push_back(&(classes_vector[j])); 00263 00264 // update classifier's number of possitive and negative 00265 // samples 00266 tmp->n_pos = classes_vector[i].Samples(); 00267 tmp->n_neg = classes_vector[j].Samples(); 00268 00269 // store classifier 00270 classifiers_vector.push_back(tmp); 00271 00272 break; 00273 } 00274 00275 default: 00276 { 00277 arma_debug_print("one_vs_one(): Unknown classifier's option"); 00278 } 00279 00280 } 00281 00282 // update ECOC matrix in order to create 1 vs 1 configuration 00283 coding_matrix(i, k) = 1; 00284 coding_matrix(j, k) = -1; 00285 00286 // increase ECOC matrix column counter 00287 k++; 00288 } 00289 00290 } 00291 00292 // ================================================================ // 00293 // || Testing Step || // 00294 // ================================================================ // 00295 00296 // classification error 00297 double error = 0.0; 00298 00299 // predictions for each sample 00300 uvec predictions; 00301 00302 // confussion matrix 00303 umat confussion; 00304 00305 // number of misclassified samples 00306 u32 n_missed = 0; 00307 00308 // used to hold the number of missclassified testing samples 00309 decode 00310 ( 00311 testing_samples, 00312 tmp_testing_labels, 00313 coding_matrix, 00314 classifiers_vector, 00315 classes_vector, 00316 decoding_strategy, 00317 predictions, 00318 n_missed, 00319 error, 00320 confussion 00321 ); 00322 00323 // if verbose output is activated 00324 if(verbose == true) 00325 { 00326 verbose_output << "* Predictions vs Labels: " 00327 << endl 00328 << join_rows(predictions, tmp_testing_labels) 00329 << endl << endl; 00330 verbose_output << "* Coding Matrix: " << endl << coding_matrix << endl << endl; 00331 verbose_output << "* Confusion Matrix: " << endl << confussion << endl; 00332 } 00333 00334 // clean up classifiers vector 00335 for(u32 i = 0; i < classifiers_vector.size(); i++) 00336 { 00337 delete classifiers_vector[i]; 00338 } 00339 00340 // stop timer 00341 execution_time = timer.toc(); 00342 00343 // reset class counter 00344 ClassData::globalIndex = 0; 00345 00346 // return number of misclassified samples 00347 return n_missed; 00348 } 00349 00350 00351