Feature Selection Toolbox FST4
UTIA · Czech Academy of Sciences
Loading...
Searching...
No Matches
seq_step_hybrid.hpp
Go to the documentation of this file.
1#ifndef FSTSEARCHSEQSTEPHYBRID_H
2#define FSTSEARCHSEQSTEPHYBRID_H
3 /*
27=========================================================================
28Copyright and license:
29 * FST4 software (with the exception of any bundled or externally linked
30 third-party components) is Copyright (C) 2000-present Institute of
31 Information Theory and Automation of the Czech Academy of Sciences (UTIA).
32 * FST4 is free software: you can redistribute it and/or modify it under
33 the terms of the GNU Affero General Public License as published by the
34 Free Software Foundation, version 3. The full text of the license is in
35 the file LICENSE in the distribution root and at
36 https://www.gnu.org/licenses/agpl-3.0.html.
37 * FST4 is distributed in the hope that it will be useful, but WITHOUT ANY
38 WARRANTY; without even the implied warranty of MERCHANTABILITY or
39 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
40 License for more details.
41 * Closed-source use without the AGPL's copyleft obligations requires a
42 commercial license from UTIA; in case of interest write to
43 utia@utia.cas.cz. LICENSING.md in the distribution root explains both
44 options, the contributor license agreement that every contribution
45 requires, and the contacts (technical questions and pull requests:
46 somol@utia.cas.cz, with "FST" in the subject line).
47========================================================================== */
48
49#include <memory>
50#include <cassert>
51#include <iostream>
52#include <sstream>
53#include <list>
54#include "error.hpp"
55#include "global.hpp"
56#include "seq_step.hpp"
59
60/*============== Template parameter type naming conventions ==============
61--------- Numeric types: -------------------------------------------------
62DATATYPE - data sample values - usually real numbers (but may be integers
63 in text processing etc.)
64REALTYPE - must be real numbers - for representing intermediate results of
65 calculations like mean, covariance etc.
66IDXTYPE - index values for enumeration of data samples - (nonnegative) integers,
67 extent depends on numbers of samples in data
68DIMTYPE - index values for enumeration of features (dimensions), or classes (not
69 class sizes) - (nonnegative) integers, usually lower extent than IDXTYPE,
70 but be aware of expressions like _classes*_features*_features !
71 in linearized representations of feature matrices for all classes
72BINTYPE - feature selection marker type - represents ca. <10 different feature
73 states (selected, deselected, sel./desel. temporarily 1st nested loop, 2nd...)
74RETURNTYPE - criterion value: real value, but may be extended in future to support
75 multiple values
76--------- Class types: ---------------------------------------------------
77SUBSET - class of class type Subset
78CLASSIFIER - class implementing interface defined in abstract class Classifier
79EVALUATOR - class implementing interface defined in abstract class Sequential_Step
80DISTANCE - class implementing interface defined in abstract class Distance
81DATAACCESSOR - class implementing interface defined in abstract class Data_Accessor
82INTERVALCONTAINER - class of class type Data_Intervaller
83CONTAINER - STL container of class type Data_Interval
84========================================================================== */
85
86namespace FST {
87
116template<class RETURNTYPE, typename DIMTYPE, class SUBSET, class CRITERION, class FILTERCRITERION>
117class Sequential_Step_Hybrid : public Sequential_Step<RETURNTYPE,DIMTYPE,SUBSET,CRITERION>{
118public:
119 typedef Sequential_Step<RETURNTYPE,DIMTYPE,SUBSET,CRITERION> parent;
120 typedef std::shared_ptr<FILTERCRITERION> PFilterCriterion;
121 typedef std::shared_ptr<CRITERION> PCriterion;
122 typedef std::shared_ptr<SUBSET> PSubset;
124 typedef std::shared_ptr<EVALUATORENGINE> PEvaluatorEngine;
129 Sequential_Step_Hybrid(const PFilterCriterion filtercrit, const DIMTYPE keep_perc, const DIMTYPE keep_max=1000, PEvaluatorEngine engine=PEvaluatorEngine()):Sequential_Step<RETURNTYPE,DIMTYPE,SUBSET,CRITERION>(),_engine(engine),track(false) {assert(keep_perc<=100); assert(keep_max>0); assert(filtercrit); _filtercrit=filtercrit; _keep_perc=keep_perc; _keep_max=keep_max; _listsize=0; if(!_engine) _engine.reset(new Candidate_Evaluator_Sequential<RETURNTYPE,DIMTYPE,SUBSET,CRITERION>()); notify("Sequential_Step_Hybrid constructor.");}
130 virtual ~Sequential_Step_Hybrid() {notify("Sequential_Step_Hybrid destructor.");}
131
132 void set_prefiltering_limits(const DIMTYPE keep_perc, const DIMTYPE keep_max) {assert(keep_perc<=100); assert(keep_max>0); _keep_perc=keep_perc; _keep_max=keep_max;}
133 DIMTYPE get_prefiltering_perc() const {return _keep_perc;}
134 DIMTYPE get_prefiltering_max() const {return _keep_max;}
135
136 // NOTE: crit is expected to be already initialize()d before use here
137 inline bool evaluate_candidates(RETURNTYPE &result, const PSubset sub, const PCriterion crit, const DIMTYPE _generalization_level=1, std::ostream& os=std::cout) override;
138
139 virtual std::ostream& print(std::ostream& os) const override;
140protected:
141 inline bool filter_candidates(const PSubset sub, const DIMTYPE _generalization_level, std::ostream& os);
142 inline bool test_candidate(const PSubset sub);
143
146 DIMTYPE _keep_perc;
147 DIMTYPE _keep_max;
148
151 public:
152 SubsetCandidate(const RETURNTYPE value, const PSubset sub) : _value(value), _sub(new SUBSET(*sub)) {}
153 const RETURNTYPE _value;
154 const PSubset _sub;
155 };
156 typedef std::list<SubsetCandidate> CANDIDATELIST;
157
158 DIMTYPE _listsize;
160 typename CANDIDATELIST::iterator iter;
161
162private:
163 bool track;
164};
165
166template<class RETURNTYPE, typename DIMTYPE, class SUBSET, class CRITERION, class FILTERCRITERION>
168{
169 if(_engine->is_threaded()) os << "Sequential_Step_Hybrid(keep_perc="<<_keep_perc<<", max="<<_keep_max<<", threads="<<_engine->get_max_threads()<<")";
170 else os << "Sequential_Step_Hybrid(keep_perc="<<_keep_perc<<", max="<<_keep_max<<")";
171 if(_filtercrit) os << " with filter " << *_filtercrit;
172 if(parent::result_tracker_active()) os << " with " << *parent::_tracker;
173 return os;
174}
175
176template<class RETURNTYPE, typename DIMTYPE, class SUBSET, class CRITERION, class FILTERCRITERION>
178{
179 assert(sub);
180 assert(_filtercrit);
181 RETURNTYPE val;
182 DIMTYPE _idx=0;
183 assert(sub->get_d()!=0);
184 // the filter criterion's values are deliberately NOT fed to the result tracker: the tracker
185 // would then hold values of two different criteria, which are not comparable with each other
186 if(!_filtercrit->evaluate(val,sub)) return false;
187 for(iter=_filterlist.begin(); _idx<_listsize && iter!=_filterlist.end() && (val<iter->_value || (val==iter->_value && sub->get_d()>=iter->_sub->get_d())); iter++) {++_idx;}
188 if(_idx<_listsize) { // candidate good enough to be inserted
189 _filterlist.insert(iter,SubsetCandidate(val,sub));
190 if(_filterlist.size()>_listsize) _filterlist.pop_back();
191 }
192 return true;
193}
194
195template<class RETURNTYPE, typename DIMTYPE, class SUBSET, class CRITERION, class FILTERCRITERION>
196bool Sequential_Step_Hybrid<RETURNTYPE,DIMTYPE,SUBSET,CRITERION,FILTERCRITERION>::filter_candidates(const PSubset sub, const DIMTYPE _generalization_level, std::ostream& os)
197{
198 assert(sub);
199 _filterlist.clear();
200 assert(_keep_perc<=100);
201 assert(_keep_max>0);
202 assert(_generalization_level>=1 && _generalization_level<=sub->get_n());
203
204 // determine maximum _filterlist size: keep_perc percent of the candidates, capped at
205 // keep_max, but never less than one - a shortlist of zero would leave the main criterion
206 // nothing to evaluate, so keep_perc==0 means "shortlist the single best by filtercrit"
207 _listsize=DIMTYPE(((double)_keep_perc/100.0)*sub->getNoOfCandidateSubsets(_generalization_level,false/*reverse*/));
209 if(_listsize==0) _listsize=1;
210
211 // first build candidate list _filterlist (pre-filter using _filtercrit criterion)
212 bool b=sub->getFirstCandidateSubset(_generalization_level,false/*reverse*/); if(!b) return false; // no candidate subsets can be traversed for whatever reason
213 if(!test_candidate(sub)) return false;
214 b=sub->getNextCandidateSubset(); // evaluate the remaining candidates
215 while(b) {
216 if(!test_candidate(sub)) return false;
217 b=sub->getNextCandidateSubset();
218 }
219 assert(_filterlist.size()>0);
221 std::ostringstream sos;
222 sos << "candidate list of "<<_filterlist.size() << ":" << std::endl;
223 for(iter=_filterlist.begin(); iter!=_filterlist.end(); iter++) {sos << iter->_value << " ~ " << *(iter->_sub) << std::endl;}
224 sos << std::endl << std::flush;
225 syncout::print(os,sos);
226 }
227 return true;
228}
229
230template<class RETURNTYPE, typename DIMTYPE, class SUBSET, class CRITERION, class FILTERCRITERION>
231bool Sequential_Step_Hybrid<RETURNTYPE,DIMTYPE,SUBSET,CRITERION,FILTERCRITERION>::evaluate_candidates(RETURNTYPE &result, const PSubset sub, const PCriterion crit, const DIMTYPE _generalization_level, std::ostream& os)
232{
233 assert(sub);
234 assert(crit);
235 assert(_filtercrit);
236 assert(_keep_perc<=100);
237 assert(_keep_max>0);
238 assert(_generalization_level>=1 && _generalization_level<=sub->get_n());
240
241 if(!filter_candidates(sub,_generalization_level,os)) {if(parent::output_normal()) {std::ostringstream sos; sos << "FAILURE filter_candidates() sub=" << *sub << std::endl << std::endl << std::flush; syncout::print(os,sos);} return false;}
242 assert(_filterlist.size()>0);
243
244 if(_keep_perc==0) { // shortlist of one: no main-criterion SELECTION, but the main criterion
245 // is still evaluated on that candidate and its value is what we return
246 assert(_filterlist.size()>0);
247 sub->stateless_copy( *((_filterlist.begin())->_sub) );
248 assert(sub->get_d()!=0);
249 if(!crit->evaluate(result,sub)) {if(parent::output_normal()) {std::ostringstream sos; sos << "FAILURE crit->eval() sub=" << *(sub) << std::endl << std::endl << std::flush; syncout::print(os,sos);} return false;}
250 if(track) parent::_tracker->add(result,sub);
251 return true;
252 }
253
254 // main-criterion phase through the injected engine (sequential in-line by default,
255 // thread-pooled when constructed with Candidate_Evaluator_Threaded); the engine fires the
256 // per-result callback in candidate (add) order and getBestResult() breaks ties by earliest
257 // candidate, so results and tracker feed are the same for any thread count
258 assert(_engine);
259 typename EVALUATORENGINE::ResultCallback on_result;
260 if(track) {
262 on_result=[tracker](const RETURNTYPE val, const PSubset &csub, const DIMTYPE) {tracker->add(val,csub);};
263 }
264 _engine->initialize(crit,(DIMTYPE)_filterlist.size(),on_result);
265 for(iter=_filterlist.begin();iter!=_filterlist.end();iter++) {
266 if(!_engine->add_candidate(iter->_sub)) {if(parent::output_normal()) {std::ostringstream sos; sos << "FAILURE crit->eval() sub=" << *(iter->_sub) << std::endl << std::endl << std::flush; syncout::print(os,sos);} return false;}
267 }
268 PSubset psub;
269 DIMTYPE dummyfeature;
270 if(!_engine->getBestResult(result,psub,dummyfeature)) {if(parent::output_normal()) {std::ostringstream sos; sos << "FAILURE crit->eval() (no candidate evaluated)" << std::endl << std::endl << std::flush; syncout::print(os,sos);} return false;}
271 assert(psub);
272 sub->stateless_copy(*psub);
273 assert(sub->get_d()!=0);
274
275 return true;
276}
277
278
279} // namespace
280#endif // FSTSEARCHSEQSTEPHYBRID_H ///:~
Abstract candidate-evaluation strategy: the seam through which one search algorithm body evaluates ca...
Implements sequential in-line evaluation of a criterion on a set of subset candidates.
Implements sequential in-line evaluation of a criterion on a set of subset candidates.
Definition candidate_evaluator_sequential.hpp:62
Abstract candidate-evaluation strategy (sequential-inline vs. thread-pooled).
Definition candidate_evaluator.hpp:86
std::function< void(const RETURNTYPE, const PSubset &, const DIMTYPE)> ResultCallback
fired once per evaluated batch candidate: (criterion value, candidate, feature tag as passed to add_c...
Definition candidate_evaluator.hpp:94
Nested class to hold [Subset,criterion value] pair in the course of hybrid feature candidate evaluati...
Definition seq_step_hybrid.hpp:150
const PSubset _sub
an owned copy of the candidate subset (independent of the caller's subset instance)
Definition seq_step_hybrid.hpp:154
SubsetCandidate(const RETURNTYPE value, const PSubset sub)
stores value together with an owned copy of sub
Definition seq_step_hybrid.hpp:152
const RETURNTYPE _value
the filter criterion value of _sub
Definition seq_step_hybrid.hpp:153
Implements hybrid selection step in sequential search type of methods.
Definition seq_step_hybrid.hpp:117
Candidate_Evaluator< RETURNTYPE, DIMTYPE, SUBSET, CRITERION > EVALUATORENGINE
Definition seq_step_hybrid.hpp:123
std::shared_ptr< SUBSET > PSubset
Definition seq_step_hybrid.hpp:122
bool evaluate_candidates(RETURNTYPE &result, const PSubset sub, const PCriterion crit, const DIMTYPE _generalization_level=1, std::ostream &os=std::cout) override
chooses among subsets offered by sub->get*CandidateSubset()
Definition seq_step_hybrid.hpp:231
bool filter_candidates(const PSubset sub, const DIMTYPE _generalization_level, std::ostream &os)
evaluates every offered candidate with _filtercrit and keeps the top _listsize in _filterlist,...
Definition seq_step_hybrid.hpp:196
PFilterCriterion _filtercrit
Definition seq_step_hybrid.hpp:145
std::shared_ptr< CRITERION > PCriterion
Definition seq_step_hybrid.hpp:121
DIMTYPE get_prefiltering_max() const
the currently configured keep_max
Definition seq_step_hybrid.hpp:134
Sequential_Step_Hybrid(const PFilterCriterion filtercrit, const DIMTYPE keep_perc, const DIMTYPE keep_max=1000, PEvaluatorEngine engine=PEvaluatorEngine())
Definition seq_step_hybrid.hpp:129
DIMTYPE get_prefiltering_perc() const
the currently configured keep_perc
Definition seq_step_hybrid.hpp:133
CANDIDATELIST::iterator iter
Definition seq_step_hybrid.hpp:160
virtual std::ostream & print(std::ostream &os) const override
writes a human-readable identification of the step, its prefiltering settings, filter criterion and (...
Definition seq_step_hybrid.hpp:167
std::shared_ptr< CRITERION > PFilterCriterion
Definition seq_step_hybrid.hpp:120
bool test_candidate(const PSubset sub)
evaluates one candidate with _filtercrit and inserts it into _filterlist in sorted position,...
Definition seq_step_hybrid.hpp:177
Sequential_Step< RETURNTYPE, DIMTYPE, SUBSET, CRITERION > parent
Definition seq_step_hybrid.hpp:119
std::list< SubsetCandidate > CANDIDATELIST
Definition seq_step_hybrid.hpp:156
std::shared_ptr< EVALUATORENGINE > PEvaluatorEngine
Definition seq_step_hybrid.hpp:124
void set_prefiltering_limits(const DIMTYPE keep_perc, const DIMTYPE keep_max)
reconfigures the pre-filtering percentage/cap (see the constructor parameters)
Definition seq_step_hybrid.hpp:132
bool output_normal() const
true unless output detail is SILENT
Definition seq_step.hpp:137
std::shared_ptr< Result_Tracker< RETURNTYPE, SUBSET > > PResultTracker
shared pointer to the result tracker enabled via enable_result_tracking()
Definition seq_step.hpp:103
PResultTracker _tracker
the assigned result tracker, or null (see enable_result_tracking()/result_tracker_active())
Definition seq_step.hpp:140
bool output_detailed() const
true only at the DETAILED output level
Definition seq_step.hpp:138
bool result_tracker_active() const
true if a result tracker was assigned via enable_result_tracking() and not since disabled
Definition seq_step.hpp:133
static void print(std::ostream &os, std::ostringstream &sos)
Writes sos's buffered content to os, serializing concurrent writers under FST_THREADED via a shared m...
Definition global.hpp:86
FST4 specific error passing class.
Global definitions.
The Feature Selection Toolbox 4 library: every library component – data access, criteria and classifi...
Definition data_accessor.hpp:80
void notify(const std::string msg)
Prints msg followed by a newline via syncout::print(); a no-op unless the preprocessor macro DEBUG is...
Definition global.hpp:112
Defines interface for implementations of one selection step in sequential search type of methods.
Copyright © 2000–present ÚTIA, Institute of Information Theory and Automation of the Czech Academy of Sciences · Contacts · This site sets no cookies and uses no analytics.