CMS 3D CMS Logo

SprCombiner.cc

Go to the documentation of this file.
00001 //$Id: SprCombiner.cc,v 1.1 2007/09/21 22:32:09 narsky Exp $
00002 
00003 #include "PhysicsTools/StatPatternRecognition/interface/SprExperiment.hh"
00004 #include "PhysicsTools/StatPatternRecognition/interface/SprCombiner.hh"
00005 #include "PhysicsTools/StatPatternRecognition/interface/SprAbsTrainedClassifier.hh"
00006 #include "PhysicsTools/StatPatternRecognition/interface/SprAbsFilter.hh"
00007 #include "PhysicsTools/StatPatternRecognition/interface/SprData.hh"
00008 #include "PhysicsTools/StatPatternRecognition/interface/SprPoint.hh"
00009 #include "PhysicsTools/StatPatternRecognition/interface/SprClass.hh"
00010 #include "PhysicsTools/StatPatternRecognition/interface/SprCoordinateMapper.hh"
00011 #include "PhysicsTools/StatPatternRecognition/interface/SprEmptyFilter.hh"
00012 
00013 #include <algorithm>
00014 
00015 using namespace std;
00016 
00017 
00018 SprCombiner::~SprCombiner() 
00019 { 
00020   delete features_; 
00021   for( int i=0;i<trained_.size();i++ ) {
00022     if( trained_[i].second )
00023       delete trained_[i].first;
00024   }
00025   for( int i=0;i<inputDataMappers_.size();i++ )
00026     delete inputDataMappers_[i];
00027 }
00028 
00029 
00030 SprCombiner::SprCombiner(SprAbsFilter* data) 
00031   : 
00032   SprAbsClassifier(data),
00033   trainable_(0),
00034   features_(0),
00035   trained_(),
00036   labels_(),
00037   constraints_(),
00038   inputDataMappers_(),
00039   defaultValues_()
00040 {}
00041 
00042 
00043 bool SprCombiner::train(int verbose)
00044 {
00045   // sanity check
00046   if( trainable_==0 || trained_.empty() ) {
00047     cerr << "Cannot train Combiner - not all classifiers defined." << endl;
00048     return false;
00049   }
00050   if( features_ == 0 ) {
00051     cerr << "Classifier list has not been closed." << endl;
00052     return false;
00053   }
00054 
00055   // set data
00056   if( !trainable_->setData(features_) ) {
00057     cerr << "Unable to set data for trainable classifier " 
00058          << trainable_->name().c_str() << endl;
00059     return false;
00060   }
00061 
00062   // train
00063   return trainable_->train(verbose);
00064 }
00065 
00066 
00067 bool SprCombiner::reset()
00068 {
00069   return trainable_->reset();
00070 }
00071 
00072 
00073 bool SprCombiner::setData(SprAbsFilter* data)
00074 {
00075   // reset main data
00076   data_ = data;
00077 
00078   // remake features
00079   delete features_;
00080 
00081   // size
00082   int nClassifiers = trained_.size();
00083   if( nClassifiers == 0 ) {
00084     cerr << "No classifiers have been specified for Combiner." << endl;
00085     return false;
00086   }
00087   assert( nClassifiers == labels_.size() );
00088   assert( nClassifiers == constraints_.size() );
00089   assert( nClassifiers == inputDataMappers_.size() );
00090   assert( nClassifiers == defaultValues_.size() );
00091 
00092   // make copies of everything
00093   vector<pair<const SprAbsTrainedClassifier*,bool> > trained = trained_;
00094   vector<string> labels = labels_;
00095   vector<LocalIndexMap> constraints = constraints_;
00096   vector<double> defaultValues = defaultValues_; 
00097 
00098   // clean up
00099   trained_.clear();
00100   labels_.clear();
00101   constraints_.clear();
00102   defaultValues_.clear();
00103   for( int i=0;i<inputDataMappers_.size();i++ )
00104     delete inputDataMappers_[i];
00105   inputDataMappers_.clear();
00106 
00107   // re-make
00108   for( int i=0;i<nClassifiers;i++ ) {
00109     if( !this->addTrained(trained[i].first,
00110                           labels[i].c_str(),
00111                           SprAllowedStringMap(),
00112                           defaultValues[i],
00113                           trained[i].second) ) {
00114       cerr << "Unable to re-insert trained classifier " << i 
00115            << " with name " << trained[i].first->name().c_str() << endl;
00116       return false;
00117     }
00118   }
00119 
00120   // mapping from user contraints to trained classifier vars does not change
00121   constraints_ = constraints;
00122 
00123   // make features
00124   if( !this->closeClassifierList() ) {
00125     cerr << "Unable to re-make features." << endl;
00126     return false;
00127   }
00128 
00129   // reset
00130   return this->reset();
00131 }
00132 
00133 
00134 void SprCombiner::print(std::ostream& os) const
00135 {
00136   os << "Trained Combiner " << SprVersion << endl;
00137   os << "Sub-classifiers: " << trained_.size() << endl;
00138 
00139   // loop over sub-classfiers
00140   for( int i=0;i<trained_.size();i++ ) {
00141     os << "Sub-classifier: " << i 
00142        << " Name: " << labels_[i] 
00143        << " Default: " << defaultValues_[i] << endl;
00144 
00145     // dump variables
00146     vector<string> vars;
00147     trained_[i].first->vars(vars);
00148     os << "Variables: " << vars.size() << endl;
00149     for( int j=0;j<vars.size();j++ )
00150       os << vars[j].c_str() << " ";
00151     os << endl;
00152 
00153     // dump mappers
00154     vector<unsigned> mapper;
00155     inputDataMappers_[i]->mapper(mapper);
00156     os << "Mappers: " << mapper.size() << endl;
00157     for( int j=0;j<mapper.size();j++ )
00158       os << mapper[j] << " ";
00159     os << endl;
00160 
00161     // dump constraints
00162     os << "Constraints: " << constraints_[i].size() << endl;
00163     for( LocalIndexMap::const_iterator 
00164            iter=constraints_[i].begin();iter!=constraints_[i].end();iter++ ) {
00165       os << iter->first << " " << iter->second.size() << " ";
00166       for( int k=0;k<iter->second.size();k++ )
00167         os << iter->second[k].first << " " << iter->second[k].second << " ";
00168       os << endl;
00169     }
00170 
00171     // dump the sub-classifier
00172     trained_[i].first->print(os);
00173   }
00174 
00175   // dump the main classifier
00176   trainable_->print(os);
00177 
00178   // dump features for trainable classifier
00179   os << "Features: " << features_->dim() << endl;
00180   vector<string> fVars;
00181   features_->vars(fVars);
00182   for( int d=0;d<features_->dim();d++ )
00183     os << fVars[d] << " ";
00184   os << endl;
00185 }
00186 
00187 
00188 bool SprCombiner::addTrained(const SprAbsTrainedClassifier* c, 
00189                              const char* label,
00190                              const SprAllowedStringMap& stringMap,
00191                              double defaultValue,
00192                              bool own)
00193 {
00194   // sanity check
00195   if( c==0 || label==0 ) {
00196     cerr << "Unable to add classifier " << c->name().c_str() << endl;
00197     return false;
00198   }
00199 
00200   // get classifier vars
00201   vector<string> trainedVars;
00202   c->vars(trainedVars);
00203 
00204   // make sure that each trained classifier variable is present in the data
00205   vector<string> vars;
00206   data_->vars(vars);
00207   SprCoordinateMapper* mapper 
00208     = SprCoordinateMapper::createMapper(trainedVars,vars);
00209   if( mapper == 0 ) {
00210     cerr << "Unable to map trained variables for combiner." << endl;
00211     return false;
00212   }
00213 
00214   // make sure that each cut-on variable is present in the variable list
00215   LocalIndexMap indexMap;
00216   for( SprAllowedStringMap::const_iterator 
00217          iter=stringMap.begin();iter!=stringMap.end();iter++ ) {
00218     vector<string>::const_iterator found 
00219       = find(trainedVars.begin(),trainedVars.end(),iter->first);
00220     if( found == trainedVars.end() ) {
00221       cerr << "Unable to find variable " << iter->first.c_str() 
00222            << " from the input map among variables for trained" 
00223            << " classifier " << c->name().c_str() << endl;
00224       return false;
00225     }
00226     int d = found - trainedVars.begin();
00227     indexMap.insert(pair<unsigned,SprCut>(d,iter->second));
00228   }
00229 
00230   // add
00231   trained_.push_back(pair<const SprAbsTrainedClassifier*,bool>(c,own));
00232   labels_.push_back(label);
00233   constraints_.push_back(indexMap);
00234   inputDataMappers_.push_back(mapper);
00235   defaultValues_.push_back(defaultValue);
00236 
00237   // exit
00238   return true;
00239 }
00240 
00241 
00242 
00243 bool SprCombiner::makeFeatures()
00244 {
00245   // size
00246   int nClassifiers = trained_.size();
00247   if( nClassifiers == 0 ) {
00248     cerr << "No classifiers have been specified for Combiner." << endl;
00249     return false;
00250   }
00251   assert( nClassifiers == labels_.size() );
00252   assert( nClassifiers == constraints_.size() );
00253   assert( nClassifiers == inputDataMappers_.size() );
00254   assert( nClassifiers == defaultValues_.size() );
00255 
00256   // make data
00257   SprData* features = new SprData("features",labels_);
00258 
00259   // loop over data points
00260   for( int ip=0;ip<data_->size();ip++ ) {
00261     const SprPoint* p = (*data_)[ip];
00262 
00263     // loop over classifiers
00264     vector<double> resp(nClassifiers);
00265     for( int ic=0;ic<nClassifiers;ic++ ) {
00266 
00267       // map this point onto classifier variables
00268       const SprPoint* pResp 
00269         = ( inputDataMappers_[ic]==0 ? p : inputDataMappers_[ic]->output(p) );
00270 
00271       // does this point satisfy constraints?
00272       bool overall = true;
00273       const LocalIndexMap& indexMap = constraints_[ic];
00274       for( unsigned d=0;d<pResp->dim();d++ ) {
00275         double x = pResp->x_[d];
00276         LocalIndexMap::const_iterator found = indexMap.find(d);
00277         if( found == indexMap.end() ) continue;
00278         bool accept = true;
00279         const SprCut& cut = found->second;
00280         if( !cut.empty() ) accept = false;
00281         for( int k=0;k<cut.size();k++ ) {
00282           if( x>cut[k].first && x<cut[k].second ) {
00283             accept = true;
00284             break;
00285           }
00286         }
00287         if( !accept ) {
00288           overall = false;
00289           break;
00290         }
00291       }
00292 
00293       // compute classifier response
00294       if( overall )
00295         resp[ic] = trained_[ic].first->response(pResp);
00296       else
00297         resp[ic] = defaultValues_[ic];
00298 
00299       // clean up the new point
00300       if( inputDataMappers_[ic] != 0 ) inputDataMappers_[ic]->clear();
00301     }// end of classifier loop
00302     
00303     // insert this point into features
00304     features->insert(p->class_,resp);
00305   }
00306 
00307   // get weights
00308   vector<double> weights;
00309   data_->weights(weights);
00310 
00311   // get classes
00312   vector<SprClass> classes;
00313   data_->classes(classes);
00314 
00315   // make filter
00316   features_ = new SprEmptyFilter(features,classes,weights,true);
00317 
00318   // exit
00319   return true;
00320 }
00321 
00322 
00323 bool SprCombiner::closeClassifierList()
00324 {
00325   return this->makeFeatures();
00326 }
00327 
00328 
00329 SprTrainedCombiner* SprCombiner::makeTrained() const
00330 {
00331   // make trained classifier
00332   SprAbsTrainedClassifier* overall = trainable_->makeTrained();
00333   bool ownOverall = true;
00334 
00335   // clone sub-classifiers
00336   vector<pair<const SprAbsTrainedClassifier*,bool> > trained;
00337   for( int i=0;i<trained_.size();i++ ) {
00338     SprAbsTrainedClassifier* c = trained_[i].first->clone();
00339     trained.push_back(pair<const SprAbsTrainedClassifier*,bool>(c,true));
00340   }
00341 
00342   // clone coordinate mappers
00343   vector<SprCoordinateMapper*> inputDataMappers(inputDataMappers_.size());
00344   for( int i=0;i<inputDataMappers_.size();i++ )
00345     inputDataMappers.push_back(inputDataMappers_[i]->clone());
00346 
00347   // make trained combiner
00348   SprTrainedCombiner* t 
00349     = new SprTrainedCombiner(overall,trained,labels_,constraints_,
00350                              inputDataMappers,defaultValues_,ownOverall);
00351 
00352   // vars
00353   vector<string> vars;
00354   data_->vars(vars);
00355   t->setVars(vars);
00356 
00357   // exit
00358   return t;
00359 }
00360 
00361 
00362 bool SprCombiner::setClasses(const SprClass& cls0, const SprClass& cls1) 
00363 {
00364   if( !trainable_->setClasses(cls0,cls1) ) {
00365     cerr << "Combiner unable to reset classes." << endl;
00366     return false;
00367   }
00368   cout << "Classes for Combiner reset to " << cls0 << " " << cls1 << endl;
00369   return true;
00370 }

Generated on Tue Jun 9 17:42:02 2009 for CMSSW by  doxygen 1.5.4