Explorar o código

Merge branch 'raw_version' of dbv.inf-cv.uni-jena.de:nice/nice-gp-hik-core into raw_version

Erik Rodner %!s(int64=9) %!d(string=hai) anos
pai
achega
e303a6cb64

+ 6 - 1
FMKGPHyperparameterOptimization.cpp

@@ -23,7 +23,6 @@
 #include <core/basics/Exception.h>
 // 
 #include <core/vector/Algorithms.h>
-#include <core/vector/Eigen.h>
 // 
 #include <core/optimization/blackbox/DownhillSimplexOptimizer.h>
 
@@ -827,6 +826,12 @@ void FMKGPHyperparameterOptimization::computeMatricesAndLUTs ( const GPLikelihoo
     PrecomputedType A;
     PrecomputedType B;
 
+    if ( this->b_debug &&  i->first == 1)
+    {
+        std::cerr << "Training for class " << i->first << endl;
+        std::cerr << "  " << i->second << std::endl;
+    }
+
     fmk->hik_prepare_alpha_multiplications ( i->second, A, B );
     A.setIoUntilEndOfFile ( false );
     B.setIoUntilEndOfFile ( false );

+ 31 - 4
GMHIKernelRaw.cpp

@@ -83,21 +83,42 @@ void GMHIKernelRaw::initData ( const std::vector< const NICE::SparseVector *> &_
         this->nnz_per_dimension[d] = 0;
     }
 
+    // additionally allocate a Vector with as many entries as examples
+    // this vector will contain the L1 norm values of all examples + noise
+    // thereby, it represents the diagonal entries of our kernel matrix for
+    // the special case of minimum kernel
+    this->diagonalElements.resize ( this->num_examples );
+    this->diagonalElements.set ( this->d_noise );
+
+
     uint example_index = 0;
-    for (std::vector< const NICE::SparseVector * >::const_iterator i = _examples.begin();
-            i != _examples.end(); i++, example_index++)
+    NICE::Vector::iterator itDiagEl = this->diagonalElements.begin();
+
+    // minor pre-allocation
+    uint index;
+    double value;
+    double l1norm;
+
+    for ( std::vector< const NICE::SparseVector * >::const_iterator i = _examples.begin();
+          i != _examples.end();
+          i++, example_index++, itDiagEl++
+        )
     {
+        l1norm = 0.0;
         const NICE::SparseVector *x = *i;
         for ( NICE::SparseVector::const_iterator j = x->begin(); j != x->end(); j++ )
         {
-            uint index = j->first;
-            double value = j->second;
+            index = j->first;
+            value = j->second;
             examples_raw_increment[index]->value = value;
             examples_raw_increment[index]->example_index = example_index;
             // move to the next element
             examples_raw_increment[index]++;
             this->nnz_per_dimension[index]++;
+
+            l1norm = l1norm + value;
         }
+        *itDiagEl = *itDiagEl + l1norm;
     }
 
     delete [] examples_raw_increment;
@@ -258,3 +279,9 @@ uint *GMHIKernelRaw::getNNZPerDimension() const
         v[i] = this->nnz_per_dimension[i];
     return v;
 }
+
+
+void NICE::GMHIKernelRaw::getDiagonalElements( NICE::Vector & _diagonalElements) const
+{
+    _diagonalElements = this->diagonalElements;
+}

+ 6 - 0
GMHIKernelRaw.h

@@ -39,6 +39,8 @@ class GMHIKernelRaw : public GenericMatrix
     double **table_A;
     double **table_B;
 
+    NICE::Vector diagonalElements;
+
     uint *nnz_per_dimension;
     uint num_dimension;
     uint num_examples;
@@ -72,6 +74,10 @@ class GMHIKernelRaw : public GenericMatrix
 
     sparseVectorElement **getDataMatrix() const { return examples_raw; };
     void updateTables ( const NICE::Vector _x ) const;
+
+    /** get the diagonal elements of the current matrix */
+    void getDiagonalElements ( NICE::Vector & _diagonalElements ) const;
+
 };
 
 }

+ 0 - 1
GPHIKClassifier.cpp

@@ -451,7 +451,6 @@ void GPHIKClassifier::predictUncertainty( const NICE::SparseVector * _example,
     }
     case APPROXIMATE_FINE:
     {
-      std::cerr << "gphyper->computePredictiveVarianceApproximateFine" << std::endl;
       this->gphyper->computePredictiveVarianceApproximateFine( *_example, _uncertainty );
       break;
     }    

+ 85 - 11
GPHIKRawClassifier.cpp

@@ -14,6 +14,7 @@
 #include <core/basics/Timer.h>
 
 #include <core/algebra/ILSConjugateGradients.h>
+#include <core/algebra/EigValues.h>
 
 // gp-hik-core includes
 #include "GPHIKRawClassifier.h"
@@ -83,7 +84,8 @@ GPHIKRawClassifier::GPHIKRawClassifier( const Config *_conf,
 
 GPHIKRawClassifier::~GPHIKRawClassifier()
 {
-  delete solver;
+  delete this->solver;
+  this->solver = NULL;
 }
 
 void GPHIKRawClassifier::initFromConfig(const Config *_conf,
@@ -97,12 +99,29 @@ void GPHIKRawClassifier::initFromConfig(const Config *_conf,
   this->b_debug     = _conf->gB( _confSection, "debug", false);
   this->f_tolerance = _conf->gD( _confSection, "f_tolerance", 1e-10);
 
-  string ilssection = "FMKGPHyperparameterOptimization";
+  //FIXME this is not used in that way for the standard GPHIKClassifier
+  //string ilssection = "FMKGPHyperparameterOptimization";
+  string ilssection       = _confSection;
   uint ils_max_iterations = _conf->gI( ilssection, "ils_max_iterations", 1000 );
-  double ils_min_delta = _conf->gD( ilssection, "ils_min_delta", 1e-7 );
+  double ils_min_delta    = _conf->gD( ilssection, "ils_min_delta", 1e-7 );
   double ils_min_residual = _conf->gD( ilssection, "ils_min_residual", 1e-7 );
-  bool ils_verbose = _conf->gB( ilssection, "ils_verbose", false );
-  this->solver = new ILSConjugateGradients( ils_verbose, ils_max_iterations, ils_min_delta, ils_min_residual );
+  bool ils_verbose        = _conf->gB( ilssection, "ils_verbose", false );
+  this->solver            = new ILSConjugateGradients( ils_verbose,
+                                                       ils_max_iterations,
+                                                       ils_min_delta,
+                                                       ils_min_residual
+                                                     );
+  if ( this->b_verbose )
+  {
+      std::cerr << "GPHIKRawClassifier::initFromConfig " <<std::endl;
+      std::cerr << "   confSection " << confSection << std::endl;
+      std::cerr << "   d_noise " << d_noise << std::endl;
+      std::cerr << "   f_tolerance " << f_tolerance << std::endl;
+      std::cerr << "   ils_max_iterations " << ils_max_iterations << std::endl;
+      std::cerr << "   ils_min_delta " << ils_min_delta << std::endl;
+      std::cerr << "   ils_min_residual " << ils_min_residual << std::endl;
+      std::cerr << "   ils_verbose " << ils_verbose << std::endl;
+  }
 }
 
 ///////////////////// ///////////////////// /////////////////////
@@ -114,7 +133,7 @@ std::set<uint> GPHIKRawClassifier::getKnownClassNumbers ( ) const
   if ( ! this->b_isTrained )
      fthrow(Exception, "Classifier not trained yet -- aborting!" );
 
-  fthrow(Exception, "GPHIKRawClassifier::getKnownClassNumbers() not yet implemented");
+  return this->knownClasses;
 }
 
 
@@ -254,7 +273,7 @@ void GPHIKRawClassifier::train ( const std::vector< const NICE::SparseVector *>
     binLabels.erase( binLabels.begin(), it );
   }
 
-  train ( _examples, binLabels );
+  this->train ( _examples, binLabels );
 }
 
 void GPHIKRawClassifier::train ( const std::vector< const NICE::SparseVector *> & _examples,
@@ -288,17 +307,72 @@ void GPHIKRawClassifier::train ( const std::vector< const NICE::SparseVector *>
   gm = new GMHIKernelRaw ( _examples, this->d_noise );
   nnz_per_dimension = gm->getNNZPerDimension();
 
+  // compute largest eigenvalue of our kernel matrix
+  // note: this guy is shared among all categories,
+  //       since the kernel matrix is shared as well
+  NICE::Vector eigenMax;
+  NICE::Matrix eigenMaxV;
+  // for reproducibility during debuggin
+  srand ( 0 );
+  srand48 ( 0 );
+  NICE::EigValues * eig = new EVArnoldi ( false /* verbose flag */,
+                                        10 /*_maxiterations*/
+                                      );
+  eig->getEigenvalues( *gm, eigenMax, eigenMaxV, 1 /*rank*/ );
+
+  delete eig;
+
+  std::cerr << " largest eigenvalue: " << eigenMax[0] << std::endl;
+  // set simple jacobi pre-conditioning
+  NICE::Vector diagonalElements;
+  gm->getDiagonalElements ( diagonalElements );
+  solver->setJacobiPreconditioner ( diagonalElements );
+
   // solve linear equations for each class
   // be careful when parallising this!
-  for ( map<uint, NICE::Vector>::const_iterator i = _binLabels.begin();
-          i != _binLabels.end(); i++ )
+  for ( std::map<uint, NICE::Vector>::const_iterator i = _binLabels.begin();
+        i != _binLabels.end();
+        i++
+      )
   {
     uint classno = i->first;
     if (b_verbose)
         std::cerr << "Training for class " << classno << endl;
-    const Vector & y = i->second;
-    Vector alpha;
+    const NICE::Vector & y = i->second;
+    NICE::Vector alpha;
+
+
+  /** About finding a good initial solution (see also GPLikelihoodApproximation)
+    * K~ = K + sigma^2 I
+    *
+    * K~ \approx lambda_max v v^T
+    * \lambda_max v v^T * alpha = k_*     | multiply with v^T from left
+    * => \lambda_max v^T alpha = v^T k_*
+    * => alpha = k_* / lambda_max could be a good initial start
+    * If we put everything in the first equation this gives us
+    * v = k_*
+    *  This reduces the number of iterations by 5 or 8
+    */
+    alpha = (y * (1.0 / eigenMax[0]) );
+
+    //DEBUG!!!
+    if ( this->b_debug && classno == 1 )
+    {
+        std::cerr << "Training for class " << classno << endl;
+        std::cerr << y << std::endl;
+        std::cerr << " alpha before and after linsolve" << classno << endl;
+        std::cerr << "  " << alpha << std::endl;
+    }
+
     solver->solveLin( *gm, y, alpha );
+
+    //DEBUG!!!
+    if ( this->b_debug && classno == 1 )
+    {
+//        std::cerr << "Training for class " << classno << endl;
+        std::cerr << "  " << alpha << std::endl;
+    }
+
     // TODO: get lookup tables, A, B, etc. and store them
     gm->updateTables(alpha);
     double **A = gm->getTableA();

+ 7 - 4
GPHIKRawClassifier.h

@@ -10,14 +10,15 @@
 // STL includes
 #include <string>
 #include <limits>
+#include <set>
 
 // NICE-core includes
 #include <core/basics/Config.h>
 #include <core/basics/Persistent.h>
 #include <core/vector/SparseVectorT.h>
-#include <core/algebra/IterativeLinearSolver.h>
+#include <core/algebra/ILSConjugateGradients.h>
+
 //
-#include <set>
 #include "quantization/Quantization.h"
 #include "GMHIKernelRaw.h"
 
@@ -66,7 +67,7 @@ class GPHIKRawClassifier //: public NICE::Persistent
     /** Gaussian label noise for model regularization */
     double d_noise;
 
-    IterativeLinearSolver *solver;
+    ILSConjugateGradients *solver;
     /** object performing feature quantization */
     NICE::Quantization *q;
 
@@ -107,7 +108,7 @@ class GPHIKRawClassifier //: public NICE::Persistent
      * @brief standard constructor
      */
     GPHIKRawClassifier( const NICE::Config *_conf ,
-                     const std::string & s_confSection = "GPHIKClassifier"
+                     const std::string & s_confSection = "GPHIKRawClassifier"
                    );
 
     /**
@@ -133,6 +134,8 @@ class GPHIKRawClassifier //: public NICE::Persistent
      */
     std::set<uint> getKnownClassNumbers ( ) const;
 
+
+
     ///////////////////// ///////////////////// /////////////////////
     //                      CLASSIFIER STUFF
     ///////////////////// ///////////////////// /////////////////////

+ 46 - 0
matlab/GPHIKRawClassifier.m

@@ -0,0 +1,46 @@
+% brief:    MATLAB class wrapper for the underlying Matlab-C++ Interface (GPHIKRawClassifierMex.cpp)
+% author:   Alexander Freytag
+% date:     07-01-2014 (dd-mm-yyyy)
+classdef GPHIKRawClassifier < handle
+
+    properties (SetAccess = private, Hidden = true)
+        % Handle to the underlying C++ class instance
+        objectHandle;
+    end
+
+    methods
+
+        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+        %%      Constructor / Destructor    %%
+        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+        %% constructor - create object
+        function this = GPHIKRawClassifier(varargin)
+            this.objectHandle = GPHIKRawClassifierMex('new', varargin{:});
+        end
+
+        %% destructor - delete object
+        function delete(this)
+            GPHIKRawClassifierMex('delete', this.objectHandle);
+        end
+
+        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+        %%       Classification stuff       %%
+        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+        %% train - standard train - assumes initialized object
+        function varargout = train(this, varargin)
+            [varargout{1:nargout}] = GPHIKRawClassifierMex('train', this.objectHandle, varargin{:});
+        end
+
+        %% classify
+        function varargout = classify(this, varargin)
+            [varargout{1:nargout}] = GPHIKRawClassifierMex('classify', this.objectHandle, varargin{:});
+        end
+
+
+        %% test - evaluate classifier on whole test set
+        function varargout = test(this, varargin)
+            [varargout{1:nargout}] = GPHIKRawClassifierMex('test', this.objectHandle, varargin{:});
+        end
+
+    end
+end

+ 497 - 0
matlab/GPHIKRawClassifierMex.cpp

@@ -0,0 +1,497 @@
+#ifdef NICE_USELIB_MEX
+/**
+* @file GPHIKRawClassifierMex.cpp
+* @author Alexander Freytag
+* @date 21-09-2015 (dd-mm-yyyy)
+* @brief Matlab-Interface of our GPHIKRawClassifier, allowing for training and classification without more advanced methods.
+*/
+
+// STL includes
+#include <math.h>
+#include <matrix.h>
+#include <mex.h>
+
+// NICE-core includes
+#include <core/basics/Config.h>
+#include <core/basics/Timer.h>
+#include <core/vector/MatrixT.h>
+#include <core/vector/VectorT.h>
+
+// gp-hik-core includes
+#include "gp-hik-core/GPHIKRawClassifier.h"
+
+
+// Interface for conversion between Matlab and C objects
+#include "gp-hik-core/matlab/classHandleMtoC.h"
+#include "gp-hik-core/matlab/ConverterMatlabToNICE.h"
+#include "gp-hik-core/matlab/ConverterNICEToMatlab.h"
+
+using namespace std; //C basics
+using namespace NICE;  // nice-core
+
+
+NICE::Config parseParametersGPHIKRawClassifier(const mxArray *prhs[], int nrhs)
+{
+  NICE::Config conf;
+
+  // if first argument is the filename of an existing config file,
+  // read the config accordingly
+
+  int i_start ( 0 );
+  std::string variable = MatlabConversion::convertMatlabToString(prhs[i_start]);
+  if(variable == "conf")
+  {
+      conf = NICE::Config ( MatlabConversion::convertMatlabToString( prhs[i_start+1] )  );
+      i_start = i_start+2;
+  }
+
+  // now run over all given parameter specifications
+  // and add them to the config
+  for( int i=i_start; i < nrhs; i+=2 )
+  {
+    std::string variable = MatlabConversion::convertMatlabToString(prhs[i]);
+
+    /////////////////////////////////////////
+    // READ STANDARD BOOLEAN VARIABLES
+    /////////////////////////////////////////
+    if( (variable == "verbose") ||
+        (variable == "debug") ||
+        (variable == "ils_verbose")
+      )
+    {
+      if ( mxIsChar( prhs[i+1] ) )
+      {
+        string value = MatlabConversion::convertMatlabToString( prhs[i+1] );
+        if ( (value != "true") && (value != "false") )
+        {
+          std::string errorMsg = "Unexpected parameter value for \'" +  variable + "\'. In string modus, \'true\' or \'false\' expected.";
+          mexErrMsgIdAndTxt( "mexnice:error", errorMsg.c_str() );
+        }
+
+        if( value == "true" )
+          conf.sB("GPHIKRawClassifier", variable, true);
+        else
+          conf.sB("GPHIKRawClassifier", variable, false);
+      }
+      else if ( mxIsLogical( prhs[i+1] ) )
+      {
+        bool value = MatlabConversion::convertMatlabToBool( prhs[i+1] );
+        conf.sB("GPHIKRawClassifier", variable, value);
+      }
+      else
+      {
+          std::string errorMsg = "Unexpected parameter value for \'" +  variable + "\'. \'true\', \'false\', or logical expected.";
+          mexErrMsgIdAndTxt( "mexnice:error", errorMsg.c_str() );
+      }
+    }
+
+    /////////////////////////////////////////
+    // READ STANDARD INT VARIABLES
+    /////////////////////////////////////////
+
+    /////////////////////////////////////////
+    // READ STRICT POSITIVE INT VARIABLES
+    /////////////////////////////////////////
+    if ( variable == "ils_max_iterations" )
+    {
+      if ( mxIsDouble( prhs[i+1] ) )
+      {
+        double value = MatlabConversion::convertMatlabToDouble(prhs[i+1]);
+        if( value < 1 )
+        {
+          std::string errorMsg = "Expected parameter value larger than 0 for \'" +  variable + "\'.";
+          mexErrMsgIdAndTxt( "mexnice:error", errorMsg.c_str() );
+        }
+        conf.sI("GPHIKRawClassifier", variable, (int) value);
+      }
+      else if ( mxIsInt32( prhs[i+1] ) )
+      {
+        int value = MatlabConversion::convertMatlabToInt32(prhs[i+1]);
+        if( value < 1 )
+        {
+          std::string errorMsg = "Expected parameter value larger than 0 for \'" +  variable + "\'.";
+          mexErrMsgIdAndTxt( "mexnice:error", errorMsg.c_str() );
+        }
+        conf.sI("GPHIKRawClassifier", variable, value);
+      }
+      else
+      {
+          std::string errorMsg = "Unexpected parameter value for \'" +  variable + "\'. Int32 or Double expected.";
+          mexErrMsgIdAndTxt( "mexnice:error", errorMsg.c_str() );
+      }
+    }
+
+    /////////////////////////////////////////
+    // READ STANDARD DOUBLE VARIABLES
+    /////////////////////////////////////////
+
+
+    /////////////////////////////////////////
+    // READ POSITIVE DOUBLE VARIABLES
+    /////////////////////////////////////////
+    if ( (variable == "f_tolerance") ||
+         (variable == "ils_min_delta") ||
+         (variable == "ils_min_residual") ||
+         (variable == "noise")
+       )
+    {
+      if ( mxIsDouble( prhs[i+1] ) )
+      {
+        double value = MatlabConversion::convertMatlabToDouble(prhs[i+1]);
+        if( value < 0.0 )
+        {
+          std::string errorMsg = "Expected parameter value larger than 0 for \'" +  variable + "\'.";
+          mexErrMsgIdAndTxt( "mexnice:error", errorMsg.c_str() );
+        }
+        conf.sD("GPHIKRawClassifier", variable, value);
+      }
+      else
+      {
+          std::string errorMsg = "Unexpected parameter value for \'" +  variable + "\'. Double expected.";
+          mexErrMsgIdAndTxt( "mexnice:error", errorMsg.c_str() );
+      }
+    }
+
+    /////////////////////////////////////////
+    // READ REMAINING SPECIFIC VARIABLES
+    /////////////////////////////////////////
+
+    if(variable == "ils_method")
+    {
+      string value = MatlabConversion::convertMatlabToString(prhs[i+1]);
+      if(value != "CG" && value != "CGL" && value != "SYMMLQ" && value != "MINRES")
+        mexErrMsgIdAndTxt("mexnice:error","Unexpected parameter value for \'ils_method\'. \'CG\', \'CGL\', \'SYMMLQ\' or \'MINRES\' expected.");
+        conf.sS("GPHIKRawClassifier", variable, value);
+    }
+
+  }
+
+
+  return conf;
+}
+
+// MAIN MATLAB FUNCTION
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+    // get the command string specifying what to do
+    if (nrhs < 1)
+        mexErrMsgTxt("No commands and options passed... Aborting!");
+
+    if( !mxIsChar( prhs[0] ) )
+        mexErrMsgTxt("First argument needs to be the command, ie.e, the class method to call... Aborting!");
+
+    std::string cmd = MatlabConversion::convertMatlabToString( prhs[0] );
+
+
+    // create object
+    if ( !strcmp("new", cmd.c_str() ) )
+    {
+        // check output variable
+        if (nlhs != 1)
+            mexErrMsgTxt("New: One output expected.");
+
+        // read config settings
+        NICE::Config conf = parseParametersGPHIKRawClassifier(prhs+1,nrhs-1);
+
+        // create class instance
+        NICE::GPHIKRawClassifier * classifier = new NICE::GPHIKRawClassifier ( &conf, "GPHIKRawClassifier" /*sectionName in config*/ );
+
+
+        // handle to the C++ instance
+        plhs[0] = MatlabConversion::convertPtr2Mat<NICE::GPHIKRawClassifier>( classifier );
+        return;
+    }
+
+    // in all other cases, there should be a second input,
+    // which the be the class instance handle
+    if (nrhs < 2)
+      mexErrMsgTxt("Second input should be a class instance handle.");
+
+    // delete object
+    if ( !strcmp("delete", cmd.c_str() ) )
+    {
+        // Destroy the C++ object
+        MatlabConversion::destroyObject<NICE::GPHIKRawClassifier>(prhs[1]);
+        return;
+    }
+
+    // get the class instance pointer from the second input
+    // every following function needs the classifier object
+    NICE::GPHIKRawClassifier * classifier = MatlabConversion::convertMat2Ptr<NICE::GPHIKRawClassifier>(prhs[1]);
+
+
+    ////////////////////////////////////////
+    //  Check which class method to call  //
+    ////////////////////////////////////////
+
+
+    // standard train - assumes initialized object
+    if (!strcmp("train", cmd.c_str() ))
+    {
+        // Check parameters
+        if (nlhs < 0 || nrhs < 4)
+        {
+            mexErrMsgTxt("Train: Unexpected arguments.");
+        }
+
+        //------------- read the data --------------
+
+        std::vector< const NICE::SparseVector *> examplesTrain;
+        NICE::Vector yMultiTrain;
+
+        if ( mxIsSparse( prhs[2] ) )
+        {
+            examplesTrain = MatlabConversion::convertSparseMatrixToNice( prhs[2] );
+        }
+        else
+        {
+            NICE::Matrix dataTrain;
+            dataTrain = MatlabConversion::convertDoubleMatrixToNice(prhs[2]);
+
+            //----------------- convert data to sparse data structures ---------
+            examplesTrain.resize( dataTrain.rows() );
+
+
+            std::vector< const NICE::SparseVector *>::iterator exTrainIt = examplesTrain.begin();
+            for (int i = 0; i < (int)dataTrain.rows(); i++, exTrainIt++)
+            {
+                *exTrainIt =  new NICE::SparseVector( dataTrain.getRow(i) );
+            }
+        }
+
+        yMultiTrain = MatlabConversion::convertDoubleVectorToNice(prhs[3]);
+
+        //----------------- train our classifier -------------
+        classifier->train ( examplesTrain , yMultiTrain );
+
+        //----------------- clean up -------------
+        for(int i=0;i<examplesTrain.size();i++)
+            delete examplesTrain[i];
+
+        return;
+    }
+
+
+    // Classify
+    if ( !strcmp("classify", cmd.c_str() ) )
+    {
+        // Check parameters
+        if ( (nlhs < 0) || (nrhs < 2) )
+        {
+            mexErrMsgTxt("Test: Unexpected arguments.");
+        }
+
+        //------------- read the data --------------
+
+        uint result;
+        NICE::SparseVector scores;
+
+        if ( mxIsSparse( prhs[2] ) )
+        {
+            NICE::SparseVector * example;
+            example = new NICE::SparseVector ( MatlabConversion::convertSparseVectorToNice( prhs[2] ) );
+            classifier->classify ( example,  result, scores );
+
+            //----------------- clean up -------------
+            delete example;
+        }
+        else
+        {
+            NICE::Vector * example;
+            example = new NICE::Vector ( MatlabConversion::convertDoubleVectorToNice(prhs[2]) );
+            NICE::SparseVector * svec  = new NICE::SparseVector( *example );
+            delete example;
+
+            classifier->classify ( svec,  result, scores );
+
+            //----------------- clean up -------------
+            delete svec;
+
+        }
+
+
+
+          // output
+          plhs[0] = mxCreateDoubleScalar( result );
+
+          if(nlhs >= 2)
+          {
+            plhs[1] = MatlabConversion::convertSparseVectorFromNice( scores, true  /*b_adaptIndex*/);
+          }
+          return;
+    }
+
+
+    // Test - evaluate classifier on whole test set
+    if ( !strcmp("test", cmd.c_str() ) )
+    {
+        // Check parameters
+        if (nlhs < 0 || nrhs < 4)
+            mexErrMsgTxt("Test: Unexpected arguments.");
+        //------------- read the data --------------
+
+
+        bool dataIsSparse ( mxIsSparse( prhs[2] ) );
+
+        std::vector< const NICE::SparseVector *> dataTest_sparse;
+        NICE::Matrix dataTest_dense;
+
+        if ( dataIsSparse )
+        {
+            dataTest_sparse = MatlabConversion::convertSparseMatrixToNice( prhs[2] );
+        }
+        else
+        {
+            dataTest_dense = MatlabConversion::convertDoubleMatrixToNice(prhs[2]);
+        }
+
+        NICE::Vector yMultiTest;
+        yMultiTest = MatlabConversion::convertDoubleVectorToNice(prhs[3]);
+
+
+        // ------------------------------------------
+        // ------------- PREPARATION --------------
+        // ------------------------------------------
+
+        // determine classes known during training and corresponding mapping
+        // thereby allow for non-continous class labels
+        std::set< uint > classesKnownTraining = classifier->getKnownClassNumbers();
+
+        uint noClassesKnownTraining ( classesKnownTraining.size() );
+        std::map< uint, uint > mapClNoToIdxTrain;
+        std::set< uint >::const_iterator clTrIt = classesKnownTraining.begin();
+        for ( uint i=0; i < noClassesKnownTraining; i++, clTrIt++ )
+            mapClNoToIdxTrain.insert ( std::pair< uint, uint > ( *clTrIt, i )  );
+
+        // determine classes known during testing and corresponding mapping
+        // thereby allow for non-continous class labels
+        std::set< uint > classesKnownTest;
+        classesKnownTest.clear();
+
+
+        // determine which classes we have in our label vector
+        // -> MATLAB: myClasses = unique(y);
+        for ( NICE::Vector::const_iterator it = yMultiTest.begin(); it != yMultiTest.end(); it++ )
+        {
+          if ( classesKnownTest.find ( *it ) == classesKnownTest.end() )
+          {
+            classesKnownTest.insert ( *it );
+          }
+        }
+
+        int noClassesKnownTest ( classesKnownTest.size() );
+        std::map< uint, uint> mapClNoToIdxTest;
+        std::set< uint >::const_iterator clTestIt = classesKnownTest.begin();
+        for ( uint i=0; i < noClassesKnownTest; i++, clTestIt++ )
+            mapClNoToIdxTest.insert ( std::pair< uint, uint > ( *clTestIt, i )  );
+
+
+
+        int i_numTestSamples;
+
+        if ( dataIsSparse )
+            i_numTestSamples = dataTest_sparse.size();
+        else
+            i_numTestSamples = (int) dataTest_dense.rows();
+
+        NICE::Matrix confusionMatrix( noClassesKnownTraining, noClassesKnownTest, 0.0);
+        NICE::Matrix scores( i_numTestSamples, noClassesKnownTraining, 0.0);
+
+
+
+        // ------------------------------------------
+        // ------------- CLASSIFICATION --------------
+        // ------------------------------------------
+
+        NICE::Timer t;
+        double testTime (0.0);
+
+
+
+        for (int i = 0; i < i_numTestSamples; i++)
+        {
+            //----------------- convert data to sparse data structures ---------
+
+
+            uint result;
+            NICE::SparseVector exampleScoresSparse;
+
+            if ( dataIsSparse )
+            {
+              // and classify
+              t.start();
+              classifier->classify( dataTest_sparse[ i ], result, exampleScoresSparse );
+              t.stop();
+              testTime += t.getLast();
+            }
+            else
+            {
+                NICE::Vector example ( dataTest_dense.getRow(i) );
+                NICE::SparseVector * svec = new NICE::SparseVector ( example );
+              // and classify
+              t.start();
+              classifier->classify( svec, result, exampleScoresSparse );
+              t.stop();
+              testTime += t.getLast();
+              delete svec;
+            }
+
+            confusionMatrix(  mapClNoToIdxTrain.find(result)->second, mapClNoToIdxTest.find(yMultiTest[i])->second ) += 1.0;
+            int scoreCnt ( 0 );
+            for ( NICE::SparseVector::const_iterator scoreIt = exampleScoresSparse.begin(); scoreIt != exampleScoresSparse.end(); scoreIt++, scoreCnt++ )
+            {
+              scores(i,scoreCnt) = scoreIt->second;
+            }
+
+        }
+
+        std::cerr << "Time for testing: " << testTime << std::endl;
+
+        // clean up
+        if ( dataIsSparse )
+        {
+            for ( std::vector<const NICE::SparseVector *>::iterator it = dataTest_sparse.begin(); it != dataTest_sparse.end(); it++)
+                delete *it;
+        }
+
+
+
+        confusionMatrix.normalizeColumnsL1();
+
+        double recRate = confusionMatrix.trace()/confusionMatrix.cols();
+
+
+        plhs[0] = mxCreateDoubleScalar( recRate );
+
+        if(nlhs >= 2)
+          plhs[1] = MatlabConversion::convertMatrixFromNice(confusionMatrix);
+        if(nlhs >= 3)
+          plhs[2] = MatlabConversion::convertMatrixFromNice(scores);
+
+
+        return;
+    }
+
+    ///////////////////// INTERFACE ONLINE LEARNABLE /////////////////////
+    // interface specific methods for incremental extensions
+    ///////////////////// INTERFACE ONLINE LEARNABLE /////////////////////
+
+   // not supported here
+
+    ///////////////////// INTERFACE PERSISTENT /////////////////////
+    // interface specific methods for store and restore
+    ///////////////////// INTERFACE PERSISTENT /////////////////////
+
+    // not supported here
+
+
+
+    // Got here, so command not recognized
+
+    std::string errorMsg (cmd.c_str() );
+    errorMsg += " -- command not recognized.";
+    mexErrMsgTxt( errorMsg.c_str() );
+
+}
+#endif
+

+ 15 - 12
matlab/testGPHIKClassifierMex.m

@@ -13,47 +13,50 @@ myLabels = [1,1,2,2,3,3];
 
 
 % init new GPHIKClassifier object
-myGPHIKClassifier = GPHIKClassifierMex ( 'new', 'verbose', 'false', ...
-    'optimization_method', 'none', 'varianceApproximation', 'approximate_rough',...
+myGPHIKClassifier = GPHIKClassifier ( ...
+    'verbose', 'false', ...
+    'optimization_method', 'none', ...
+    'varianceApproximation', 'approximate_rough',...
     'nrOfEigenvaluesToConsiderForVarApprox',4,...
     'uncertaintyPredictionForClassification', false ...
     );
 
 % run train method
-GPHIKClassifierMex ( 'train', myGPHIKClassifier, myData, myLabels);
+myGPHIKClassifier.train( myData, myLabels );
 
 myDataTest = [ 0.3 0.4 0.3
              ];
 myLabelsTest = [1];
 
 % run single classification call
-[ classNoEst, score, uncertainty] = GPHIKClassifierMex ( 'classify', myGPHIKClassifier, myDataTest )
+[ classNoEst, score, uncertainty] = myGPHIKClassifier.classify( myDataTest )
 % compute predictive variance
-uncertainty = GPHIKClassifierMex ( 'uncertainty', myGPHIKClassifier, myDataTest )
+uncertainty = myGPHIKClassifier.uncertainty( myDataTest )
 % run test method evaluating arr potentially using multiple examples
-[ arr, confMat, scores] = GPHIKClassifierMex ( 'test', myGPHIKClassifier, myDataTest, myLabelsTest )
+[ arr, confMat, scores] = myGPHIKClassifier.test( myDataTest, myLabelsTest )
 
 % add a single new example
 newExample = [ 0.5 0.5 0.0
              ];
 newLabel = [4];
-GPHIKClassifierMex ( 'addExample', myGPHIKClassifier, newExample, newLabel);
+myGPHIKClassifier.addExample( newExample, newLabel );
 
 % add mutiple new examples
 newExamples = [ 0.3 0.3 0.4;
                 0.1, 0.2, 0.7
              ];
 newLabels = [1,3];
-GPHIKClassifierMex ( 'addMultipleExamples', myGPHIKClassifier, newExamples, newLabels );
+myGPHIKClassifier.addMultipleExamples( newExamples, newLabels );
 
 % perform evaluation again
 
 % run single classification call
-[ classNoEst, score, uncertainty] = GPHIKClassifierMex ( 'classify', myGPHIKClassifier, myDataTest )
+[ classNoEst, score, uncertainty] = myGPHIKClassifier.classify( myDataTest )
 % compute predictive variance
-uncertainty = GPHIKClassifierMex ( 'uncertainty', myGPHIKClassifier, myDataTest )
+uncertainty = myGPHIKClassifier.uncertainty( myDataTest )
 % run test method evaluating arr potentially using multiple examples
-[ arr, confMat, scores] = GPHIKClassifierMex ( 'test', myGPHIKClassifier, myDataTest, myLabelsTest )
+[ arr, confMat, scores] = myGPHIKClassifier.test( myDataTest, myLabelsTest )
 
 % clean up and delete object
-GPHIKClassifierMex ( 'delete',myGPHIKClassifier);
+myGPHIKClassifier.delete();
+clear ( 'myGPHIKClassifier' );

+ 37 - 0
matlab/testGPHIKRawClassifier.m

@@ -0,0 +1,37 @@
+% brief:    Demo-program showing how to use the GPHIKRaw Interface (without a class wrapper)
+% author:   Alexander Freytag
+% date:     21-09-2015 (dd-mm-yyyy)
+
+myData = [ 0.2 0.3 0.5;
+           0.3 0.2 0.5;
+           0.9 0.0 0.1;
+           0.8 0.1 0.1;
+           0.1 0.1 0.8;
+           0.1 0.0 0.9
+          ];
+myLabels = [1,1,2,2,3,3];
+
+
+% init new GPHIKRawClassifier object
+myGPHIKRawClassifier = GPHIKRawClassifierMex ( ...
+     'new', ...
+     'verbose', 'false' ...
+    );
+
+% run train method
+GPHIKRawClassifierMex ( 'train', myGPHIKRawClassifier, myData, myLabels);
+
+myDataTest = [ 0.3 0.4 0.3
+             ];
+myLabelsTest = [1];
+
+% run single classification call
+[ classNoEst, score ]   = GPHIKRawClassifierMex ( 'classify', myGPHIKRawClassifier, myDataTest )
+
+% run test call which classifies entire data set
+[ arr, confMat, scores] = GPHIKRawClassifierMex ( 'test', myGPHIKRawClassifier, myDataTest, myLabelsTest )
+
+
+
+% clean up and delete object
+GPHIKRawClassifierMex ( 'delete',myGPHIKRawClassifier);

+ 36 - 0
matlab/testGPHIKRawClassifierMex.m

@@ -0,0 +1,36 @@
+% brief:    Demo-program showing how to use the GPHIKRawClassifier
+%           Interface ( with a class wrapper)
+% author:   Alexander Freytag
+% date:     21-09-2015 (dd-mm-yyyy)
+
+myData = [ 0.2 0.3 0.5;
+           0.3 0.2 0.5;
+           0.9 0.0 0.1;
+           0.8 0.1 0.1;
+           0.1 0.1 0.8;
+           0.1 0.0 0.9
+          ];
+myLabels = [1,1,2,2,3,3];
+
+
+% init new GPHIKRawClassifier object
+myGPHIKRawClassifier = GPHIKRawClassifier ( ...
+                       'verbose', 'false' ...
+                     );
+
+% run train method
+myGPHIKRawClassifier.train( myData, myLabels );
+
+myDataTest = [ 0.3 0.4 0.3
+             ];
+myLabelsTest = [1];
+
+% run single classification call
+[ classNoEst, score] = myGPHIKRawClassifier.classify ( myDataTest )
+% run test method evaluating arr potentially using multiple examples
+[ arr, confMat, scores] = myGPHIKRawClassifier.test( myDataTest, myLabelsTest )
+
+
+% clean up and delete object
+myGPHIKRawClassifier.delete();
+clear ( 'myGPHIKRawClassifier' );