Feature Selection Toolbox FST4
UTIA · Czech Academy of Sciences
Loading...
Searching...
No Matches
search_branch_and_bound_partial_prediction.hpp
Go to the documentation of this file.
1#ifndef FSTSEARCHBRANCHANDBOUNDPARTIALPREDICTION_H
2#define FSTSEARCHBRANCHANDBOUNDPARTIALPREDICTION_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>
54#include "error.hpp"
55#include "global.hpp"
56#include "result_tracker.hpp"
57
58/*============== Template parameter type naming conventions ==============
59--------- Numeric types: -------------------------------------------------
60DATATYPE - data sample values - usually real numbers (but may be integers
61 in text processing etc.)
62REALTYPE - must be real numbers - for representing intermediate results of
63 calculations like mean, covariance etc.
64IDXTYPE - index values for enumeration of data samples - (nonnegative) integers,
65 extent depends on numbers of samples in data
66DIMTYPE - index values for enumeration of features (dimensions), or classes (not
67 class sizes) - (nonnegative) integers, usually lower extent than IDXTYPE,
68 but be aware of expressions like _classes*_features*_features !
69 in linearized representations of feature matrices for all classes
70BINTYPE - feature selection marker type - represents ca. <10 different feature
71 states (selected, deselected, sel./desel. temporarily 1st nested loop, 2nd...)
72RETURNTYPE - criterion value: real value, but may be extended in future to support
73 multiple values
74--------- Class types: ---------------------------------------------------
75SUBSET - class of class type Subset
76CLASSIFIER - class implementing interface defined in abstract class Classifier
77EVALUATOR - class implementing interface defined in abstract class Sequential_Step
78DISTANCE - class implementing interface defined in abstract class Distance
79DATAACCESSOR - class implementing interface defined in abstract class Data_Accessor
80INTERVALCONTAINER - class of class type Data_Intervaller
81CONTAINER - STL container of class type Data_Interval
82========================================================================== */
83
84namespace FST {
85
111
112template<class RETURNTYPE, typename DIMTYPE, class SUBSET, class CRITERION, class PREDICTOR>
113class Search_Branch_And_Bound_Partial_Prediction : public Search_Branch_And_Bound<RETURNTYPE,DIMTYPE,SUBSET,CRITERION>{
114public:
117 typedef typename parent::PSubset PSubset;
118 typedef typename parent::PNode PNode;
119 typedef typename parent::Node Node;
120 typedef typename parent::NodeType NodeType;
122 explicit Search_Branch_And_Bound_Partial_Prediction(PEvaluatorEngine engine=PEvaluatorEngine()):Search_Branch_And_Bound<RETURNTYPE,DIMTYPE,SUBSET,CRITERION>(engine) {notify("Search_Branch_And_Bound_Partial_Prediction constructor.");}
123 virtual ~Search_Branch_And_Bound_Partial_Prediction() {notify("Search_Branch_And_Bound_Partial_Prediction destructor.");}
124
125 // for search() implementation see parent class
126
128 virtual std::ostream& print(std::ostream& os) const override {
129 if(parent::get_engine()->is_threaded()) os << "Branch & Bound with Partial Prediction (BBPP) [Search_Branch_And_Bound_Partial_Prediction(threads="<<parent::get_engine()->get_max_threads()<<") with " << _predictor << "]";
130 else os << "Branch & Bound with Partial Prediction (BBPP) [Search_Branch_And_Bound_Partial_Prediction() with " << _predictor << "]";
131 return os;
132 };
133protected:
134 PREDICTOR _predictor;
135
136 // the following may be overriden in descendant Branch and Bound specialization classes
137 virtual void initialize(const DIMTYPE d, const DIMTYPE n, const PCriterion crit) override {_predictor.initialize(n);}
138 virtual void leaf_result(const DIMTYPE feature, const RETURNTYPE value) override;
142 virtual void pre_evaluate_availables() override;
147 virtual void post_process_tree_level() override;
151 virtual bool cut_possible() override;
152};
153
154template<class RETURNTYPE, typename DIMTYPE, class SUBSET, class CRITERION, class PREDICTOR>
156{
157 // conditionally update prediction info: the base class fires this hook after each leaf's
158 // bound update, in leaf order, so the parent node's value is the right reference point
159 Node &parentnode=parent::get_parent_node();
160 if(parentnode.type==parent::COMPUTED) _predictor.learn(feature,parentnode.value-value);
161}
162
163template<class RETURNTYPE, typename DIMTYPE, class SUBSET, class CRITERION, class PREDICTOR>
165{
166 assert(parent::get_criterion());
167 assert(parent::get_engine());
168 const PSubset &currentset=parent::get_currentset(); assert(currentset);
169 Node &parentnode=parent::get_parent_node(); assert(parentnode.type==parent::COMPUTED);
170
171 // pass 1 (master thread): decide predict-vs-compute for every available feature. Deciding
172 // for all of them upfront gives the same decisions as deciding one at a time while
173 // evaluating, because predictor state is per-feature (the PREDICTOR contract) and each
174 // feature is decided once - so the outcome does not depend on the evaluation engine
175 PNode avail;
176 RETURNTYPE val;
177 DIMTYPE to_compute=0;
178 for(bool got=this->getFirstAvailable(avail);got;got=this->getNextAvailable(avail))
179 {
180 if(_predictor.predict(avail->feature,val)) { //value could be predicted
181 avail->value=parentnode.value-val;
182 avail->type=parent::PREDICTED;
183 } else { //value could not be predicted
184 avail->type=parent::UNKNOWN; // computed by the engine batch below
185 ++to_compute;
186 }
187 }
188 if(to_compute==0) return;
189
190 // pass 2: batch-evaluate the non-predictable features through the engine; the per-result
191 // callback fires in add-order under both engine implementations, so node values are
192 // assigned and prediction contrasts learned in the same order either way
193 typename parent::EVALUATORENGINE::ResultCallback on_result=[this,&parentnode](const RETURNTYPE value, const PSubset&, const DIMTYPE feat) {
194 PNode node;
195 if(this->getAvailable(feat,node)) {
196 node->value=value;
197 node->type=parent::COMPUTED;
198 // conditionally update prediction info
199 if(parentnode.type==parent::COMPUTED) _predictor.learn(feat,parentnode.value-value);
200 }
201 };
202 parent::get_engine()->initialize(parent::get_criterion(),parent::get_n(),on_result);
203 for(bool got=this->getFirstAvailable(avail);got;got=this->getNextAvailable(avail))
204 {
205 if(avail->type!=parent::PREDICTED) {
206 assert(currentset->selected_raw(avail->feature));
207 currentset->deselect_raw(avail->feature);
208 if(!parent::get_engine()->add_candidate(currentset,avail->feature)) throw FST::fst_error("Criterion evaluation failure.");
209 currentset->select_raw(avail->feature);
210 }
211 }
212 // collect() is where a worker's exception is rethrown; a false return means some
213 // evaluate() failed and no callbacks fired at all, which would leave nodes at UNKNOWN and
214 // poison the level sort-in - so it must be an error, not a silent continuation
215 if(!parent::get_engine()->collect()) throw FST::fst_error("Criterion evaluation failure.");
216}
217
218template<class RETURNTYPE, typename DIMTYPE, class SUBSET, class CRITERION, class PREDICTOR>
220{
221 assert(parent::get_criterion());
222 assert(parent::get_engine());
223 const PSubset &currentset=parent::get_currentset(); assert(currentset);
224 Node &parentnode=parent::get_parent_node(); assert(parentnode.type==parent::PREDICTED || parentnode.type==parent::COMPUTED);
225
226 // supply the true criterion value of the level's chosen PREDICTED nodes (partial
227 // prediction: predictions only order the level, the tree path is exact) - batched
228 // through the engine. Results map back to their nodes by submission order: the
229 // per-result callback fires in add-order under both engine implementations, and the
230 // submitted vector is fully built before the first add_candidate, which matters because
231 // the sequential engine fires callbacks synchronously inside add_candidate. The list
232 // node pointers stay valid throughout (nothing is inserted into or erased from the level
233 // during the batch), and prediction contrasts are learned in the same order either way
234 PNode nod;
235 std::vector<PNode> submitted;
236 for(bool got=this->getFirstNode(nod);got;got=this->getNextNode(nod))
237 if(nod->type!=parent::COMPUTED) submitted.push_back(nod);
238 if(submitted.empty()) return;
239
240 DIMTYPE done=0;
241 typename parent::EVALUATORENGINE::ResultCallback on_result=[this,&parentnode,&submitted,&done](const RETURNTYPE value, const PSubset&, const DIMTYPE feat) {
242 PNode node=submitted[done++];
243 assert(node->feature==feat);
244 node->value=value;
245 node->type=parent::COMPUTED;
246 // conditionally update prediction info
247 if(parentnode.type==parent::COMPUTED) _predictor.learn(feat,parentnode.value-value);
248 };
249 parent::get_engine()->initialize(parent::get_criterion(),(DIMTYPE)submitted.size(),on_result);
250 for(PNode snod : submitted)
251 {
252 assert(currentset->selected_raw(snod->feature));
253 currentset->deselect_raw(snod->feature);
254 if(!parent::get_engine()->add_candidate(currentset,snod->feature)) throw FST::fst_error("Criterion evaluation failure.");
255 currentset->select_raw(snod->feature);
256 }
257 // a failed batch must not be allowed to leave nodes without a true value on the tree path
258 if(!parent::get_engine()->collect()) throw FST::fst_error("Criterion evaluation failure.");
259}
260
261template<class RETURNTYPE, typename DIMTYPE, class SUBSET, class CRITERION, class PREDICTOR>
263{
265 Node &currentnode=parent::get_current_node(); assert(currentnode.type==parent::COMPUTED);
266 if(currentnode.value<=parent::get_bound_value()) { // BBPP ensures that the value must have been COMPUTED by now
267 return true;
268 }
269 }
270 return false;
271}
272
273} // namespace
274#endif // FSTSEARCHBRANCHANDBOUNDPARTIALPREDICTION_H ///:~
Interface for Implementations of Prediction Mechanism in Fast Branch & Bound and Branch & Bound with ...
Implements Branch and Bound with Partial Prediction (BBPP) method, i.e., with predicted node ordering...
Definition search_branch_and_bound_partial_prediction.hpp:113
Search_Branch_And_Bound< RETURNTYPE, DIMTYPE, SUBSET, CRITERION > parent
base class alias
Definition search_branch_and_bound_partial_prediction.hpp:115
parent::PEvaluatorEngine PEvaluatorEngine
shared pointer to the injected evaluation-strategy engine
Definition search_branch_and_bound_partial_prediction.hpp:121
parent::PNode PNode
pointer to a search-tree Node, see Search_Branch_And_Bound
Definition search_branch_and_bound_partial_prediction.hpp:118
virtual void initialize(const DIMTYPE d, const DIMTYPE n, const PCriterion crit) override
resets the prediction mechanism for a feature space of n features; nothing else needs setting up for ...
Definition search_branch_and_bound_partial_prediction.hpp:137
parent::Node Node
search-tree node record (feature, value, type, valid), see Search_Branch_And_Bound
Definition search_branch_and_bound_partial_prediction.hpp:119
parent::PCriterion PCriterion
shared pointer to the criterion the search optimizes
Definition search_branch_and_bound_partial_prediction.hpp:116
virtual void leaf_result(const DIMTYPE feature, const RETURNTYPE value) override
Definition search_branch_and_bound_partial_prediction.hpp:155
PREDICTOR _predictor
the prediction mechanism instance (PREDICTOR type parameter, e.g. Branch_And_Bound_Predictor_Averagin...
Definition search_branch_and_bound_partial_prediction.hpp:134
virtual void pre_evaluate_availables() override
Assigns an ordering value to every available feature: predicted (parent value minus the predicted con...
Definition search_branch_and_bound_partial_prediction.hpp:164
virtual std::ostream & print(std::ostream &os) const override
Writes the algorithm's name together with the prediction mechanism in use, and the thread count when ...
Definition search_branch_and_bound_partial_prediction.hpp:128
parent::NodeType NodeType
UNKNOWN/RANDOM/PREDICTED/COMPUTED node-value provenance, see Search_Branch_And_Bound.
Definition search_branch_and_bound_partial_prediction.hpp:120
Search_Branch_And_Bound_Partial_Prediction(PEvaluatorEngine engine=PEvaluatorEngine())
engine forwarded to Search_Branch_And_Bound; defaults to sequential in-line evaluation if not supplie...
Definition search_branch_and_bound_partial_prediction.hpp:122
parent::PSubset PSubset
shared pointer to a feature subset
Definition search_branch_and_bound_partial_prediction.hpp:117
virtual bool cut_possible() override
Returns true when the current node's value does not exceed the current bound, so the whole sub-branch...
Definition search_branch_and_bound_partial_prediction.hpp:262
virtual void post_process_tree_level() override
Replaces the merely PREDICTED values of the nodes that made it into the new tree level by exact crite...
Definition search_branch_and_bound_partial_prediction.hpp:219
PSubset & get_currentset()
mutable accessor for _currentset, for use by descendant B&B variants' hooks
Definition search_branch_and_bound.hpp:198
Node & get_parent_node()
the node one level up (_tree[k-1].back()) whose feature removal defines the branch currently being fo...
Definition search_branch_and_bound.hpp:199
Node * PNode
pointer to a Node, as used by the getFirst.../getNext... accessors below
Definition search_branch_and_bound.hpp:142
bool getFirstNode(PNode &nod)
begins forward iteration (ascending by value, from _tree[k].begin()) over the current level's not-yet...
Definition search_branch_and_bound.hpp:190
PCriterion const & get_criterion() const
accessor for _criterion, for use by descendant B&B variants' hooks
Definition search_branch_and_bound.hpp:180
Search_Branch_And_Bound(PEvaluatorEngine engine=PEvaluatorEngine())
Constructs the search, optionally injecting a candidate-evaluation engine.
Definition search_branch_and_bound.hpp:121
DIMTYPE n
no. of all features
Definition search_branch_and_bound.hpp:176
Node & get_current_node()
the node at the current level k presently being visited (_tree[k].back()), i.e. about to be tested fo...
Definition search_branch_and_bound.hpp:200
PEvaluatorEngine const & get_engine() const
accessor for the injected evaluation strategy (sequential-inline or thread-pooled),...
Definition search_branch_and_bound.hpp:181
bool getAvailable(DIMTYPE idx, PNode &avail)
direct lookup of _available[idx] by feature index, regardless of its valid flag; returns false if idx...
Definition search_branch_and_bound.hpp:195
bool getFirstAvailable(PNode &avail)
begins iteration over _available in feature-index order, skipping withdrawn (invalid) entries,...
Definition search_branch_and_bound.hpp:193
bool getNextNode(PNode &nod)
advances the getFirstNode() iteration; returns false once the level's end is reached
Definition search_branch_and_bound.hpp:191
DIMTYPE d
no. of features to be selected
Definition search_branch_and_bound.hpp:177
std::shared_ptr< EVALUATORENGINE > PEvaluatorEngine
shared pointer to an EVALUATORENGINE, as accepted by the constructor and returned by get_engine()
Definition search_branch_and_bound.hpp:115
bool is_bound_valid() const
true once a valid bound has been established, see _boundvalid
Definition search_branch_and_bound.hpp:184
std::shared_ptr< SUBSET > PSubset
shared pointer to a feature subset
Definition search_branch_and_bound.hpp:113
bool getNextAvailable(PNode &avail)
advances the getFirstAvailable() iteration, again skipping invalid entries; returns false once exhaus...
Definition search_branch_and_bound.hpp:194
std::shared_ptr< CRITERION > PCriterion
shared pointer to the criterion under optimization
Definition search_branch_and_bound.hpp:112
NodeType
Marks how a Node's value was obtained: UNKNOWN = not yet assigned; RANDOM = reserved but currently un...
Definition search_branch_and_bound.hpp:134
DIMTYPE get_n() const
total number of features, see n
Definition search_branch_and_bound.hpp:187
RETURNTYPE get_bound_value() const
the current best (bound) criterion value; meaningful only once is_bound_valid()
Definition search_branch_and_bound.hpp:183
FST4 specific error passing class.
Definition error.hpp:61
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 classes that enable collecting multiple results.
Implements Branch and Bound template method as basis for more advanced B&B implementations.
Structure representing search tree node.
Definition search_branch_and_bound.hpp:136
RETURNTYPE value
the node's criterion value: exact once type==COMPUTED, an ordering estimate while type==PREDICTED,...
Definition search_branch_and_bound.hpp:138
DIMTYPE feature
the feature index this node represents removing from its ancestor set (meaningless in the single root...
Definition search_branch_and_bound.hpp:137
NodeType type
how value was obtained, see NodeType
Definition search_branch_and_bound.hpp:139
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.