1#ifndef FSTCLASSIFIEREXTERN_H
2#define FSTCLASSIFIEREXTERN_H
145template<
class RETURNTYPE,
typename DATATYPE,
typename REALTYPE,
typename IDXTYPE,
typename DIMTYPE,
class SUBSET,
class DATAACCESSOR>
146class Classifier_Extern :
public Clonable_Impl<Classifier_Extern<RETURNTYPE,DATATYPE,REALTYPE,IDXTYPE,DIMTYPE,SUBSET,DATAACCESSOR>,Classifier<RETURNTYPE,DIMTYPE,SUBSET,DATAACCESSOR> > {
188 virtual std::ostream&
print(std::ostream& os)
const override {os <<
"Classifier_Extern(cmd=\"" <<
_bridge.get_command() <<
"\")";
return os;}
204 notify(
"Classifier_Extern copy-constructor.");
218 void send_row(
const DIMTYPE label_or_none,
const bool with_label,
const PPattern &pattern);
235template<
class RETURNTYPE,
typename DATATYPE,
typename REALTYPE,
typename IDXTYPE,
typename DIMTYPE,
class SUBSET,
class DATAACCESSOR>
238 notify(
"Classifier_Extern::initialize().");
240 assert(da->getNoOfFeatures()>0);
241 if(da->getNoOfClasses()<2)
throw fst_error(
"Classifier_Extern requires at least 2 classes");
242 if(
_bridge.get_command().empty())
throw fst_error(
"Classifier_Extern: no command set (see --extern-cmd)");
251template<
class RETURNTYPE,
typename DATATYPE,
typename REALTYPE,
typename IDXTYPE,
typename DIMTYPE,
class SUBSET,
class DATAACCESSOR>
254 std::FILE *out=
_bridge.to_child();
256 if(with_label) {std::snprintf(buf,
sizeof(buf),
"%ld",(
long)label_or_none); std::fputs(buf,out);}
259 std::snprintf(buf,
sizeof(buf),
"%.17g",(
double)pattern[
_index[f]]);
260 if(with_label || f>0) std::fputc(
' ',out);
263 if(std::fputc(
'\n',out)==EOF)
267template<
class RETURNTYPE,
typename DATATYPE,
typename REALTYPE,
typename IDXTYPE,
typename DIMTYPE,
class SUBSET,
class DATAACCESSOR>
273 const char *s=line.c_str();
275 const long v=std::strtol(s,&end,10);
276 if(end==s || *end!=
'\0')
277 {
_bridge.shutdown_process();
throw fst_error(
"Classifier_Extern: '"+
_bridge.get_command()+
"' returned a non-numeric prediction line: '"+line+
"'");}
281template<
class RETURNTYPE,
typename DATATYPE,
typename REALTYPE,
typename IDXTYPE,
typename DIMTYPE,
class SUBSET,
class DATAACCESSOR>
284 notify(
"Classifier_Extern::train().");
287 assert(
_classes==da->getNoOfClasses());
288 assert(
_features==da->getNoOfFeatures());
289 assert(sub->get_n_raw()==da->getNoOfFeatures());
300 unsigned long long n=0;
301 {
typename DATAACCESSOR::PPattern p; IDXTYPE s,i; (void)p; (void)i;
302 for(DIMTYPE c=0;c<
_classes;c++) {da->setClass(c);
for(
const auto &blk : da->blocks(
TRAIN)) {s=blk.size; n+=(
unsigned long long)s;}}}
303 if(n==0)
return false;
306 typename DATAACCESSOR::PPattern p;
308 const DIMTYPE stride=da->getNoOfFeatures();
312 for(
const auto &blk : da->blocks(
TRAIN))
for(i=0,p=blk.data,s=blk.size;i<s;i++)
313 send_row(c,
true,&p[(std::size_t)i*stride]);
316 const std::string resp=
_bridge.read_line();
317 if(resp!=
"OK")
throw fst_error(
"Classifier_Extern: '"+
_bridge.get_command()+
"' rejected TRAIN: "+resp);
321template<
class RETURNTYPE,
typename DATATYPE,
typename REALTYPE,
typename IDXTYPE,
typename DIMTYPE,
class SUBSET,
class DATAACCESSOR>
330 if(v<0 || v>=(
long)
_classes) {
_bridge.shutdown_process();
return false;}
335template<
class RETURNTYPE,
typename DATATYPE,
typename REALTYPE,
typename IDXTYPE,
typename DIMTYPE,
class SUBSET,
class DATAACCESSOR>
343 unsigned long long m=0;
344 {IDXTYPE s;
for(DIMTYPE c=0;c<
_classes;c++) {da->setClass(c);
for(
const auto &blk : da->blocks(
TEST)) {s=blk.size; m+=(
unsigned long long)s;}}}
345 if(m==0)
return false;
347 typename DATAACCESSOR::PPattern p;
349 const DIMTYPE stride=da->getNoOfFeatures();
353 for(
const auto &blk : da->blocks(
TEST))
for(i=0,p=blk.data,s=blk.size;i<s;i++)
354 send_row(0,
false,&p[(std::size_t)i*stride]);
358 predictions.reserve((std::size_t)m);
359 for(
unsigned long long k=0;k<m;k++)
369 predictions.push_back((DIMTYPE)v);
374template<
class RETURNTYPE,
typename DATATYPE,
typename REALTYPE,
typename IDXTYPE,
typename DIMTYPE,
class SUBSET,
class DATAACCESSOR>
377 notify(
"Classifier_Extern::test().");
378 std::vector<DIMTYPE> pred;
381 unsigned long long count=0, correct=0;
383 for(DIMTYPE c_test=0;c_test<
_classes;c_test++)
385 da->setClass(c_test);
386 for(
const auto &blk : da->blocks(
TEST))
for(i=0,s=blk.size;i<s;i++)
388 if(pred[count]==c_test) correct++;
392 assert(count==pred.size());
393 if(count==0)
return false;
394 result=(RETURNTYPE)correct/(RETURNTYPE)count;
398template<
class RETURNTYPE,
typename DATATYPE,
typename REALTYPE,
typename IDXTYPE,
typename DIMTYPE,
class SUBSET,
class DATAACCESSOR>
402 notify(
"Classifier_Extern::test_confusion().");
403 std::vector<DIMTYPE> pred;
406 confusion.assign((std::size_t)
_classes*(std::size_t)
_classes,(RETURNTYPE)0.0);
407 unsigned long long count=0;
409 for(DIMTYPE c_test=0;c_test<
_classes;c_test++)
411 da->setClass(c_test);
412 for(
const auto &blk : da->blocks(
TEST))
for(i=0,s=blk.size;i<s;i++)
414 confusion[(std::size_t)c_test*(std::size_t)
_classes+(std::size_t)pred[count]]+=1.0;
418 assert(count==pred.size());
Bridge classifier delegating training and prediction to a user-supplied external command.
Definition classifier_extern.hpp:146
DIMTYPE _subfeatures
d = current subset size
Definition classifier_extern.hpp:210
std::shared_ptr< SUBSET > PSubset
shared pointer to the feature subset being trained/evaluated
Definition classifier_extern.hpp:151
virtual bool classify(DIMTYPE &cls, const PPattern &pattern) override
Definition classifier_extern.hpp:322
DIMTYPE _classes
class count, set by initialize()
Definition classifier_extern.hpp:208
DATAACCESSOR::PPattern PPattern
one data sample as exposed by DATAACCESSOR
Definition classifier_extern.hpp:152
void send_row(const DIMTYPE label_or_none, const bool with_label, const PPattern &pattern)
Writes one %.17g-formatted data row over the selected subset to the child's stdin....
Definition classifier_extern.hpp:252
DIMTYPE _features
raw (full, unnarrowed) feature count, set by initialize()
Definition classifier_extern.hpp:209
bool run_test_block(std::vector< DIMTYPE > &predictions, const PDataAccessor da)
Runs one batched TEST round-trip over the designated test part, shared by test()/test_confusion(): se...
Definition classifier_extern.hpp:336
Classifier< RETURNTYPE, DIMTYPE, SUBSET, DATAACCESSOR > parent
the immediate abstract base
Definition classifier_extern.hpp:148
Clonable_Impl< Classifier_Extern, parent > parent_impl
implements clone() via the copy-constructor below
Definition classifier_extern.hpp:149
virtual bool train(const PDataAccessor da, const PSubset sub) override
Streams the designated training part as one TRAIN block: buffers the subset index,...
Definition classifier_extern.hpp:282
std::shared_ptr< DATAACCESSOR > PDataAccessor
shared pointer to the data accessor supplying train/test blocks
Definition classifier_extern.hpp:150
const std::string & get_command() const
returns the configured command line
Definition classifier_extern.hpp:157
void initialize(const PDataAccessor da)
Records the data shape and allocates the index buffer. Must be called before train()....
Definition classifier_extern.hpp:236
void set_command(const std::string &cmd)
sets the external command line (--extern-cmd); the bridge asserts it is not already running
Definition classifier_extern.hpp:156
virtual bool test(RETURNTYPE &result, const PDataAccessor da) override
Definition classifier_extern.hpp:375
std::vector< DIMTYPE > _index
subset position -> raw feature index (first d entries valid)
Definition classifier_extern.hpp:211
Classifier_Extern(const Classifier_Extern &ce)
Copy-constructor backing clone(): copies shape/config (class and feature counts, the narrowing _index...
Definition classifier_extern.hpp:196
virtual std::ostream & print(std::ostream &os) const override
writes a human-readable identification of the object; base default writes nothing
Definition classifier_extern.hpp:188
long parse_prediction(const std::string &line)
Strict full-line numeric parse of one predicted class index: the ENTIRE line must be consumed by strt...
Definition classifier_extern.hpp:268
virtual bool test_confusion(std::vector< RETURNTYPE > &confusion, DIMTYPE &classes, const PDataAccessor da) override
Definition classifier_extern.hpp:399
Extern_Bridge _bridge
persistent child process + line I/O (per instance; never shared by clones)
Definition classifier_extern.hpp:207
abstract class, defines interface for classifier implementations (mainly to be used in wrappers)
Definition classifier.hpp:97
CRTP mixin implementing the Clonable protocol for a concrete class.
Definition clonable.hpp:184
Persistent-child-process line-protocol plumbing shared by the external-tool bridges: Classifier_Exter...
Definition extern_bridge.hpp:105
const std::string & get_command() const
returns the configured command line
Definition extern_bridge.hpp:113
FST4 specific error passing class.
Definition error.hpp:61
Defines interface for classifier implementations.
Defines interface for classes that may need to get cloned.
FST4 specific error passing class.
Persistent-child-process line-protocol plumbing shared by the external-tool bridges (Classifier_Exter...
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
@ TEST
the split's test part
Definition data_accessor.hpp:86
@ TRAIN
the split's training part
Definition data_accessor.hpp:85