1#ifndef FSTCLASSIFIERLINSVM_H
2#define FSTCLASSIFIERLINSVM_H
110template<
class RETURNTYPE,
typename DATATYPE,
typename REALTYPE,
typename IDXTYPE,
typename DIMTYPE,
class SUBSET,
class DATAACCESSOR>
111class Classifier_Linear_SVM :
public Clonable_Impl<Classifier_Linear_SVM<RETURNTYPE,DATATYPE,REALTYPE,IDXTYPE,DIMTYPE,SUBSET,DATAACCESSOR>,Classifier<RETURNTYPE,DIMTYPE,SUBSET,DATAACCESSOR> > {
142 virtual std::ostream&
print(std::ostream& os)
const override
143 {os <<
"Classifier_Linear_SVM(C=" <<
_C <<
", loss=" << (
_l2loss?
"l2":
"l1") <<
", max_iter=" <<
_max_iter <<
", tol=" <<
_tol <<
")";
return os;}
159 std::vector<REALTYPE>
_W;
162 std::vector<REALTYPE>
_Z;
163 std::vector<DIMTYPE>
_y;
167 void solve_dual(REALTYPE *w,
const DIMTYPE positive_class);
174template<
class RETURNTYPE,
typename DATATYPE,
typename REALTYPE,
typename IDXTYPE,
typename DIMTYPE,
class SUBSET,
class DATAACCESSOR>
177 notify(
"Classifier_Linear_SVM::initialize().");
179 assert(da->getNoOfFeatures()>0);
180 if(da->getNoOfClasses()<2)
throw fst_error(
"Classifier_Linear_SVM requires at least 2 classes");
187template<
class RETURNTYPE,
typename DATATYPE,
typename REALTYPE,
typename IDXTYPE,
typename DIMTYPE,
class SUBSET,
class DATAACCESSOR>
196 const REALTYPE U=
_l2loss?std::numeric_limits<REALTYPE>::infinity():
_C;
197 const REALTYPE Dii=
_l2loss?(REALTYPE)1.0/((REALTYPE)2.0*
_C):(REALTYPE)0.0;
200 for(std::size_t f=0;f<dp1;f++) w[f]=0.0;
201 for(
unsigned int sweep=0;sweep<
_max_iter;sweep++)
204 for(std::size_t i=0;i<N;i++)
206 const REALTYPE *z=&
_Z[i*dp1];
207 const REALTYPE yi=(
_y[i]==positive_class)?(REALTYPE)1.0:(REALTYPE)-1.0;
209 for(std::size_t f=0;f<dp1;f++) g+=w[f]*z[f];
210 g=yi*g-(REALTYPE)1.0+Dii*
_alpha[i];
213 if(
_alpha[i]<=0.0 && g>0.0) pg=0.0;
214 else if(
_alpha[i]>=U && g<0.0) pg=0.0;
215 const REALTYPE apg=std::fabs(pg);
216 if(apg>pg_max) pg_max=apg;
219 const REALTYPE aold=
_alpha[i];
220 REALTYPE anew=aold-g/
_qbar[i];
221 if(anew<0.0) anew=0.0;
else if(anew>U) anew=U;
223 const REALTYPE step=(anew-aold)*yi;
224 if(step!=0.0)
for(std::size_t f=0;f<dp1;f++) w[f]+=step*z[f];
227 if(pg_max<
_tol)
break;
231template<
class RETURNTYPE,
typename DATATYPE,
typename REALTYPE,
typename IDXTYPE,
typename DIMTYPE,
class SUBSET,
class DATAACCESSOR>
234 notify(
"Classifier_Linear_SVM::train().");
237 assert(
_classes==da->getNoOfClasses());
238 assert(
_features==da->getNoOfFeatures());
239 assert(sub->get_n_raw()==da->getNoOfFeatures());
252 [
this](
const auto *pat,
const DIMTYPE c){(void)pat;
_Z.push_back(1.0);
_y.push_back(c);});
253 if(N==0)
return false;
256 const REALTYPE Dii=
_l2loss?(REALTYPE)1.0/((REALTYPE)2.0*
_C):(REALTYPE)0.0;
258 for(std::size_t n=0;n<N;n++)
261 const REALTYPE *z=&
_Z[n*dp1];
262 for(std::size_t f=0;f<dp1;f++) q+=z[f]*z[f];
268 _W.assign((std::size_t)M*dp1,0.0);
269 for(DIMTYPE m=0;m<M;m++)
solve_dual(&
_W[(std::size_t)m*dp1],m);
273template<
class RETURNTYPE,
typename DATATYPE,
typename REALTYPE,
typename IDXTYPE,
typename DIMTYPE,
class SUBSET,
class DATAACCESSOR>
280 for(DIMTYPE m=0;m<M;m++)
282 const REALTYPE *w=&
_W[(std::size_t)m*dp1];
284 for(std::size_t f=0;f<d;f++) dec+=w[f]*(((REALTYPE)pattern[
_index[f]]-
_mean[f])/
_scale[f]);
285 scores[m]=(RETURNTYPE)dec;
287 if(
_classes==2) scores[1]=-scores[0];
291template<
class RETURNTYPE,
typename DATATYPE,
typename REALTYPE,
typename IDXTYPE,
typename DIMTYPE,
class SUBSET,
class DATAACCESSOR>
Dependency-free linear SVM trained by dual coordinate descent (the method of Hsieh et al....
Definition classifier_linear_svm.hpp:111
std::vector< REALTYPE > _W
models x (d+1) row-major; column d = bias; two-class data holds ONE model
Definition classifier_linear_svm.hpp:159
std::vector< DIMTYPE > _y
N training labels.
Definition classifier_linear_svm.hpp:163
void set_parameter_C(const REALTYPE c)
sets the SVM regularization parameter C (box constraint upper bound U under L1-loss)
Definition classifier_linear_svm.hpp:122
std::vector< DIMTYPE > _index
subset position -> raw feature index (first d entries valid)
Definition classifier_linear_svm.hpp:155
std::vector< REALTYPE > _qbar
N diagonal entries x_i^T x_i (+ 1/(2C) for L2-loss).
Definition classifier_linear_svm.hpp:165
Classifier< RETURNTYPE, DIMTYPE, SUBSET, DATAACCESSOR > parent
the immediate abstract base
Definition classifier_linear_svm.hpp:113
virtual std::ostream & print(std::ostream &os) const override
writes a human-readable identification of the object; base default writes nothing
Definition classifier_linear_svm.hpp:142
virtual bool classify(DIMTYPE &cls, const PPattern &pattern) override
Definition classifier_linear_svm.hpp:292
DIMTYPE _classes
class count, set by initialize()
Definition classifier_linear_svm.hpp:152
std::vector< REALTYPE > _mean
standardization shift per subset position
Definition classifier_linear_svm.hpp:157
virtual bool train(const PDataAccessor da, const PSubset sub) override
Trains the linear SVM: buffers the subset index, standardizes the design with an appended bias coordi...
Definition classifier_linear_svm.hpp:232
unsigned int _max_iter
cap on full coordinate sweeps in solve_dual()
Definition classifier_linear_svm.hpp:148
DIMTYPE model_count() const
Definition classifier_linear_svm.hpp:171
Clonable_Impl< Classifier_Linear_SVM, parent > parent_impl
implements clone() via the (implicit, member-wise) copy-constructor – all members are value-semantic
Definition classifier_linear_svm.hpp:114
std::vector< REALTYPE > _scale
standardization scale per subset position (1 for constant features)
Definition classifier_linear_svm.hpp:158
std::vector< RETURNTYPE > _cs_sc
classify() score scratch (member to avoid per-pattern allocation)
Definition classifier_linear_svm.hpp:156
void solve_dual(REALTYPE *w, const DIMTYPE positive_class)
Definition classifier_linear_svm.hpp:188
bool _l2loss
true = squared hinge (default), false = hinge
Definition classifier_linear_svm.hpp:147
DATAACCESSOR::PPattern PPattern
one data sample as exposed by DATAACCESSOR
Definition classifier_linear_svm.hpp:117
DIMTYPE _features
raw (full, unnarrowed) feature count, set by initialize()
Definition classifier_linear_svm.hpp:153
void initialize(const PDataAccessor da)
Records the class/feature counts of da and allocates the subset index buffer. Must be called before t...
Definition classifier_linear_svm.hpp:175
DIMTYPE _subfeatures
d = current subset size
Definition classifier_linear_svm.hpp:154
void set_tolerance(const REALTYPE t)
max |projected gradient| sweep-stopping threshold
Definition classifier_linear_svm.hpp:125
std::shared_ptr< DATAACCESSOR > PDataAccessor
shared pointer to the data accessor supplying train/test blocks
Definition classifier_linear_svm.hpp:115
std::vector< REALTYPE > _Z
N x (d+1) standardized design incl. bias coordinate.
Definition classifier_linear_svm.hpp:162
std::vector< REALTYPE > _alpha
N dual variables of the model currently being trained (solve_dual() scratch).
Definition classifier_linear_svm.hpp:164
REALTYPE _C
regularization parameter, see set_parameter_C()
Definition classifier_linear_svm.hpp:146
void set_max_iter(const unsigned int mi)
cap on full coordinate sweeps
Definition classifier_linear_svm.hpp:124
REALTYPE _tol
max |projected gradient| sweep-stopping threshold
Definition classifier_linear_svm.hpp:149
std::shared_ptr< SUBSET > PSubset
shared pointer to the feature subset being trained/evaluated
Definition classifier_linear_svm.hpp:116
virtual bool classify_scores(std::vector< RETURNTYPE > &scores, const PPattern &pattern) override
Definition classifier_linear_svm.hpp:274
void set_l2_loss(const bool l2)
true = squared hinge (default), false = hinge
Definition classifier_linear_svm.hpp:123
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
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.
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
std::size_t standardize_design(const std::shared_ptr< DATAACCESSOR > &da, const DIMTYPE classes, const std::size_t d, const std::size_t zstride, const std::vector< DIMTYPE > &index, std::vector< REALTYPE > &Z, std::vector< REALTYPE > &mean, std::vector< REALTYPE > &scale, AFTERPATTERN after_pattern)
Definition dense_train_tools.hpp:84