00001
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
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
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
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
00076 data_ = data;
00077
00078
00079 delete features_;
00080
00081
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
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
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
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
00121 constraints_ = constraints;
00122
00123
00124 if( !this->closeClassifierList() ) {
00125 cerr << "Unable to re-make features." << endl;
00126 return false;
00127 }
00128
00129
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
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
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
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
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
00172 trained_[i].first->print(os);
00173 }
00174
00175
00176 trainable_->print(os);
00177
00178
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
00195 if( c==0 || label==0 ) {
00196 cerr << "Unable to add classifier " << c->name().c_str() << endl;
00197 return false;
00198 }
00199
00200
00201 vector<string> trainedVars;
00202 c->vars(trainedVars);
00203
00204
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
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
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
00238 return true;
00239 }
00240
00241
00242
00243 bool SprCombiner::makeFeatures()
00244 {
00245
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
00257 SprData* features = new SprData("features",labels_);
00258
00259
00260 for( int ip=0;ip<data_->size();ip++ ) {
00261 const SprPoint* p = (*data_)[ip];
00262
00263
00264 vector<double> resp(nClassifiers);
00265 for( int ic=0;ic<nClassifiers;ic++ ) {
00266
00267
00268 const SprPoint* pResp
00269 = ( inputDataMappers_[ic]==0 ? p : inputDataMappers_[ic]->output(p) );
00270
00271
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
00294 if( overall )
00295 resp[ic] = trained_[ic].first->response(pResp);
00296 else
00297 resp[ic] = defaultValues_[ic];
00298
00299
00300 if( inputDataMappers_[ic] != 0 ) inputDataMappers_[ic]->clear();
00301 }
00302
00303
00304 features->insert(p->class_,resp);
00305 }
00306
00307
00308 vector<double> weights;
00309 data_->weights(weights);
00310
00311
00312 vector<SprClass> classes;
00313 data_->classes(classes);
00314
00315
00316 features_ = new SprEmptyFilter(features,classes,weights,true);
00317
00318
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
00332 SprAbsTrainedClassifier* overall = trainable_->makeTrained();
00333 bool ownOverall = true;
00334
00335
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
00343 vector<SprCoordinateMapper*> inputDataMappers(inputDataMappers_.size());
00344 for( int i=0;i<inputDataMappers_.size();i++ )
00345 inputDataMappers.push_back(inputDataMappers_[i]->clone());
00346
00347
00348 SprTrainedCombiner* t
00349 = new SprTrainedCombiner(overall,trained,labels_,constraints_,
00350 inputDataMappers,defaultValues_,ownOverall);
00351
00352
00353 vector<string> vars;
00354 data_->vars(vars);
00355 t->setVars(vars);
00356
00357
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 }