00001 /*!@file Learn/GentleBoostComponent.C Gentle BOOST Classifier component */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Daniel Parks <danielfp@usc.edu> 00034 // $HeadURL$ 00035 // $Id$ 00036 // 00037 00038 #include "Learn/GentleBoost.H" 00039 #include "GentleBoostComponent.H" 00040 #include "Util/StringUtil.H" 00041 00042 #include <fstream> 00043 #include <iostream> 00044 #include <iomanip> 00045 #include <string> 00046 #include <cstdlib> 00047 #include <limits> 00048 00049 const ModelOptionCateg MOC_GentleBoost = { 00050 MOC_SORTPRI_3, "GentleBoost Related Options" }; 00051 00052 const ModelOptionDef OPT_GBModelInputFileNames = 00053 { MODOPT_ARG_STRING, "GB Model Input File Names", &MOC_GentleBoost, OPTEXP_CORE, 00054 "Colon separated list of input filenames to load GB models", 00055 "gb-model-inputfiles", '\0', "<filename1:filename2>", "" }; 00056 00057 const ModelOptionDef OPT_GBModelOutputFileNames = 00058 { MODOPT_ARG_STRING, "GB Model Output File Names", &MOC_GentleBoost, OPTEXP_CORE, 00059 "Colon separated list of output filenames to write GB models", 00060 "gb-model-outputfiles", '\0', "<filename1:filename2>", "" }; 00061 00062 const ModelOptionDef OPT_GBModelNames = 00063 { MODOPT_ARG_STRING, "GB Model Names", &MOC_GentleBoost, OPTEXP_CORE, 00064 "Colon separated list of model names for the GB", 00065 "gb-model-names", '\0', "<name1:name2>", "" }; 00066 00067 const ModelOptionDef OPT_GBMode = 00068 { MODOPT_ARG_STRING, "GB Mode", &MOC_GentleBoost, OPTEXP_CORE, 00069 "The mode of GB Classifier. Train|Rec", 00070 "gb-mode", '\0', "<Train|Rec>", "Rec" }; 00071 00072 const ModelOptionDef OPT_GBMaxIters = 00073 { MODOPT_ARG(int), "GB Max Iters", &MOC_GentleBoost, OPTEXP_CORE, 00074 "Maximum number of iterations to train boosted classifier", 00075 "gb-maxiters", '\0', "<Train|Rec>", "10" }; 00076 00077 00078 00079 GentleBoostComponent::GentleBoostComponent(OptionManager& mgr, 00080 const std::string& descrName, 00081 const std::string& tagName) : 00082 ModelComponent(mgr, descrName, tagName), 00083 itsGBModelInputFileNamesStr(&OPT_GBModelInputFileNames, this), 00084 itsGBModelOutputFileNamesStr(&OPT_GBModelOutputFileNames, this), 00085 itsGBModelNamesStr(&OPT_GBModelNames, this), 00086 itsGBMode(&OPT_GBMode, this), 00087 itsMaxIters(&OPT_GBMaxIters, this), 00088 itsLoadComplete(false) 00089 { 00090 } 00091 00092 GentleBoostComponent::~GentleBoostComponent() 00093 { 00094 } 00095 00096 00097 00098 void GentleBoostComponent::start2() 00099 { 00100 ModelComponent::start2(); 00101 00102 // Parse which model input files should be loaded 00103 split(itsGBModelInputFileNamesStr.getVal(), ":", std::back_inserter(itsGBModelInputFiles)); 00104 00105 // Parse which model output files should be written 00106 split(itsGBModelOutputFileNamesStr.getVal(), ":", std::back_inserter(itsGBModelOutputFiles)); 00107 00108 // Parse which model names should be loaded 00109 split(itsGBModelNamesStr.getVal(), ":", std::back_inserter(itsGBModelNames)); 00110 00111 ASSERT(itsMaxIters.getVal() > 0); 00112 00113 if (itsGBMode.getVal().compare("Train") == 0) // training 00114 { 00115 if(itsGBModelOutputFiles.size() == 0 || itsGBModelOutputFiles.size() != itsGBModelNames.size()) { 00116 LFATAL("Must specify gb model output file(s) (and equal number of model names) if in training mode"); 00117 } 00118 // Load basic classifier for training 00119 GentleBoost classifier; 00120 itsClassifiers.push_back(classifier); 00121 itsClassifierLabels.push_back(std::vector<int>()); 00122 itsClassifierVectors.push_back(std::vector<std::vector<float> >()); 00123 } 00124 else if (itsGBMode.getVal().compare("Rec") == 0) // Recognition 00125 { 00126 if(itsGBModelInputFiles.size() == 0 || itsGBModelInputFiles.size() != itsGBModelNames.size()){ 00127 LFATAL("Must specify gb model input file(s) (and equal number of model names) if in recognition mode"); 00128 } 00129 for(size_t c=0;c<itsGBModelInputFiles.size();c++) 00130 { 00131 GentleBoost classifier; 00132 // Load model file 00133 classifier.load(itsGBModelInputFiles[c]); 00134 itsClassifiers.push_back(classifier); 00135 itsClassifierLabels.push_back(std::vector<int>()); 00136 itsClassifierVectors.push_back(std::vector<std::vector<float> >()); 00137 } 00138 } 00139 else 00140 LFATAL("Unknown GB Mode type %s", itsGBMode.getVal().c_str()); 00141 itsLoadComplete = true; 00142 } 00143 00144 // ###################################################################### 00145 void GentleBoostComponent::stop1() 00146 { 00147 ModelComponent::stop1(); 00148 if(itsLoadComplete) 00149 { 00150 train(itsMaxIters.getVal()); 00151 save(); 00152 } 00153 } 00154 00155 std::string GentleBoostComponent::getMode() 00156 { 00157 return itsGBMode.getVal(); 00158 } 00159 00160 00161 std::vector<std::string> GentleBoostComponent::getModelNames() 00162 { 00163 return itsGBModelNames; 00164 } 00165 00166 int GentleBoostComponent::getMostLikelyClass(const std::map<int,float>& pdf) 00167 { 00168 float maxClassVal=-std::numeric_limits<float>::max(); 00169 int maxClassIdx=-1; 00170 std::map<int,float>::const_iterator pitr; 00171 for(pitr=pdf.begin();pitr!=pdf.end();pitr++) 00172 { 00173 if(maxClassVal < pitr->second) 00174 { 00175 maxClassVal=pitr->second; 00176 maxClassIdx=pitr->first; 00177 } 00178 } 00179 ASSERT(maxClassIdx>=0); 00180 return maxClassIdx; 00181 } 00182 00183 00184 // Add training examplar 00185 void GentleBoostComponent::addTrainVector(std::vector<float> featureVector, int id, int classifierId) 00186 { 00187 itsClassifierVectors[classifierId].push_back(featureVector); 00188 itsClassifierLabels[classifierId].push_back(id); 00189 } 00190 00191 // Train the classifier on the final data 00192 void GentleBoostComponent::train(int classifierId) 00193 { 00194 // NOTE: Training vectors must be transposed here 00195 // If not specified, train all classifiers 00196 if(classifierId == -1) 00197 { 00198 for(size_t c=0;c<itsClassifiers.size();c++) 00199 { 00200 if(itsClassifierLabels[c].size() > 0) 00201 { 00202 itsClassifiers[c].train(itsClassifiers[c].transpose(itsClassifierVectors[c]),itsClassifierLabels[c],itsMaxIters.getVal()); 00203 } 00204 } 00205 } 00206 else 00207 { 00208 if(itsClassifierLabels[classifierId].size() > 0) 00209 itsClassifiers[classifierId].train(itsClassifiers[classifierId].transpose(itsClassifierVectors[classifierId]),itsClassifierLabels[classifierId],itsMaxIters.getVal()); 00210 } 00211 } 00212 00213 // Save the classifier data 00214 void GentleBoostComponent::save(int classifierId) 00215 { 00216 // If not specified, train all classifiers 00217 if(classifierId == -1) 00218 { 00219 for(size_t c=0;c<itsClassifiers.size();c++) 00220 { 00221 itsClassifiers[c].save(itsGBModelOutputFiles[c]); 00222 } 00223 } 00224 else 00225 { 00226 itsClassifiers[classifierId].save(itsGBModelOutputFiles[classifierId]); 00227 } 00228 } 00229 00230 00231 int GentleBoostComponent::predict(std::vector<float> featureVector, int classifierId) 00232 { 00233 std::vector<std::vector<float> > convVec(1); 00234 convVec[0] = featureVector; 00235 // Transpose vector from 1xn to nx1 00236 convVec = itsClassifiers[classifierId].transpose(convVec); 00237 std::vector<int> tmpVec; 00238 tmpVec = itsClassifiers[classifierId].predict(convVec); 00239 return tmpVec[0]; 00240 } 00241 00242 std::map<int, float> GentleBoostComponent::predictPDF(std::vector<float> featureVector, int classifierId) 00243 { 00244 std::map<int, float> out; 00245 std::vector<std::vector<float> > convVec(1); 00246 convVec[0] = featureVector; 00247 // Transpose vector from 1xn to nx1 00248 convVec = itsClassifiers[classifierId].transpose(convVec); 00249 std::map<int, std::vector<float> > tmpMap; 00250 tmpMap = itsClassifiers[classifierId].predictPDF(convVec); 00251 std::map<int,std::vector<float> >::iterator litr; 00252 for(litr=tmpMap.begin();litr!=tmpMap.end();litr++) 00253 { 00254 out[litr->first] = litr->second[0]; 00255 } 00256 return out; 00257 } 00258 00259