Feature Selection Toolbox FST4
UTIA · Czech Academy of Sciences
Loading...
Searching...
No Matches
search_monte_carlo.hpp
Go to the documentation of this file.
1#ifndef FSTSEARCHMONTECARLO_H
2#define FSTSEARCHMONTECARLO_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 <ctime>
54#include "error.hpp"
55#include "global.hpp"
56#include "stopwatch.hpp"
57#include "search.hpp"
58#include "result_tracker.hpp"
61
62/*============== Template parameter type naming conventions ==============
63--------- Numeric types: -------------------------------------------------
64DATATYPE - data sample values - usually real numbers (but may be integers
65 in text processing etc.)
66REALTYPE - must be real numbers - for representing intermediate results of
67 calculations like mean, covariance etc.
68IDXTYPE - index values for enumeration of data samples - (nonnegative) integers,
69 extent depends on numbers of samples in data
70DIMTYPE - index values for enumeration of features (dimensions), or classes (not
71 class sizes) - (nonnegative) integers, usually lower extent than IDXTYPE,
72 but be aware of expressions like _classes*_features*_features !
73 in linearized representations of feature matrices for all classes
74BINTYPE - feature selection marker type - represents ca. <10 different feature
75 states (selected, deselected, sel./desel. temporarily 1st nested loop, 2nd...)
76RETURNTYPE - criterion value: real value, but may be extended in future to support
77 multiple values
78--------- Class types: ---------------------------------------------------
79SUBSET - class of class type Subset
80CLASSIFIER - class implementing interface defined in abstract class Classifier
81EVALUATOR - class implementing interface defined in abstract class Sequential_Step
82DISTANCE - class implementing interface defined in abstract class Distance
83DATAACCESSOR - class implementing interface defined in abstract class Data_Accessor
84INTERVALCONTAINER - class of class type Data_Intervaller
85CONTAINER - STL container of class type Data_Interval
86========================================================================== */
87
88namespace FST {
89
110
111template<class RETURNTYPE, typename DIMTYPE, class SUBSET, class CRITERION>
112class Search_Monte_Carlo : public Search<RETURNTYPE,DIMTYPE,SUBSET,CRITERION>{
113public:
114 typedef Search<RETURNTYPE,DIMTYPE,SUBSET,CRITERION> parent;
115 typedef std::shared_ptr<CRITERION> PCriterion;
116 typedef std::shared_ptr<SUBSET> PSubset;
118 typedef std::shared_ptr<EVALUATORENGINE> PEvaluatorEngine;
120 Search_Monte_Carlo(const unsigned long long trials_limit=1000, const unsigned long time_limit=0, const unsigned int time_limit_check_freq=1, PEvaluatorEngine engine=PEvaluatorEngine()):Search<RETURNTYPE,DIMTYPE,SUBSET,CRITERION>(),_engine(engine) {
122 notify("Search_Monte_Carlo constructor."); set_stopping_condition(trials_limit,time_limit,time_limit_check_freq); reset_cardinality_randomization();
123 }
124 virtual ~Search_Monte_Carlo() {notify("Search_Monte_Carlo destructor.");}
125
126 // NOTE: crit is expected to be already initialize()d before use here
128 virtual bool search(const DIMTYPE target_d, RETURNTYPE &result, const PSubset sub, const PCriterion crit, std::ostream& os=std::cout) override;
129
131 void set_stopping_condition(const unsigned long long trials_limit=1000, const unsigned long time_limit=0, const unsigned int time_limit_check_freq=100) {if(trials_limit==0 && time_limit==0) {_trials_limit=1000; _time_limit=0;} else {_trials_limit=trials_limit; _time_limit=time_limit;} if(time_limit_check_freq==0) _time_limit_check_freq=100; else _time_limit_check_freq=time_limit_check_freq; }
132
133 // set the way of random subset (size) generation
134 void set_cardinality_randomization(const DIMTYPE d_from, const DIMTYPE d_to) {if(d_from>0 && d_from<=d_to) {_d_from=d_from; _d_to=d_to;} else {_d_from=_d_to=0;}}
135 void set_cardinality_randomization(const float d_prob) {if(d_prob>0.0 && d_prob<1.0) _d_prob=d_prob; else _d_prob=0.0;}
137
138 virtual std::ostream& print(std::ostream& os) const override;
139
140protected:
142 unsigned long _time_limit;
143 unsigned long long _trials_limit;
145 DIMTYPE _d_from;
146 DIMTYPE _d_to;
147 float _d_prob;
148};
149
150template<class RETURNTYPE, typename DIMTYPE, class SUBSET, class CRITERION>
152{
153 if(_engine->is_threaded()) {
154 os << "Random search [Search_Monte_Carlo(max_threads="<<_engine->get_max_threads();
155 if(_trials_limit>0) os << ", maxtrials="<<_trials_limit;
156 if(_time_limit>0) os<<", seconds="<<_time_limit;
157 if(_d_prob>0.0) os<<", d_prob="<<_d_prob;
158 else os<<", d_from="<<_d_from<<", d_to="<<_d_to;
159 os<<")";
160 } else {
161 os << "Random search [Search_Monte_Carlo(";
162 if(_trials_limit>0) os << "maxtrials="<<_trials_limit<<", ";
163 if(_time_limit>0) os<<"seconds="<<_time_limit<<", ";
164 if(_d_prob>0.0) os<<"d_prob="<<_d_prob;
165 else os<<"d_from="<<_d_from<<", d_to="<<_d_to;
166 os<<")";
167 }
168 if(parent::result_tracker_active()) os << " with " << *parent::_tracker;
169 os<<"]";
170 return os;
171}
172
173template<class RETURNTYPE, typename DIMTYPE, class SUBSET, class CRITERION>
174bool Search_Monte_Carlo<RETURNTYPE,DIMTYPE,SUBSET,CRITERION>::search(const DIMTYPE target_d, RETURNTYPE &result, const PSubset sub, const PCriterion crit, std::ostream& os) // returns found subset + criterion value
175{
176 StopWatch swatch;
177 assert(sub);
178 assert(crit);
179 assert(_engine);
180 const DIMTYPE n=sub->get_n();
181 assert(target_d<n);
182
183 bool track=parent::result_tracker_active(); if(track) parent::_tracker->set_output_detail(parent::get_output_detail());
184
186 msgbuf sos;
187 sos << "---------------------------------------" << std::endl;
188 sos << "Starting " << *this << std::endl;
189 sos << "with Criterion: " << *crit << std::endl;
190 if(target_d==0) sos << "Subset size to be optimized." << std::endl; else sos << "Target subset size set to: " << target_d << std::endl;
191 sos << std::endl << std::flush;
192 this->report(os,sos);
193 }
194 assert(_trials_limit!=0 || _time_limit!=0);
195 assert(_time_limit_check_freq>0);
196 unsigned long long _trials=0; // the printed twin of the engine's generation ordinal - same 64-bit domain
197 unsigned long _time=0;
198 // the random subset size range used when target_d==0 and no inclusion probability is set:
199 // the configured [_d_from,_d_to] clamped into [1,n]; with no range configured it is the full [1,n]
200 DIMTYPE _d_from_tmp=_d_from, _d_to_tmp=_d_to;
201 if(_d_to_tmp<1 || _d_to_tmp>n) _d_to_tmp=n;
202 if(_d_from_tmp<1) _d_from_tmp=1; else if(_d_from_tmp>_d_to_tmp) _d_from_tmp=_d_to_tmp;
203 assert(_d_from_tmp>=1 && _d_from_tmp<=_d_to_tmp && _d_to_tmp<=n);
204
205 // random candidates are generated until the stopping condition (trials and/or
206 // time limit) is met; both engines call the generator on the MASTER thread only,
207 // so the random draws all come from one fst_rand stream (same seed = same
208 // candidate sequence, threaded or not) and the trial counter needs no synchronization
209 StopWatch *psw=&swatch;
210 typename EVALUATORENGINE::Generator generator=[this,psw,&_trials,&_time,_d_from_tmp,_d_to_tmp,target_d](SUBSET &cand)->bool {
211 if( (_trials_limit!=0 && _trials>=_trials_limit) || (_time_limit!=0 && _time>=_time_limit) ) return false;
212 if(target_d==0) {
213 if(_d_prob>0.0) do {cand.make_random_subset(_d_prob);} while(cand.get_d()==0);
214 else cand.make_random_subset(_d_from_tmp,_d_to_tmp);
215 } else cand.make_random_subset(target_d);
216 ++_trials;
217 if(_trials%_time_limit_check_freq==0) _time=(unsigned long)psw->time_elapsed();
218 return true;
219 };
220
221 typename EVALUATORENGINE::BetterPredicate better=[](const RETURNTYPE val, const PSubset &cand, const RETURNTYPE bestval, const PSubset &bestsub)->bool {
222 return val>bestval || (val==bestval && cand->get_d()<bestsub->get_d());
223 };
224
225 typename EVALUATORENGINE::BestCallback on_best;
227 std::ostream *pos=&os;
228 // both engines fire this on the master in generation order (tidx==-1) with the
229 // candidate's generation ordinal == the trial index, threaded or not
230 on_best=[this,psw,pos](const int /*tidx*/, const unsigned long long ordinal, const RETURNTYPE val, const PSubset &bsub) {
231 msgbuf sos;
232 sos << "new MAXCRIT="<<val<< ", trial=" << ordinal << ", " << *bsub << std::endl << *psw << std::endl << std::endl << std::flush;
233 this->report_solution(*pos,val,*bsub,sos);
234 };
235 }
236
237 if(!_engine->evaluate_stream(generator, crit, track? parent::_tracker : typename parent::PResultTracker(), better, on_best, result, sub)) return false;
238
240 msgbuf sos;
241 sos << "......................................." << std::endl;
242 if(_engine->is_threaded()) sos << "Search_Monte_Carlo_Threaded() search finished after "<<_trials<<" trials. " << swatch << std::endl;
243 else sos << "Search_Monte_Carlo() search finished after "<<_trials<<" trials. " << swatch << std::endl;
244 sos << "Search result: "<< std::endl << *sub << std::endl << "Criterion value: " << result << std::endl << std::endl << std::flush;
245 this->report(os,sos);
246 }
247 return true;
248}
249
250} // namespace
251#endif // FSTSEARCHMONTECARLO_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< bool(SUBSET &)> Generator
fills sub with the next candidate, returns false when no candidate remains (in the threaded implement...
Definition candidate_evaluator.hpp:92
std::function< bool(const RETURNTYPE, const PSubset &, const RETURNTYPE, const PSubset &)> BetterPredicate
returns true if (value,subset) is better than (best value,best subset) - encodes per-search tie-break...
Definition candidate_evaluator.hpp:99
std::function< void(const int, const unsigned long long, const RETURNTYPE, const PSubset &)> BestCallback
Definition candidate_evaluator.hpp:97
Repeatedly samples random subsets to eventually yield the one with highest criterion value.
Definition search_monte_carlo.hpp:112
unsigned int _time_limit_check_freq
number of trials before next time check
Definition search_monte_carlo.hpp:144
Candidate_Evaluator< RETURNTYPE, DIMTYPE, SUBSET, CRITERION > EVALUATORENGINE
the injected evaluation-strategy interface (sequential in-line or thread-pooled)
Definition search_monte_carlo.hpp:117
std::shared_ptr< CRITERION > PCriterion
shared pointer to the criterion the search optimizes
Definition search_monte_carlo.hpp:115
void reset_cardinality_randomization()
clears both ways of randomizing the subset size (the constructor calls this); with neither of them in...
Definition search_monte_carlo.hpp:136
virtual bool search(const DIMTYPE target_d, RETURNTYPE &result, const PSubset sub, const PCriterion crit, std::ostream &os=std::cout) override
samples random subsets of target_d features (of randomized size if target_d==0: from the configured r...
Definition search_monte_carlo.hpp:174
std::shared_ptr< SUBSET > PSubset
shared pointer to a feature subset
Definition search_monte_carlo.hpp:116
float _d_prob
active d_prob must be from (0,1]; generates random subset of random size where the mean size over a s...
Definition search_monte_carlo.hpp:147
Search_Monte_Carlo(const unsigned long long trials_limit=1000, const unsigned long time_limit=0, const unsigned int time_limit_check_freq=1, PEvaluatorEngine engine=PEvaluatorEngine())
engine defaults to sequential in-line evaluation if not supplied; see set_stopping_condition() for tr...
Definition search_monte_carlo.hpp:120
void set_cardinality_randomization(const DIMTYPE d_from, const DIMTYPE d_to)
generate subset size first from [d_from,d_to], then randomly choose exactly that number of features
Definition search_monte_carlo.hpp:134
std::shared_ptr< EVALUATORENGINE > PEvaluatorEngine
Definition search_monte_carlo.hpp:118
void set_cardinality_randomization(const float d_prob)
for each feature roll the dice and select it with probability d_prob
Definition search_monte_carlo.hpp:135
DIMTYPE _d_from
lower bound of the random subset size range; see set_cardinality_randomization(const DIMTYPE,...
Definition search_monte_carlo.hpp:145
PEvaluatorEngine _engine
injected evaluation strategy (sequential-inline or thread-pooled); defaulted in the constructor if no...
Definition search_monte_carlo.hpp:141
void set_stopping_condition(const unsigned long long trials_limit=1000, const unsigned long time_limit=0, const unsigned int time_limit_check_freq=100)
set maximum number of random trials or maximum time in seconds or both; trials_limit and time_limit b...
Definition search_monte_carlo.hpp:131
Search< RETURNTYPE, DIMTYPE, SUBSET, CRITERION > parent
base class alias
Definition search_monte_carlo.hpp:114
virtual std::ostream & print(std::ostream &os) const override
writes a human-readable identification of the search and its configuration; base default writes nothi...
Definition search_monte_carlo.hpp:151
unsigned long _time_limit
max time allowed to be spent in seconds
Definition search_monte_carlo.hpp:142
DIMTYPE _d_to
upper bound of the random subset size range
Definition search_monte_carlo.hpp:146
unsigned long long _trials_limit
max no of candidates evaluated (64-bit: counts candidates, see the LLP64 note on Candidate_Evaluator:...
Definition search_monte_carlo.hpp:143
bool output_normal() const
true unless output detail is SILENT
Definition search.hpp:159
void report(std::ostream &os, const msgbuf &m) const
delivers one pre-formatted progress message: to the observer if attached, otherwise as syncout text t...
Definition search.hpp:170
bool result_tracker_active() const
true if a result tracker was assigned via enable_result_tracking() and not since disabled
Definition search.hpp:155
OutputDetail get_output_detail() const
the currently configured output detail level
Definition search.hpp:158
std::shared_ptr< Result_Tracker< RETURNTYPE, SUBSET > > PResultTracker
shared pointer to the result tracker enabled via enable_result_tracking()
Definition search.hpp:128
PResultTracker _tracker
the assigned result tracker, or null (see enable_result_tracking()/result_tracker_active())
Definition search.hpp:179
void report_solution(std::ostream &os, const RETURNTYPE value, const SUBSET &sub, const msgbuf &m) const
like report(), for sites announcing a new (sub-)solution; fires on_solution instead
Definition search.hpp:175
Simple stopwatch to measure run time of search algorithms.
Definition stopwatch.hpp:92
double time_elapsed() const
Returns the number of whole seconds elapsed since construction (wall-clock via time(),...
Definition stopwatch.hpp:99
Message accumulator for Search::report() - collects one progress message exactly as an std::ostringst...
Definition search.hpp:87
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.
Defines interface for search method implementations.
Simple tool to measure run time.
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.