The low-level training algorithms and structure is as identical to original libsvm from Chi-Jen-Lin as possible (only some minor changes to include the templated feature vectors and kernel functions), which allows easy integration of further improvements in libsvm and ensures correct numerics.
You may use any combination of the above classes, e.g.
MultiClassSVMOneVsOne< TwoClassSVMc< Kernel_LINEAR> > svm;
Or if you like to calculate all kernel evaluations only once (and you have enough memory to store the whole kernel matrix), use:
MultiClassSVMOneVsOne< TwoClassSVMc< Kernel_MATRIX< Kernel_LINEAR> > > svm;
Each class (Kernels, Two-class-SVM's, Multi-class-SVM's, Models, etc.) can read and write its private variables from/to a templated "structured data class", e.g. the loadParameters() method of Kernel_POLY looks like this:
class Kernel_POLY { //... template<typename STDATA> void loadParameters( STDATA& stData) { stData.getValue( "gamma", p_gamma); stData.getValue( "coef0", p_coef0); stData.getValue( "degree", p_degree); } };Available strutured data classes are up to now:
Each class reports its progress during training to a given ProgressReporter object. This allows nicer display of progress, even in GUI applications and to set a time-out, e.g. when doing large grid searches over weekend.
SVMFactory allows to create any combination of the above classes at runtime (instead of compile time). Implemented with template meta programming. So if you write your own Kernel-classes just add it to the kernel-list and you are done. Sample-Code:
/*---------------------------------------------------------- * specify available multi-class Algorithms *---------------------------------------------------------*/ typedef TTLIST_2( svt::MultiClassSVMOneVsOne, svt::MultiClassSVMOneVsRest) MyMultiClassList; /*-------------------------------------------------------- * specify available two-class Algorithms *---------------------------------------------------------*/ typedef TTLIST_2( svt::TwoClassSVMc, svt::TwoClassSVMnu) MyTwoClassList; /*-------------------------------------------------------- * specify available kernel functions *--------------------------------------------------------*/ typedef TLIST_6( svt::Kernel_LINEAR, svt::Kernel_RBF, svt::Kernel_POLY, svt::Kernel_SIGMOID, svt::Kernel_MATRIX<svt::Kernel_LINEAR>, svt::Kernel_MATRIX<svt::Kernel_RBF> ) MyKernelList; /*-------------------------------------------------------- * Create approprate combination at runtime *--------------------------------------------------------*/ std::string mcName = "one_vs_rest"; std::string tcName = "c_svc"; std::string kfName = "rbf"; SVMAdapter* svm = svt::BasicSVMFactory< BasicFV, StDataASCIIFile, MyMultiClassList, MyTwoClassList, MyKernelList >::create( mcName, tcName, kfName);
Instead of having different shell applications like 'svm-train' and 'svm-predict', the libsvmTL has only one application that uses subcommands. The shell calls are:
svmtl train [options] trainfile svmtl classify [options] testfile svmtl crossval [options] trainfile svmtl gridsearch [options] trainfileThis helps you to develop applications with own kernels / feature vectors, etc. and make immediately use of all libsvmTL advantages. (see next section.
the class SVMApplication template class contains all methods for a full shell application, so the simplest way to write a fully functional svmtl Application which uses you self-written kernel, is
/*-------------------------------------------------------- * My svmtl application using MySuperKernel *--------------------------------------------------------*/ #include <SVMApplicationWithDefaults.hh> #include <MySuperKernel.hh> /*-------------------------------------------------------- * specify available kernel functions *--------------------------------------------------------*/ typedef TLIST_3( MySuperKernel, svt::Kernel_MATRIX<MySuperKernel>, svt::DefaultKernelList) MyKernelList; int main( int argc, const char** argv) { svt::SVMApplication< svt::BasicFV, svt::StDataASCIIFile, svt::DefaultMultiClassList, svt::DefaultTwoClassList, svt::DefaultOneClassList, MyKernelList> sappl; return sappl.main( argc, argv, std::cout); }
If you have to implemented the methods name(), description(), loadParameters(), saveParameters(), getParamHelp() correctly in your MySuperKernel class, you will be able to set all your kernel-parameters from commandline, you'll get help for the parameters if you call the application e.g. with "mysvmtl train --help" and they will also be saved and restored correctly from the model file.
Using non-sparse Feature-Vectors (class BasicFV) speeds up kernel evaluations. If you really need sparse feature vecotrs, just use the SparseFV class.
The libsvmTL implements a uniqueID() method for each feature vector, that allows to cache kernel evaluations from one training to another using the Kernel_MATRIX wrapper. This significantly speeds up cross-validation and grid-search
Optimized Cross-Validation algorithm that first trains all two-class SVM's for the whole dataset and then retrains only those two-class-SVM's that are affected from left-out vectors (significantly speed up for high number of subsets in cross validation and leave-one-out validation)
Optimized Grid only recalculates Kernel evaluations is kernel parameters change (e.g. when changing C ind C-SVM you don't need to reevaluate the kernel) (Planned, not implemented yet)
here is a comparison table for the runtime performance:
task | original libsvm | libsvmTL | speedup factor | comment |
---|---|---|---|---|
training with rbf-kernel gamma = 1/256, C = 1 |
13.970s | 9.830s | 1.4 | effect of using linear storage instead of sparse storage for feature vectors |
10-fold cross validation RBF, gamma = 1/256, C = 1 |
120.080s | 17.290s | 6.9 | effect of caching full kernel matrix |
40-fold cross validation RBF, gamma = 1/256, C = 1 |
511.812s | 25.480s | 20 | effect of caching full kernel matrix |
2000-fold cross validation (= leave one out) RBF, gamma = 1/256, C = 1 |
extrapolated, not yet measured: 24000s = 6.6h | measured: 47.120s | ~ 500 | effect of caching full kernel matrix, effect of reusing trained Two-class SVM's in cross validation |
... to be continued for optimzed grid search