Эх сурвалжийг харах

updated interfaces for gphik classifier

Alexander Freytag 9 жил өмнө
parent
commit
d9c0a6fbed

+ 59 - 0
FMKGPHyperparameterOptimization.cpp

@@ -1212,6 +1212,65 @@ uint FMKGPHyperparameterOptimization::classify ( const NICE::SparseVector & _xst
   }
 }
 
+uint FMKGPHyperparameterOptimization::classify ( const NICE::SparseVector & _xstar,
+                                                 NICE::Vector & _scores
+                                               )  const
+{
+    if ( _scores.size() != (*(this->knownClasses.rbegin() ) + 1) )
+    {
+        _scores.resize ( *(this->knownClasses.rbegin() ) + 1 );
+        _scores.set ( -std::numeric_limits<double>::max() );
+    }
+
+
+  // loop through all classes
+  if ( this->precomputedA.size() == 0 )
+  {
+    fthrow ( Exception, "The precomputation vector is zero...have you trained this classifier?" );
+  }
+
+  for ( std::map<uint, PrecomputedType>::const_iterator i = this->precomputedA.begin() ; i != this->precomputedA.end(); i++ )
+  {
+    uint classno = i->first;
+    double beta;
+
+    if ( this->q != NULL ) {
+      std::map<uint, double *>::const_iterator j = this->precomputedT.find ( classno );
+      double *T = j->second;
+      this->fmk->hik_kernel_sum_fast ( T, this->q, _xstar, beta );
+    } else {
+      const PrecomputedType & A = i->second;
+      std::map<uint, PrecomputedType>::const_iterator j = this->precomputedB.find ( classno );
+      const PrecomputedType & B = j->second;
+
+      // fmk->hik_kernel_sum ( A, B, _xstar, beta ); if A, B are of type Matrix
+      // Giving the transformation pf as an additional
+      // argument is necessary due to the following reason:
+      // FeatureMatrixT is sorted according to the original values, therefore,
+      // searching for upper and lower bounds ( findFirst... functions ) require original feature
+      // values as inputs. However, for calculation we need the transformed features values.
+
+      this->fmk->hik_kernel_sum ( A, B, _xstar, beta, pf );
+    }
+
+    _scores[ classno ] = beta;
+  }
+
+  if ( this->precomputedA.size() > 1 )
+  { // multi-class classification
+    return _scores.MaxIndex();
+  }
+  else if ( this->knownClasses.size() == 2 ) // binary setting
+  {
+    _scores[ this->i_binaryLabelNegative ] = -_scores[ this->i_binaryLabelPositive ];
+    return _scores[ this->i_binaryLabelPositive ] <= 0.0 ? this->i_binaryLabelNegative : this->i_binaryLabelPositive;
+  }
+  else //OCC or regression setting
+  {
+    return 1;
+  }
+}
+
 uint FMKGPHyperparameterOptimization::classify ( const NICE::Vector & _xstar, 
                                                  NICE::SparseVector & _scores 
                                                ) const

+ 12 - 0
FMKGPHyperparameterOptimization.h

@@ -439,6 +439,18 @@ class FMKGPHyperparameterOptimization : public NICE::Persistent, public NICE::On
     uint classify ( const NICE::SparseVector & _x, 
                    SparseVector & _scores 
                  ) const;
+
+    /**
+    * @brief classify an example
+    *
+    * @param x input example (sparse vector)
+    * @param scores scores for each class number (non-sparse)
+    *
+    * @return class number achieving the best score
+    */
+    uint classify ( const NICE::SparseVector & _x,
+                   NICE::Vector & _scores
+                 ) const;
     
     /**
     * @brief classify an example that is given as non-sparse vector

+ 91 - 0
GPHIKClassifier.cpp

@@ -279,6 +279,97 @@ void GPHIKClassifier::classify ( const NICE::Vector * _example,
   }
 }
 
+
+
+void GPHIKClassifier::classify ( const NICE::SparseVector * _example,
+                                 uint & _result,
+                                 NICE::Vector & _scores,
+                                 double & _uncertainty
+                               ) const
+{
+    if ( ! this->b_isTrained )
+       fthrow(Exception, "Classifier not trained yet -- aborting!" );
+
+
+    _result = gphyper->classify ( *_example, _scores );
+
+
+    if ( _scores.size() == 0 ) {
+      fthrow(Exception, "Zero scores, something is likely to be wrong here: svec.size() = " << _example->size() );
+    }
+
+    if ( this->uncertaintyPredictionForClassification )
+    {
+
+      if ( this->varianceApproximation != NONE)
+      {
+        this->predictUncertainty( _example, _uncertainty );
+      }
+      else
+      {
+  //       //do nothing
+        _uncertainty = std::numeric_limits<double>::max();
+      }
+    }
+    else
+    {
+
+      //do nothing
+      _uncertainty = std::numeric_limits<double>::max();
+    }
+}
+
+
+
+void GPHIKClassifier::classify ( const std::vector< const NICE::SparseVector *> _examples,
+                                 NICE::Vector & _results,
+                                 NICE::Matrix & _scores,
+                                 NICE::Vector & _uncertainties
+                               ) const
+{
+    if ( ! this->b_isTrained )
+       fthrow(Exception, "Classifier not trained yet -- aborting!" );
+
+    std::set<unsigned int> knownClasses = (this->getKnownClassNumbers());
+
+
+    _scores.resize( _examples.size(), * (knownClasses.rbegin()) +1 );
+    _scores.set( 0.0 );
+
+    _results.resize( _examples.size() );
+    _results.set( 0.0 );
+
+    _uncertainties.resize( _examples.size() );
+    _uncertainties.set( 0.0 );
+
+
+    NICE::Vector::iterator resultsIt = _results.begin();
+    NICE::Vector::iterator uncIt     = _uncertainties.begin();
+
+
+    uint exCnt ( 0 );
+    uint resUI ( 0 );
+    NICE::Vector scoresSingle( * (knownClasses.rbegin()) +1, -std::numeric_limits<double>::max() );
+    double uncSingle ( 0.0 );
+
+    for ( std::vector< const NICE::SparseVector *>::const_iterator exIt = _examples.begin();
+          exIt != _examples.end();
+          exIt++, resultsIt++, exCnt++, uncIt++
+        )
+    {
+        this->classify ( *exIt,
+                         resUI,
+                         scoresSingle,
+                         uncSingle
+                       );
+        *resultsIt = resUI;
+        *uncIt     = uncSingle;
+        _scores.setRow( exCnt, scoresSingle );
+       scoresSingle.set( -std::numeric_limits<double>::max() );
+    }
+}
+
+
 /** training process */
 void GPHIKClassifier::train ( const std::vector< const NICE::SparseVector *> & _examples, 
                               const NICE::Vector & _labels 

+ 32 - 0
GPHIKClassifier.h

@@ -197,6 +197,38 @@ class GPHIKClassifier : public NICE::Persistent, public NICE::OnlineLearnable
                     double & _uncertainty 
                   ) const;    
 
+
+    /**
+     * @brief classify a given example with the previously learnt model
+     * NOTE: whenever possible, you should the sparse version to obtain significantly smaller computation times
+     * @date 18-06-2013 (dd-mm-yyyy)
+     * @author Alexander Freytag
+     * @param example (sparse Vector) to be classified given in a non-sparse representation
+     * @param result (uint) class number of most likely class
+     * @param scores (non-sparse vector) classification scores for known classes
+     * @param uncertainty (double) predictive variance of the classification result, if computed
+     */
+    void classify ( const NICE::SparseVector * _example,
+                    uint & _result,
+                    NICE::Vector & _scores,
+                    double & _uncertainty
+                  ) const;
+
+
+    /**
+     * @brief classify a given set of examples with the previously learned model
+     * @author Alexander Freytag, Erik Rodner
+     * @param examples ((std::vector< NICE::SparseVector *>)) to be classified given in a sparse representation
+     * @param results (Vector) class number of most likely class per example
+     * @param scores (NICE::Matrix) classification scores for known classes and test examples
+     * @param _uncertainties (NICE::Vector) predictive variance for each test input, if computed
+     */
+    void classify ( const std::vector< const NICE::SparseVector *> _examples,
+                    NICE::Vector & _results,
+                    NICE::Matrix & _scores,
+                    NICE::Vector & _uncertainties
+                  ) const;
+
     /**
      * @brief train this classifier using a given set of examples and a given set of binary label vectors 
      * @date 18-10-2012 (dd-mm-yyyy)

+ 91 - 31
matlab/GPHIKClassifierMex.cpp

@@ -117,7 +117,8 @@ NICE::Config parseParametersGPHIKClassifier(const mxArray *prhs[], int nrhs)
     /////////////////////////////////////////
     if ( (variable == "num_bins") || 
          (variable == "ils_max_iterations") ||
-         (variable == "eig_value_max_iterations")
+         (variable == "eig_value_max_iterations") ||
+         (variable == "downhillsimplex_max_iterations")
        )
     {
       if ( mxIsDouble( prhs[i+1] ) )
@@ -213,6 +214,7 @@ NICE::Config parseParametersGPHIKClassifier(const mxArray *prhs[], int nrhs)
         conf.sS("GPHIKClassifier", variable, value);
     }
 
+
     if(variable == "s_quantType")
     {
       string value = MatlabConversion::convertMatlabToString( prhs[i+1] );
@@ -356,46 +358,105 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
         {
             mexErrMsgTxt("Test: Unexpected arguments.");
         }
-        
-        //------------- read the data --------------
-
-        uint result;
-        NICE::SparseVector scores;
-        double uncertainty;        
 
         if ( mxIsSparse( prhs[2] ) )
         {
-            NICE::SparseVector * example;
-            example = new NICE::SparseVector ( MatlabConversion::convertSparseVectorToNice( prhs[2] ) );
-            classifier->classify ( example,  result, scores, uncertainty );
-            
-            //----------------- clean up -------------
-            delete example;
+            if ( MatlabConversion::isSparseDataAMatrix( prhs[2] ) )
+            {
+              //----------------- conversion -------------
+              std::vector< const NICE::SparseVector *> examplesTest;
+              examplesTest = MatlabConversion::convertSparseMatrixToNice( prhs[2] );
+
+              //----------------- classification -------------
+              NICE::Vector results;
+              NICE::Matrix scores;
+              NICE::Vector uncertainties;
+
+              classifier->classify ( examplesTest,  results, scores, uncertainties );
+
+              //----------------- clean up -------------
+              for ( std::vector< const NICE::SparseVector *>::iterator exIt = examplesTest.begin();
+                   exIt != examplesTest.end();
+                   exIt++
+              )
+              {
+                delete *exIt;
+              }
+
+              //----------------- output -------------
+              plhs[0] = MatlabConversion::convertVectorFromNice( results );
+
+              if(nlhs >= 2)
+              {
+                plhs[1] = MatlabConversion::convertMatrixFromNice( scores );
+              }
+              if(nlhs >= 3)
+              {
+                plhs[2] = MatlabConversion::convertVectorFromNice( uncertainties );
+              }
+              return;
+            }
+            else
+            {
+                //----------------- conversion -------------
+                NICE::SparseVector * example;
+                example = new NICE::SparseVector ( MatlabConversion::convertSparseVectorToNice( prhs[2] ) );
+
+                //----------------- classification -------------
+                uint result;
+                NICE::SparseVector scores;
+                double uncertainty;
+
+                classifier->classify ( example,  result, scores, uncertainty );
+
+
+                //----------------- clean up -------------
+                delete example;
+
+                //----------------- output -------------
+                plhs[0] = mxCreateDoubleScalar( result );
+
+                if(nlhs >= 2)
+                {
+                  plhs[1] = MatlabConversion::convertSparseVectorFromNice( scores, true  /*b_adaptIndex*/);
+                }
+                if(nlhs >= 3)
+                {
+                  plhs[2] = mxCreateDoubleScalar( uncertainty );
+                }
+                return;
+            }
         }
         else
         {
+            //----------------- conversion -------------
             NICE::Vector * example;
             example = new NICE::Vector ( MatlabConversion::convertDoubleVectorToNice(prhs[2]) );
+
+            //----------------- classification -------------
+            uint result;
+            NICE::SparseVector scores;
+            double uncertainty;
             classifier->classify ( example,  result, scores, uncertainty );
-            
+
             //----------------- clean up -------------
-            delete example;            
+            delete example;
+
+
+            //----------------- output -------------
+            plhs[0] = mxCreateDoubleScalar( result );
+
+            if(nlhs >= 2)
+            {
+              plhs[1] = MatlabConversion::convertSparseVectorFromNice( scores, true  /*b_adaptIndex*/);
+            }
+            if(nlhs >= 3)
+            {
+              plhs[2] = mxCreateDoubleScalar( uncertainty );
+            }
+            return;
         }
-          
-          
 
-          // output
-          plhs[0] = mxCreateDoubleScalar( result ); 
-                    
-          if(nlhs >= 2)
-          {
-            plhs[1] = MatlabConversion::convertSparseVectorFromNice( scores, true  /*b_adaptIndex*/);
-          }
-          if(nlhs >= 3)
-          {
-            plhs[2] = mxCreateDoubleScalar( uncertainty );          
-          }
-          return;
     }
     
     // Uncertainty prediction    
@@ -558,8 +619,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
             }
               
         }
-        
-        std::cerr << "Time for testing: " << testTime << std::endl;          
+
         
         // clean up
         if ( dataIsSparse )