Browse Source

stable support of new quantization techniques

Alexander Freytag 9 years ago
parent
commit
50b61955bf

+ 86 - 38
FMKGPHyperparameterOptimization.cpp

@@ -39,6 +39,10 @@
 #include "gp-hik-core/parameterizedFunctions/PFExp.h"
 #include "gp-hik-core/parameterizedFunctions/PFMKL.h"
 #include "gp-hik-core/parameterizedFunctions/PFWeightedDim.h"
+// 
+#include "gp-hik-core/quantization/Quantization1DAequiDist0To1.h"
+#include "gp-hik-core/quantization/Quantization1DAequiDist0ToMax.h"
+#include "gp-hik-core/quantization/QuantizationNDAequiDist0ToMax.h"
 
 
 
@@ -251,8 +255,8 @@ FMKGPHyperparameterOptimization::FMKGPHyperparameterOptimization( )
   this->b_debug = false;
   
   //stupid unneeded default values
-  this->i_binaryLabelPositive = -1;
-  this->i_binaryLabelNegative = -2;
+  this->i_binaryLabelPositive = 0;
+  this->i_binaryLabelNegative = 1;
   this->knownClasses.clear();  
   
   this->b_usePreviousAlphas = false;
@@ -280,8 +284,8 @@ FMKGPHyperparameterOptimization::FMKGPHyperparameterOptimization( const bool & _
   this->b_debug = false;
   
   //stupid unneeded default values
-  this->i_binaryLabelPositive = -1;
-  this->i_binaryLabelNegative = -2;
+  this->i_binaryLabelPositive = 0;
+  this->i_binaryLabelNegative = 1;
   this->knownClasses.clear();   
   
   this->b_usePreviousAlphas = false;
@@ -316,8 +320,8 @@ FMKGPHyperparameterOptimization::FMKGPHyperparameterOptimization ( const Config
   this->b_debug = false;
   
   //stupid unneeded default values
-  this->i_binaryLabelPositive = -1;
-  this->i_binaryLabelNegative = -2;
+  this->i_binaryLabelPositive = 0;
+  this->i_binaryLabelNegative = 1;
   this->knownClasses.clear();  
   
   this->b_usePreviousAlphas = false;
@@ -353,8 +357,8 @@ FMKGPHyperparameterOptimization::FMKGPHyperparameterOptimization ( const Config
   this->b_debug = false;
   
   //stupid unneeded default values
-  this->i_binaryLabelPositive = -1;
-  this->i_binaryLabelNegative = -2;
+  this->i_binaryLabelPositive = 0;
+  this->i_binaryLabelNegative = 1;
   this->knownClasses.clear();    
   
   this->b_usePreviousAlphas = false;
@@ -446,7 +450,28 @@ void FMKGPHyperparameterOptimization::initFromConfig ( const Config *_conf,
     int numBins = _conf->gI ( _confSection, "num_bins", 100 );
     if ( this->b_verbose )
       std::cerr << "FMKGPHyperparameterOptimization: quantization initialized with " << numBins << " bins." << std::endl;
-    this->q = new Quantization ( numBins );
+    
+    
+    std::string s_quantType = _conf->gS( _confSection, "s_quantType", "1d-aequi-0-1" );
+
+    if ( s_quantType == "1d-aequi-0-1" )
+    {
+      this->q = new NICE::Quantization1DAequiDist0To1 ( numBins );
+    }
+    else if ( s_quantType == "1d-aequi-0-max" )
+    {     
+      this->q = new NICE::Quantization1DAequiDist0ToMax ( numBins );
+    }
+    else if ( s_quantType == "nd-aequi-0-max" )
+    {
+      this->q = new NICE::QuantizationNDAequiDist0ToMax ( numBins );
+    }
+    else
+    {
+      fthrow(Exception, "Quantization type is unknown " << s_quantType);
+    }      
+      
+    
   }
   else
   {
@@ -642,7 +667,13 @@ void FMKGPHyperparameterOptimization::setFastMinKernel ( FastMinKernel * _fmk )
       this->fmk = NULL;
     }    
     this->fmk = _fmk;
-  }  
+  }
+  
+  //
+  if ( this->q != NULL )
+  {  
+    this->q->computeParametersFromData ( &(this->fmk->featureMatrix()) );
+  }
 }
 
 void FMKGPHyperparameterOptimization::setNrOfEigenvaluesToConsiderForVarApprox ( const int & _nrOfEigenvaluesToConsiderForVarApprox )
@@ -803,9 +834,9 @@ void FMKGPHyperparameterOptimization::computeMatricesAndLUTs ( const GPLikelihoo
     this->precomputedA[ i->first ] = A;
     this->precomputedB[ i->first ] = B;
 
-    if ( q != NULL )
+    if ( this->q != NULL )
     {
-      double *T = fmk->hik_prepare_alpha_multiplications_fast ( A, B, *q, pf );
+      double *T = fmk->hik_prepare_alpha_multiplications_fast ( A, B, this->q, this->pf );
       //just to be sure that we do not waste space here
       if ( precomputedT[ i->first ] != NULL )
         delete precomputedT[ i->first ];
@@ -1092,9 +1123,9 @@ void FMKGPHyperparameterOptimization::prepareVarianceApproximationRough()
   this->precomputedAForVarEst = AVar;
   this->precomputedAForVarEst.setIoUntilEndOfFile ( false );
 
-  if ( q != NULL )
+  if ( this->q != NULL )
   {   
-    double *T = this->fmk->hikPrepareLookupTableForKVNApproximation ( *q, pf );
+    double *T = this->fmk->hikPrepareLookupTableForKVNApproximation ( this->q, this->pf );
     this->precomputedTForVarEst = T;
   }
 }
@@ -1129,7 +1160,7 @@ uint FMKGPHyperparameterOptimization::classify ( const NICE::SparseVector & _xst
     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, *q, _xstar, beta );
+      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 );
@@ -1148,8 +1179,6 @@ uint FMKGPHyperparameterOptimization::classify ( const NICE::SparseVector & _xst
     _scores[ classno ] = beta;
   }
   _scores.setDim ( maxClassNo + 1 );
-  std::cerr << "_scores : " << std::endl;
-  _scores.store ( std::cerr ) ;
   
   if ( this->precomputedA.size() > 1 )
   { // multi-class classification
@@ -1157,7 +1186,6 @@ uint FMKGPHyperparameterOptimization::classify ( const NICE::SparseVector & _xst
   }
   else if ( this->knownClasses.size() == 2 ) // binary setting
   {      
-    std::cerr << "i_binaryLabelNegative: " << i_binaryLabelNegative << " i_binaryLabelPositive: " << i_binaryLabelPositive<< std::endl;
     _scores[ this->i_binaryLabelNegative ] = -_scores[ this->i_binaryLabelPositive ];     
     return _scores[ this->i_binaryLabelPositive ] <= 0.0 ? this->i_binaryLabelNegative : this->i_binaryLabelPositive;
   }
@@ -1190,7 +1218,7 @@ uint FMKGPHyperparameterOptimization::classify ( const NICE::Vector & _xstar,
     {
       std::map<uint, double *>::const_iterator j = this->precomputedT.find ( classno );
       double *T = j->second;
-      this->fmk->hik_kernel_sum_fast ( T, *q, _xstar, beta );
+      this->fmk->hik_kernel_sum_fast ( T, this->q, _xstar, beta );
     }
     else
     {
@@ -1253,13 +1281,13 @@ void FMKGPHyperparameterOptimization::computePredictiveVarianceApproximateRough
   // ---------------- compute the approximation of the second term --------------------
   double normKStar;
 
-  if ( q != NULL )
+  if ( this->q != NULL )
   {
     if ( precomputedTForVarEst == NULL )
     {
       fthrow ( Exception, "The precomputed LUT for uncertainty prediction is NULL...have you prepared the uncertainty prediction? Aborting..." );
     }
-    fmk->hikComputeKVNApproximationFast ( precomputedTForVarEst, *q, _x, normKStar );
+    fmk->hikComputeKVNApproximationFast ( precomputedTForVarEst, this->q, _x, normKStar );
   }
   else
   {
@@ -1276,11 +1304,7 @@ void FMKGPHyperparameterOptimization::computePredictiveVarianceApproximateRough
 void FMKGPHyperparameterOptimization::computePredictiveVarianceApproximateFine ( const NICE::SparseVector & _x, 
                                                                                  double & _predVariance 
                                                                                ) const
-{
-  
-  std::cerr << " security check! " << std::endl;
-  std::cerr << "b_debug: " << this->b_debug << std::endl;
-  
+{  
   if ( this->b_debug )
   {
     std::cerr << "FMKGPHyperparameterOptimization::computePredictiveVarianceApproximateFine" << std::endl;
@@ -1468,13 +1492,13 @@ void FMKGPHyperparameterOptimization::computePredictiveVarianceApproximateRough
   // ---------------- compute the approximation of the second term --------------------
   double normKStar;
 
-  if ( q != NULL )
+  if ( this->q != NULL )
   {
     if ( precomputedTForVarEst == NULL )
     {
       fthrow ( Exception, "The precomputed LUT for uncertainty prediction is NULL...have you prepared the uncertainty prediction? Aborting..." );
     }
-    fmk->hikComputeKVNApproximationFast ( precomputedTForVarEst, *q, x, normKStar );
+    fmk->hikComputeKVNApproximationFast ( precomputedTForVarEst, this->q, x, normKStar );
   }
   else
   {
@@ -1482,7 +1506,7 @@ void FMKGPHyperparameterOptimization::computePredictiveVarianceApproximateRough
     {
       fthrow ( Exception, "The precomputedAForVarEst is empty...have you trained this classifer? Aborting..." );
     }    
-    fmk->hikComputeKVNApproximation ( precomputedAForVarEst, x, normKStar, pf );
+    fmk->hikComputeKVNApproximation ( precomputedAForVarEst, x, normKStar, this->pf );
   }
 
   predVariance = kSelf - ( 1.0 / eigenMax[0] )* normKStar;
@@ -1635,7 +1659,7 @@ void FMKGPHyperparameterOptimization::restore ( std::istream & _is,
   if ( _is.good() )
   {
     if ( b_restoreVerbose ) 
-      std::cerr << " in FMKGP restore" << std::endl;
+      std::cerr << " in FMKGPHyperparameterOptimization restore" << std::endl;
     
     std::string tmp;
     _is >> tmp; //class name 
@@ -1729,7 +1753,28 @@ void FMKGPHyperparameterOptimization::restore ( std::istream & _is,
         {   
           if ( this->q != NULL )
             delete this->q;
-          this->q = new Quantization();
+          
+          std::string s_quantType;
+           _is >> s_quantType;
+           s_quantType = this->removeStartTag ( s_quantType );
+          
+          if ( s_quantType == "Quantization1DAequiDist0To1" )
+          {
+            this->q = new NICE::Quantization1DAequiDist0To1();
+          }
+          else if ( s_quantType == "Quantization1DAequiDist0ToMax" )
+          {           
+            this->q = new NICE::Quantization1DAequiDist0ToMax ( );
+          }
+          else if ( s_quantType == "QuantizationNDAequiDist0ToMax" )
+          {
+            this->q = new NICE::QuantizationNDAequiDist0ToMax ( );
+          }
+          else
+          {
+            fthrow(Exception, "Quantization type is unknown " << s_quantType);
+          }
+               
           this->q->restore ( _is, _format );
         }
         else
@@ -1763,14 +1808,17 @@ void FMKGPHyperparameterOptimization::restore ( std::istream & _is,
           throw;
         } 
         
-        std::string transform = this->removeStartTag ( tmp );
-        
+        std::string transform ( this->removeStartTag( tmp ) );
 
         if ( transform == "PFAbsExp" )
         {
-          this->pf = new PFAbsExp ();
+          this->pf = new NICE::PFAbsExp ();
         } else if ( transform == "PFExp" ) {
-          this->pf = new PFExp ();
+          this->pf = new NICE::PFExp ();
+        }
+        else if ( transform == "PFIdentity" )
+        {
+          this->pf = new NICE::PFIdentity( );          
         } else {
           fthrow(Exception, "Transformation type is unknown " << transform);
         }
@@ -1796,7 +1844,7 @@ void FMKGPHyperparameterOptimization::restore ( std::istream & _is,
           PrecomputedType pct;
           pct.setIoUntilEndOfFile ( false );
           pct.restore ( _is, _format );
-          precomputedA.insert ( std::pair<uint, PrecomputedType> ( nr, pct ) );
+          this->precomputedA.insert ( std::pair<uint, PrecomputedType> ( nr, pct ) );
         }
         
         _is >> tmp; // end of block 
@@ -1818,7 +1866,7 @@ void FMKGPHyperparameterOptimization::restore ( std::istream & _is,
           PrecomputedType pct;
           pct.setIoUntilEndOfFile ( false );
           pct.restore ( _is, _format );
-          precomputedB.insert ( std::pair<uint, PrecomputedType> ( nr, pct ) );
+          this->precomputedB.insert ( std::pair<uint, PrecomputedType> ( nr, pct ) );
         }    
         
         _is >> tmp; // end of block 
@@ -2220,7 +2268,7 @@ void FMKGPHyperparameterOptimization::store ( std::ostream & _os,
     if ( q != NULL )
     {
       _os << "NOTNULL" << std::endl;
-      q->store ( _os, _format );
+      this->q->store ( _os, _format );
     }
     else
     {

+ 3 - 4
FMKGPHyperparameterOptimization.h

@@ -28,9 +28,8 @@
 #include "gp-hik-core/GPLikelihoodApprox.h"
 #include "gp-hik-core/IKMLinearCombination.h"
 #include "gp-hik-core/OnlineLearnable.h"
-#include "gp-hik-core/Quantization.h"
-
 
+#include "gp-hik-core/quantization/Quantization.h"
 #include "gp-hik-core/parameterizedFunctions/ParameterizedFunction.h"
 
 namespace NICE {
@@ -103,9 +102,9 @@ class FMKGPHyperparameterOptimization : public NICE::Persistent, public NICE::On
     NICE::Vector labels; 
     
     //! store the class number of the positive class (i.e., larger class no), only used in binary settings
-    int i_binaryLabelPositive;
+    uint i_binaryLabelPositive;
     //! store the class number of the negative class (i.e., smaller class no), only used in binary settings
-    int i_binaryLabelNegative;
+    uint i_binaryLabelNegative;
     
     //! contains all class numbers of the currently known classes
     std::set<uint> knownClasses;

+ 131 - 89
FastMinKernel.cpp

@@ -250,27 +250,35 @@ void FastMinKernel::hik_prepare_alpha_multiplications(const NICE::Vector & _alph
 
 double *FastMinKernel::hik_prepare_alpha_multiplications_fast(const NICE::VVector & _A, 
                                                               const NICE::VVector & _B,
-                                                              const Quantization & _q,
+                                                              const Quantization * _q,
                                                               const ParameterizedFunction *_pf 
                                                              ) const
 {
   //NOTE keep in mind: for doing this, we already have precomputed A and B using hik_prepare_alpha_multiplications!
   
   // number of quantization bins
-  uint hmax = _q.size();
+  uint hmax = _q->getNumberOfBins();
 
   // store (transformed) prototypes
-  double *prototypes = new double [ hmax ];
-  for ( uint i = 0 ; i < hmax ; i++ )
-    if ( _pf != NULL ) {
-      // FIXME: the transformed prototypes could change from dimension to another dimension
-      // We skip this flexibility ...but it should be changed in the future
-      prototypes[i] = _pf->f ( 1, _q.getPrototype(i) );
-    } else {
-      prototypes[i] = _q.getPrototype(i);
-    }
-
+  double * prototypes   = new double [ hmax * this->ui_d ];
+  double * p_prototypes = prototypes;
 
+  for (uint dim = 0; dim < this->ui_d; dim++)  
+  {
+    for ( uint i = 0 ; i < hmax ; i++ )
+    {
+      if ( _pf != NULL )
+      {
+        *p_prototypes = _pf->f ( dim, _q->getPrototype( i, dim ) );
+      } else
+      {
+        *p_prototypes = _q->getPrototype( i, dim );
+      }
+      
+      p_prototypes++;
+    }
+  } 
+  
   // creating the lookup table as pure C, which might be beneficial
   // for fast evaluation
   double *Tlookup = new double [ hmax * this->ui_d ];
@@ -294,7 +302,7 @@ double *FastMinKernel::hik_prepare_alpha_multiplications_fast(const NICE::VVecto
     uint index = 0;
     // we use the quantization of the original features! the transformed feature were
     // already used to calculate A and B, this of course assumes monotonic functions!!!
-    uint qBin = _q.quantize ( i->first ); 
+    uint qBin = _q->quantize ( i->first, dim ); 
 
     // the next loop is linear in max(hmax, n)
     // REMARK: this could be changed to hmax*log(n), when
@@ -302,7 +310,7 @@ double *FastMinKernel::hik_prepare_alpha_multiplications_fast(const NICE::VVecto
     
     for (uint j = 0; j < hmax; j++)
     {
-      double fval = prototypes[j];
+      double fval = prototypes[ dim*hmax + j ];
       double t;
 
       if (  (index == 0) && (j < qBin) ) {
@@ -319,7 +327,7 @@ double *FastMinKernel::hik_prepare_alpha_multiplications_fast(const NICE::VVecto
           i++;
 
           if ( i->first !=  iPredecessor->first )
-            qBin = _q.quantize ( i->first );
+            qBin = _q->quantize ( i->first, dim );
         }
         // compute current element in the lookup table and keep in mind that
         // index is the next element and not the previous one
@@ -344,23 +352,32 @@ double *FastMinKernel::hik_prepare_alpha_multiplications_fast(const NICE::VVecto
 }
 
 double *FastMinKernel::hikPrepareLookupTable(const NICE::Vector & _alpha, 
-                                             const Quantization & _q, 
+                                             const Quantization * _q, 
                                              const ParameterizedFunction *_pf 
                                             ) const
 {
   // number of quantization bins
-  uint hmax = _q.size();
+  uint hmax = _q->getNumberOfBins();
 
   // store (transformed) prototypes
-  double *prototypes = new double [ hmax ];
-  for ( uint i = 0 ; i < hmax ; i++ )
-    if ( _pf != NULL ) {
-      // FIXME: the transformed prototypes could change from dimension to another dimension
-      // We skip this flexibility ...but it should be changed in the future
-      prototypes[i] = _pf->f ( 1, _q.getPrototype(i) );
-    } else {
-      prototypes[i] = _q.getPrototype(i);
+  double * prototypes   = new double [ hmax * this->ui_d ];
+  double * p_prototypes = prototypes;
+
+  for (uint dim = 0; dim < this->ui_d; dim++)  
+  {
+    for ( uint i = 0 ; i < hmax ; i++ )
+    {
+      if ( _pf != NULL )
+      {
+        *p_prototypes = _pf->f ( dim, _q->getPrototype( i, dim ) );
+      } else
+      {
+        *p_prototypes = _q->getPrototype( i, dim );
+      }
+      
+      p_prototypes++;
     }
+  }
 
   // creating the lookup table as pure C, which might be beneficial
   // for fast evaluation
@@ -391,7 +408,7 @@ double *FastMinKernel::hikPrepareLookupTable(const NICE::Vector & _alpha,
     uint index = 0;
     
     // we use the quantization of the original features! Nevetheless, the resulting lookupTable is computed using the transformed ones
-    uint qBin = _q.quantize ( i->first ); 
+    uint qBin = _q->quantize ( i->first, dim ); 
     
     double alpha_sum(0.0);
     double alpha_times_x_sum(0.0);
@@ -400,7 +417,7 @@ double *FastMinKernel::hikPrepareLookupTable(const NICE::Vector & _alpha,
     
     for (uint j = 0; j < hmax; j++)
     {
-      double fval = prototypes[j];
+      double fval = prototypes[ dim*hmax + j ];
       double t;
 
       if (  (index == 0) && (j < qBin) ) {
@@ -423,7 +440,7 @@ double *FastMinKernel::hikPrepareLookupTable(const NICE::Vector & _alpha,
           i++;
 
           if ( i->first !=  iPredecessor->first )
-            qBin = _q.quantize ( i->first );
+            qBin = _q->quantize ( i->first, dim );
         }
         // compute current element in the lookup table and keep in mind that
         // index is the next element and not the previous one
@@ -454,7 +471,7 @@ void FastMinKernel::hikUpdateLookupTable(double * _T,
                                          const double & _alphaNew, 
                                          const double & _alphaOld, 
                                          const uint & _idx, 
-                                         const Quantization & _q, 
+                                         const Quantization * _q, 
                                          const ParameterizedFunction *_pf 
                                         ) const
 {
@@ -466,18 +483,27 @@ void FastMinKernel::hikUpdateLookupTable(double * _T,
   }
   
   // number of quantization bins
-  uint hmax = _q.size();
+  uint hmax = _q->getNumberOfBins();
 
   // store (transformed) prototypes
-  double *prototypes = new double [ hmax ];
-  for ( uint i = 0 ; i < hmax ; i++ )
-    if ( _pf != NULL ) {
-      // FIXME: the transformed prototypes could change from dimension to another dimension
-      // We skip this flexibility ...but it should be changed in the future
-      prototypes[i] = _pf->f ( 1, _q.getPrototype(i) );
-    } else {
-      prototypes[i] = _q.getPrototype(i);
+  double * prototypes   = new double [ hmax * this->ui_d ];
+  double * p_prototypes = prototypes;
+
+  for (uint dim = 0; dim < this->ui_d; dim++)  
+  {
+    for ( uint i = 0 ; i < hmax ; i++ )
+    {
+      if ( _pf != NULL )
+      {
+        *p_prototypes = _pf->f ( dim, _q->getPrototype( i, dim ) );
+      } else
+      {
+        *p_prototypes = _q->getPrototype( i, dim );
+      }
+      
+      p_prototypes++;
     }
+  }
   
   double diffOfAlpha(_alphaNew - _alphaOld);
   
@@ -494,10 +520,10 @@ void FastMinKernel::hikUpdateLookupTable(double * _T,
     for (uint j = 0; j < hmax; j++)
     {
         double fval;
-        uint q_bin = _q.quantize(x_i);
+        uint q_bin = _q->quantize( x_i, dim );
         
         if ( q_bin > j )
-          fval = prototypes[j];
+          fval = prototypes[ dim*hmax + j ];
         else
           fval = x_i;      
         
@@ -575,7 +601,7 @@ void FastMinKernel::hik_kernel_multiply(const NICE::VVector & _A,
 }
 
 void FastMinKernel::hik_kernel_multiply_fast(const double *_Tlookup, 
-                                             const Quantization & _q, 
+                                             const Quantization * _q, 
                                              const NICE::Vector & _alpha, 
                                              NICE::Vector & _beta) const
 {
@@ -593,8 +619,8 @@ void FastMinKernel::hik_kernel_multiply_fast(const double *_Tlookup,
     {
       const SortedVectorSparse<double>::dataelement & de = i->second;
       uint feat = de.first;
-      uint qBin = _q.quantize(i->first);
-      _beta[feat] += _Tlookup[dim*_q.size() + qBin];
+      uint qBin = _q->quantize( i->first, dim );
+      _beta[feat] += _Tlookup[dim*_q->size() + qBin];
     }
   }
   
@@ -752,7 +778,7 @@ void FastMinKernel::hik_kernel_sum(const NICE::VVector & _A,
 }
 
 void FastMinKernel::hik_kernel_sum_fast(const double *_Tlookup, 
-                                        const Quantization & _q, 
+                                        const Quantization * _q, 
                                         const NICE::Vector & _xstar, 
                                         double & _beta
                                        ) const
@@ -768,14 +794,14 @@ void FastMinKernel::hik_kernel_sum_fast(const double *_Tlookup,
   for ( uint dim = 0; dim < this->ui_d; dim++)
   {
     double v = _xstar[dim];
-    uint qBin = _q.quantize(v);
+    uint qBin = _q->quantize( v, dim );
     
-    _beta += _Tlookup[dim*_q.size() + qBin];
+    _beta += _Tlookup[dim*_q->size() + qBin];
   }
 }
 
 void FastMinKernel::hik_kernel_sum_fast(const double *_Tlookup, 
-                                        const Quantization & _q, 
+                                        const Quantization * _q, 
                                         const NICE::SparseVector & _xstar, 
                                         double & _beta
                                        ) const
@@ -789,15 +815,15 @@ void FastMinKernel::hik_kernel_sum_fast(const double *_Tlookup,
   {
     uint dim = i->first;
     double v = i->second;
-    uint qBin = _q.quantize(v);
+    uint qBin = _q->quantize( v, dim );
     
-    _beta += _Tlookup[dim*_q.size() + qBin];
+    _beta += _Tlookup[dim*_q->size() + qBin];
   }
 }
 
 double *FastMinKernel::solveLin(const NICE::Vector & _y, 
                                 NICE::Vector & _alpha,
-                                const Quantization & _q, 
+                                const Quantization * _q, 
                                 const ParameterizedFunction *_pf, 
                                 const bool & _useRandomSubsets, 
                                 uint _maxIterations, 
@@ -811,7 +837,7 @@ double *FastMinKernel::solveLin(const NICE::Vector & _y,
   bool verboseMinimal ( false );
   
   // number of quantization bins
-  uint hmax = _q.size();
+  uint hmax = _q->size();
   
   NICE::Vector diagonalElements(_y.size(),0.0);
   this->X_sorted.hikDiagonalElements(diagonalElements);
@@ -877,7 +903,7 @@ double *FastMinKernel::solveLin(const NICE::Vector & _y,
         for (uint j = 0; j < this->ui_d; j++)
         {
           x_i = this->X_sorted(j,perm[i]);
-          pseudoResidual(perm[i]) += Tlookup[j*hmax + _q.quantize(x_i)];
+          pseudoResidual(perm[i]) += Tlookup[j*hmax + _q->quantize( x_i, j )];
         }
       
         //NOTE: this threshhold could also be a parameter of the function call
@@ -928,7 +954,7 @@ double *FastMinKernel::solveLin(const NICE::Vector & _y,
         for (uint j = 0; j < this->ui_d; j++)
         {
           x_i = this->X_sorted(j,i);
-          pseudoResidual(i) += Tlookup[j*hmax + _q.quantize(x_i)];
+          pseudoResidual(i) += Tlookup[j*hmax + _q->quantize( x_i, j )];
         }
       
         //NOTE: this threshhold could also be a parameter of the function call
@@ -1132,24 +1158,33 @@ void FastMinKernel::hikPrepareKVNApproximation(NICE::VVector & _A) const
 }
 
 double * FastMinKernel::hikPrepareKVNApproximationFast(NICE::VVector & _A, 
-                                                       const Quantization & _q, 
+                                                       const Quantization * _q, 
                                                        const ParameterizedFunction *_pf ) const
 {
   //NOTE keep in mind: for doing this, we already have precomputed A using hikPrepareSquaredKernelVector!
   
   // number of quantization bins
-  uint hmax = _q.size();
+  uint hmax = _q->getNumberOfBins();
 
   // store (transformed) prototypes
-  double *prototypes = new double [ hmax ];
-  for ( uint i = 0 ; i < hmax ; i++ )
-    if ( _pf != NULL ) {
-      // FIXME: the transformed prototypes could change from dimension to another dimension
-      // We skip this flexibility ...but it should be changed in the future
-      prototypes[i] = _pf->f ( 1, _q.getPrototype(i) );
-    } else {
-      prototypes[i] = _q.getPrototype(i);
+  double *prototypes = new double [ hmax * this->ui_d ];
+  double * p_prototypes = prototypes;
+  
+  for (uint dim = 0; dim < this->ui_d; dim++)  
+  {
+    for ( uint i = 0 ; i < hmax ; i++ )
+    {
+      if ( _pf != NULL )
+      {
+        *p_prototypes = _pf->f ( dim, _q->getPrototype( i, dim ) );
+      } else
+      {
+        *p_prototypes = _q->getPrototype( i, dim );
+      }
+      
+      p_prototypes++;
     }
+  }
 
 
   // creating the lookup table as pure C, which might be beneficial
@@ -1172,7 +1207,7 @@ double * FastMinKernel::hikPrepareKVNApproximationFast(NICE::VVector & _A,
     uint index = 0;
     // we use the quantization of the original features! the transformed feature were
     // already used to calculate A and B, this of course assumes monotonic functions!!!
-    uint qBin = _q.quantize ( i->first ); 
+    uint qBin = _q->quantize ( i->first, dim ); 
 
     // the next loop is linear in max(hmax, n)
     // REMARK: this could be changed to hmax*log(n), when
@@ -1181,7 +1216,7 @@ double * FastMinKernel::hikPrepareKVNApproximationFast(NICE::VVector & _A,
     
     for (uint j = 0; j < hmax; j++)
     {
-      double fval = prototypes[j];
+      double fval = prototypes[ dim*hmax + j];
       double t;
 
       if (  (index == 0) && (j < qBin) ) {
@@ -1198,7 +1233,7 @@ double * FastMinKernel::hikPrepareKVNApproximationFast(NICE::VVector & _A,
           i++;
 
           if ( i->first !=  iPredecessor->first )
-            qBin = _q.quantize ( i->first );
+            qBin = _q->quantize ( i->first, dim );
         }
         // compute current element in the lookup table and keep in mind that
         // index is the next element and not the previous one
@@ -1209,9 +1244,7 @@ double * FastMinKernel::hikPrepareKVNApproximationFast(NICE::VVector & _A,
           t = _A[dim][index];
         } else {
           // standard case
-          t =  _A[dim][index-1] + pow( fval, 2 ) * (this->ui_n-nrZeroIndices-(index) );
-//           A[dim][index-1] + fval * (n-nrZeroIndices-(index) );//fval*fval * (n-nrZeroIndices-(index-1) );
-          
+          t =  _A[dim][index-1] + pow( fval, 2 ) * (this->ui_n-nrZeroIndices-(index) );          
         }
       }
 
@@ -1224,23 +1257,32 @@ double * FastMinKernel::hikPrepareKVNApproximationFast(NICE::VVector & _A,
   return Tlookup;  
 }
 
-double* FastMinKernel::hikPrepareLookupTableForKVNApproximation(const Quantization & _q,
+double* FastMinKernel::hikPrepareLookupTableForKVNApproximation(const Quantization * _q,
                                                                 const ParameterizedFunction *_pf 
                                                                ) const
 {
   // number of quantization bins
-  uint hmax = _q.size();
+  uint hmax = _q->getNumberOfBins();
 
   // store (transformed) prototypes
-  double *prototypes = new double [ hmax ];
-  for ( uint i = 0 ; i < hmax ; i++ )
-    if ( _pf != NULL ) {
-      // FIXME: the transformed prototypes could change from dimension to another dimension
-      // We skip this flexibility ...but it should be changed in the future
-      prototypes[i] = _pf->f ( 1, _q.getPrototype(i) );
-    } else {
-      prototypes[i] = _q.getPrototype(i);
+  double *prototypes = new double [ hmax * this->ui_d ];
+  double * p_prototypes = prototypes;
+
+  for (uint dim = 0; dim < this->ui_d; dim++)  
+  {
+    for ( uint i = 0 ; i < hmax ; i++ )
+    {
+      if ( _pf != NULL )
+      {
+        *p_prototypes = _pf->f ( dim, _q->getPrototype( i, dim ) );
+      } else
+      {
+        *p_prototypes = _q->getPrototype( i, dim );
+      }
+      
+      p_prototypes++;
     }
+  }    
 
   // creating the lookup table as pure C, which might be beneficial
   // for fast evaluation
@@ -1262,13 +1304,13 @@ double* FastMinKernel::hikPrepareLookupTableForKVNApproximation(const Quantizati
     uint index = 0;
     
     // we use the quantization of the original features! Nevetheless, the resulting lookupTable is computed using the transformed ones
-    uint qBin = _q.quantize ( i->first ); 
+    uint qBin = _q->quantize ( i->first, dim ); 
     
     double sum(0.0);
     
     for (uint j = 0; j < hmax; j++)
     {
-      double fval = prototypes[j];
+      double fval = prototypes[ dim*hmax + j];
       double t;
 
       if (  (index == 0) && (j < qBin) ) {
@@ -1287,7 +1329,7 @@ double* FastMinKernel::hikPrepareLookupTableForKVNApproximation(const Quantizati
           i++;
 
           if ( i->first !=  iPredecessor->first )
-            qBin = _q.quantize ( i->first );
+            qBin = _q->quantize ( i->first, dim );
         }
         // compute current element in the lookup table and keep in mind that
         // index is the next element and not the previous one
@@ -1374,7 +1416,7 @@ void FastMinKernel::hikComputeKVNApproximation(const NICE::VVector & _A,
 }
 
 void FastMinKernel::hikComputeKVNApproximationFast(const double *_Tlookup, 
-                                                   const Quantization & _q, 
+                                                   const Quantization * _q, 
                                                    const NICE::SparseVector & _xstar, 
                                                    double & _norm
                                                   ) const
@@ -1387,9 +1429,9 @@ void FastMinKernel::hikComputeKVNApproximationFast(const double *_Tlookup,
     double v = i->second;
     // we do not need a parameterized function here, since the quantizer works on the original feature values. 
     // nonetheless, the lookup table was created using the parameterized function    
-    uint qBin = _q.quantize(v);
+    uint qBin = _q->quantize( v, dim );
     
-    _norm += _Tlookup[dim*_q.size() + qBin];
+    _norm += _Tlookup[dim*_q->size() + qBin];
   }  
 }
 
@@ -1517,7 +1559,7 @@ void FastMinKernel::hikComputeKVNApproximation(const NICE::VVector & _A,
 }
 
 void FastMinKernel::hikComputeKVNApproximationFast(const double *_Tlookup, 
-                                                   const Quantization & _q, 
+                                                   const Quantization * _q, 
                                                    const NICE::Vector & _xstar, 
                                                    double & _norm
                                                   ) const
@@ -1525,14 +1567,14 @@ void FastMinKernel::hikComputeKVNApproximationFast(const double *_Tlookup,
   _norm = 0.0;
   // runtime is O(d) if the quantizer is O(1)
   uint dim ( 0 );
-  for (Vector::const_iterator i = _xstar.begin(); i != _xstar.end(); i++, dim++ )
+  for ( NICE::Vector::const_iterator i = _xstar.begin(); i != _xstar.end(); i++, dim++ )
   {
     double v = *i;
     // we do not need a parameterized function here, since the quantizer works on the original feature values. 
     // nonetheless, the lookup table was created using the parameterized function    
-    uint qBin = _q.quantize(v);
+    uint qBin = _q->quantize( v, dim );
     
-    _norm += _Tlookup[dim*_q.size() + qBin];
+    _norm += _Tlookup[dim*_q->size() + qBin];
   }  
 }
 

+ 13 - 12
FastMinKernel.h

@@ -24,7 +24,8 @@
 // gp-hik-core includes
 #include "gp-hik-core/FeatureMatrixT.h"
 #include "gp-hik-core/OnlineLearnable.h"
-#include "gp-hik-core/Quantization.h"
+// 
+#include "gp-hik-core/quantization/Quantization.h"
 #include "gp-hik-core/parameterizedFunctions/ParameterizedFunction.h"
 
 namespace NICE {
@@ -229,7 +230,7 @@ namespace NICE {
                                NICE::Vector & _beta
                               ) const;
       void hik_kernel_multiply_fast(const double *_Tlookup, 
-                                    const Quantization & _q, 
+                                    const Quantization * _q, 
                                     const NICE::Vector & _alpha, 
                                     NICE::Vector & _beta
                                    ) const;
@@ -283,7 +284,7 @@ namespace NICE {
       * @param beta result of the calculation
       */
       void hik_kernel_sum_fast(const double* _Tlookup, 
-                               const Quantization & _q, 
+                               const Quantization * _q, 
                                const NICE::Vector & _xstar, 
                                double & _beta
                               ) const;
@@ -299,7 +300,7 @@ namespace NICE {
       */      
 
       void hik_kernel_sum_fast(const double *_Tlookup, 
-                               const Quantization & _q, 
+                               const Quantization * _q, 
                                const NICE::SparseVector & _xstar, 
                                double & _beta
                               ) const;
@@ -318,7 +319,7 @@ namespace NICE {
       */
       double *hik_prepare_alpha_multiplications_fast(const NICE::VVector & _A, 
                                                      const NICE::VVector & _B, 
-                                                     const Quantization & _q, 
+                                                     const Quantization * _q, 
                                                      const ParameterizedFunction *_pf = NULL 
                                                     ) const;
       
@@ -334,7 +335,7 @@ namespace NICE {
       * T[dim*q.size() + j], where j is a bin entry corresponding to quantization q.
       */
       double* hikPrepareLookupTable(const NICE::Vector & _alpha, 
-                                    const Quantization & _q, 
+                                    const Quantization * _q, 
                                     const ParameterizedFunction *_pf = NULL
                                    ) const;
 
@@ -353,7 +354,7 @@ namespace NICE {
                                 const double & _alphaNew, 
                                 const double & _alphaOld, 
                                 const uint & _idx, 
-                                const Quantization & _q, 
+                                const Quantization * _q, 
                                 const ParameterizedFunction *pf 
                                ) const;
 
@@ -382,7 +383,7 @@ namespace NICE {
        **/
       double *solveLin(const NICE::Vector & _y, 
                        NICE::Vector & _alpha, 
-                       const Quantization & _q, 
+                       const Quantization * _q, 
                        const ParameterizedFunction *_pf = NULL, 
                        const bool & _useRandomSubsets = true, 
                        uint _maxIterations = 10000, 
@@ -420,7 +421,7 @@ namespace NICE {
       * @return C standard vector representing a q.size()*d double matrix and the lookup table T. Elements can be accessed with
       * T[dim*q.size() + j], where j is a bin entry corresponding to quantization q.
       */
-      double * hikPrepareKVNApproximationFast(NICE::VVector & _A, const Quantization & _q, const ParameterizedFunction *_pf = NULL ) const;
+      double * hikPrepareKVNApproximationFast(NICE::VVector & _A, const Quantization * _q, const ParameterizedFunction *_pf = NULL ) const;
       
       /**
       * @brief Compute lookup table for HIK calculation of |k_*|^2 assuming quantized test samples ( equals hikPrepareSquaredKernelVector + hikPrepareSquaredKernelVectorFast, but is faster). Approximation does not considere mixed terms between dimensions.
@@ -433,7 +434,7 @@ namespace NICE {
       * @return C standard vector representing a q.size()*d double matrix and the lookup table T. Elements can be accessed with
       * T[dim*q.size() + j], where j is a bin entry corresponding to quantization q.
       */
-      double* hikPrepareLookupTableForKVNApproximation(const Quantization & _q, const ParameterizedFunction *_pf = NULL) const;
+      double* hikPrepareLookupTableForKVNApproximation(const Quantization * _q, const ParameterizedFunction *_pf = NULL) const;
       
     //////////////////////////////////////////
     // variance computation: sparse inputs
@@ -461,7 +462,7 @@ namespace NICE {
       * @param xstar feature vector (indirect k_*)
       * @param norm result of the calculation
       */
-      void hikComputeKVNApproximationFast(const double *_Tlookup, const Quantization & _q, const NICE::SparseVector & _xstar, double & _norm ) const;
+      void hikComputeKVNApproximationFast(const double *_Tlookup, const Quantization * _q, const NICE::SparseVector & _xstar, double & _norm ) const;
 
       /**
       * @brief Compute the kernel vector k_* between training examples and test example. Runtime. O(n \times D). Exploiting sparsity
@@ -499,7 +500,7 @@ namespace NICE {
       * @param xstar feature vector (indirect k_*)
       * @param norm result of the calculation
       */
-      void hikComputeKVNApproximationFast(const double *_Tlookup, const Quantization & _q, const NICE::Vector & _xstar, double & _norm ) const;      
+      void hikComputeKVNApproximationFast(const double *_Tlookup, const Quantization * _q, const NICE::Vector & _xstar, double & _norm ) const;      
       
       /**
       * @brief Compute the kernel vector k_* between training examples and test example. Runtime. O(n \times D). Does not exploit sparsity - deprecated!

+ 7 - 0
FeatureMatrixT.h

@@ -293,6 +293,13 @@ template<class T> class FeatureMatrixT : public NICE::Persistent
                                     const T & _elem, 
                                     uint & _position
                                    ) const;
+                                   
+                                   
+    T getLargestValue ( const bool & _getTransformedValue = false ) const;
+    
+    NICE::VectorT<T> getLargestValuePerDimension ( const double & _quantile=1.0,
+                                                              const bool & _getTransformedValue = false
+                                                            ) const;
     
     //------------------------------------------------------
     // high level methods

+ 40 - 0
FeatureMatrixT.tcc

@@ -503,6 +503,46 @@ namespace NICE {
         _position += this->features[_dim].getZeros();
     }
     
+    template <typename T>
+    T FeatureMatrixT<T>::getLargestValue ( const bool & _getTransformedValue ) const
+    {
+      T vmax = (T) 0; 
+      T vtmp = (T) 0;
+      
+      uint tmp ( 0 );
+      for ( typename std::vector<NICE::SortedVectorSparse<T> >::const_iterator it = this->features.begin();
+            it != this->features.end();
+            it++, tmp++
+      )
+      {
+        vtmp = it->getLargestValueUnsafe( 1.0 /*quantile, we are interested in the largest value*/, _getTransformedValue );
+        if ( vtmp > vmax )
+        {
+          vmax = vtmp;
+        }
+      }
+      return vmax;
+    }
+    
+    template <typename T>
+    NICE::VectorT<T> FeatureMatrixT<T>::getLargestValuePerDimension ( const double & _quantile, 
+                                                                      const bool & _getTransformedValue
+                                                                    ) const     
+    {
+      NICE::VectorT<T> vmax ( this->get_d() );
+      
+      uint tmp ( 0 );      
+      typename NICE::VectorT<T>::iterator vmaxIt = vmax.begin();
+      for ( typename std::vector<NICE::SortedVectorSparse<T> >::const_iterator it = this->features.begin();
+            it != this->features.end();
+            it++, vmaxIt++, tmp++
+      )
+      {       
+        *vmaxIt = it->getLargestValueUnsafe( _quantile, _getTransformedValue );
+      }    
+      return vmax;
+    }
+    
     //------------------------------------------------------
     // high level methods
     //------------------------------------------------------

+ 11 - 13
GMHIKernel.cpp

@@ -34,7 +34,7 @@ GMHIKernel::~GMHIKernel()
 void GMHIKernel::multiply (NICE::Vector & y, const NICE::Vector & x) const
 {
   //do we want to use any quantization at all?
-  if (q != NULL)
+  if ( this->q != NULL )
   {
     double *T;
     if (useOldPreparation)
@@ -43,13 +43,13 @@ void GMHIKernel::multiply (NICE::Vector & y, const NICE::Vector & x) const
       NICE::VVector B; 
       // prepare to calculate sum_i x_i K(x,x_i)
       fmk->hik_prepare_alpha_multiplications(x, A, B);
-      T = fmk->hik_prepare_alpha_multiplications_fast(A, B, *q, pf);
+      T = fmk->hik_prepare_alpha_multiplications_fast(A, B, this->q, pf);
     }
     else
     {
-      T = fmk->hikPrepareLookupTable(x, *q, pf );
+      T = fmk->hikPrepareLookupTable(x, this->q, pf );
     }
-    fmk->hik_kernel_multiply_fast ( T, *q, x, y ); 
+    fmk->hik_kernel_multiply_fast ( T, this->q, x, y ); 
     delete [] T;
   }
   else //no quantization
@@ -111,23 +111,23 @@ void GMHIKernel::setUseOldPreparation( const bool & _useOldPreparation)
 
 uint GMHIKernel::getNumParameters() const 
 {
-  if ( pf == NULL )
+  if ( this->pf == NULL )
     return 0;
   else
-    return pf->parameters().size();
+    return this->pf->parameters().size();
 }
 
-void GMHIKernel::getParameters(Vector & parameters) const
+void GMHIKernel::getParameters( NICE::Vector & parameters ) const
 {
-  if ( pf == NULL )
+  if ( this->pf == NULL )
     parameters.clear();
   else {
-    parameters.resize( pf->parameters().size() );
-    parameters = pf->parameters();
+    parameters.resize( this->pf->parameters().size() );
+    parameters = this->pf->parameters();
   }
 }
 
-void GMHIKernel::setParameters(const Vector & parameters)
+void GMHIKernel::setParameters( const NICE::Vector & parameters )
 {
   if ( pf == NULL && parameters.size() > 0 )
     fthrow(Exception, "Unable to set parameters of a non-parameterized GMHIKernel object");
@@ -135,8 +135,6 @@ void GMHIKernel::setParameters(const Vector & parameters)
   pf->parameters() = parameters;
   
   fmk->applyFunctionToFeatureMatrix( pf );
-
-  // only for debugging with small matrices: fmk->featureMatrix().print();
 }
 
 void GMHIKernel::getDiagonalElements ( Vector & diagonalElements ) const

+ 78 - 0
SortedVectorSparse.h

@@ -255,7 +255,85 @@ template<class T> class SortedVectorSparse : NICE::Persistent{
         return ( T ) 0;
       }
     }
+    
+    inline T getLargestValueUnsafe ( const double & _quantile = 1.0, 
+                                     const bool & _getTransformedValue = false
+                                   ) const
+    {
+        uint idxDest ( round ( (this->getNonZeros() - 1) * _quantile)  );
+        
+        if ( _quantile > 0.5 )
+        {
+          typename std::multimap< T, dataelement >::const_reverse_iterator it = this->nzData.rend();
+          
+          //
+          // take as many backward steps as indicated by _quantile
+          for ( uint idx = this->getNonZeros(); idx > idxDest; idx-- )
+          {
+            it++;
+          }          
+          // alternative usage for random access iterators:
+          // it = it + (uint) this->getNonZeros() * ( 1.0 -  _quantile );
 
+            if ( _getTransformedValue )
+              return it->second.second;
+            else
+              return it->first;
+        }
+        else
+        {
+          typename std::multimap< T, dataelement >::const_iterator it = this->nzData.begin();
+          
+          // take as many steps forward as indicated by _quantile
+          for ( uint idx = 0; idx < idxDest; idx++ )
+          {
+            it++;
+          }
+          // alternative usage for random access iterators:
+          // it = it + (uint) this->getNonZeros() * _quantile;  
+          
+          if ( _getTransformedValue )
+            return it->second.second;
+          else
+            return it->first;
+        }
+    }    
+    
+    inline T getLargestTransformedValueUnsafe ( const double & _quantile = 1.0 ) const
+    {
+        uint idxDest ( round ( (this->getNonZeros() - 1) * _quantile )  );
+        
+        if ( _quantile > 0.5 )
+        {
+          typename std::multimap< T, dataelement >::const_reverse_iterator it = this->nzData.rend();
+          
+          //
+          // take as many backward steps as indicated by _quantile
+          for ( uint idx = this->getNonZeros(); idx > idxDest; idx-- )
+          {
+            it++;
+          }          
+          // alternative usage for random access iterators:
+          // it = it + (uint) this->getNonZeros() * ( 1.0 -  _quantile );
+     
+          return it->second.second;
+        }
+        else
+        {
+          typename std::multimap< T, dataelement >::const_iterator it = this->nzData.begin();
+          
+          // take as many steps forward as indicated by _quantile
+          for ( uint idx = 0; idx < idxDest; idx++ )
+          {
+            it++;
+          }
+          // alternative usage for random access iterators:
+          // it = it + (uint) this->getNonZeros() * _quantile;  
+          
+          return it->second.second;
+        }
+    }
+      
     std::multimap< T, dataelement > & nonzeroElements()
     {
       return this->nzData;

+ 8 - 0
matlab/GPHIKClassifierMex.cpp

@@ -212,6 +212,14 @@ NICE::Config parseParametersGPHIKClassifier(const mxArray *prhs[], int nrhs)
         conf.sS("GPHIKClassifier", variable, value);
     }
 
+    if(variable == "s_quantType")
+    {
+      string value = MatlabConversion::convertMatlabToString( prhs[i+1] );
+      if( value != "1d-aequi-0-1" && value != "1d-aequi-0-max" && value != "nd-aequi-0-max" )
+        mexErrMsgIdAndTxt("mexnice:error","Unexpected parameter value for \'s_quantType\'. \'1d-aequi-0-1\' , \'1d-aequi-0-max\' or \'nd-aequi-0-max\' expected.");
+        conf.sS("GPHIKClassifier", variable, value);
+    }
+    
     if(variable == "transform")
     {
       string value = MatlabConversion::convertMatlabToString( prhs[i+1] );

+ 8 - 0
matlab/GPHIKRegressionMex.cpp

@@ -210,6 +210,14 @@ NICE::Config parseParametersGPHIKRegression(const mxArray *prhs[], int nrhs)
         mexErrMsgIdAndTxt("mexnice:error","Unexpected parameter value for \'optimization_method\'. \'greedy\', \'downhillsimplex\' or \'none\' expected.");
         conf.sS("GPHIKRegression", variable, value);
     }
+    
+    if(variable == "s_quantType")
+    {
+      string value = MatlabConversion::convertMatlabToString( prhs[i+1] );
+      if( value != "1d-aequi-0-1" && value != "1d-aequi-0-max" && value != "nd-aequi-0-max" )
+        mexErrMsgIdAndTxt("mexnice:error","Unexpected parameter value for \'s_quantType\'. \'1d-aequi-0-1\' , \'1d-aequi-0-max\' or \'nd-aequi-0-max\' expected.");
+        conf.sS("GPHIKClassifier", variable, value);
+    }    
 
     if(variable == "transform")
     {

+ 7 - 3
matlab/plot1dExampleClassification.m

@@ -22,14 +22,14 @@ b_debug                             = false;
 b_uncertaintyPredictionForClassification ...
                                     = true; 
 b_optimize_noise                    = false;
-b_use_quantization                  = false;
+b_use_quantization                  = true;
 b_ils_verbose                       = false;
 %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %% integer
 i_nrOfEigenvaluesToConsiderForVarApprox ...
                                     = 1;
-i_num_bins                          = 100; % default
+i_num_bins                          = 1000; % default
 i_ils_max_iterations                = 1000; % default
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %% double    
@@ -49,6 +49,9 @@ s_ils_method                        = 'CG'; % default
 % options: 'none', 'greedy', 'downhillsimplex'
 s_optimization_method               = 'downhillsimplex';
 
+% options: '1d-aequi-0-1' , '1d-aequi-0-max' or 'nd-aequi-0-1'
+s_quantType                         = '1d-aequi-0-1';
+
 % options:  'identity', 'exp', 'absexp'
 % with settings above, this equals 'identity'
 s_transform                         = 'identity'; 
@@ -79,6 +82,7 @@ myGPHIKClassifier = ...
                           ...
                           'ils_method',                                s_ils_method, ...
                           'optimization_method',                       s_optimization_method, ...   
+                          's_quantType',                               s_quantType, ...                          
                           'transform',                                 s_transform, ...
                           'varianceApproximation',                     s_varianceApproximation ...
         );
@@ -89,7 +93,7 @@ myGPHIKClassifier.train( myData, myLabels );
 
 %% evaluate model on test data
 
-myDataTest = 0:0.01:1;
+myDataTest = 0:0.001:1;
 % create l1-normalized 'histograms'
 myDataTest = cat(1, myDataTest, 1-myDataTest)';
 

+ 33 - 33
parameterizedFunctions/PFAbsExp.h

@@ -70,39 +70,39 @@ class PFAbsExp : public ParameterizedFunction
       
       while ( !b_endOfBlock )
       {
-	is >> tmp; // start of block 
-	
-	if ( this->isEndTag( tmp, "PFAbsExp" ) )
-	{
-	  b_endOfBlock = true;
-	  continue;
-	}
-		    
-	
-	tmp = this->removeStartTag ( tmp );
-	
-	if ( tmp.compare("upperBound") == 0 )
-	{
-	  is >> upperBound;
-	  is >> tmp; // end of block 
-	  tmp = this->removeEndTag ( tmp );
-	}
-	else if ( tmp.compare("lowerBound") == 0 )
-	{
-	  is >> lowerBound;
-	  is >> tmp; // end of block 
-	  tmp = this->removeEndTag ( tmp );	    
-	}
-	else if ( tmp.compare("ParameterizedFunction") == 0 )
-	{
-	  // restore parent object
-	  ParameterizedFunction::restore(is);
-	}	
-	else
-	{
-	  std::cerr << "WARNING -- unexpected PFAbsExp object -- " << tmp << " -- for restoration... aborting" << std::endl;
-	  throw;	
-	}      
+        is >> tmp; // start of block 
+        
+        if ( this->isEndTag( tmp, "PFAbsExp" ) )
+        {
+          b_endOfBlock = true;
+          continue;
+        }
+              
+        
+        tmp = this->removeStartTag ( tmp );
+        
+        if ( tmp.compare("upperBound") == 0 )
+        {
+          is >> upperBound;
+          is >> tmp; // end of block 
+          tmp = this->removeEndTag ( tmp );
+        }
+        else if ( tmp.compare("lowerBound") == 0 )
+        {
+          is >> lowerBound;
+          is >> tmp; // end of block 
+          tmp = this->removeEndTag ( tmp );	    
+        }
+        else if ( tmp.compare("ParameterizedFunction") == 0 )
+        {
+          // restore parent object
+          ParameterizedFunction::restore(is);
+        }	
+        else
+        {
+          std::cerr << "WARNING -- unexpected PFAbsExp object -- " << tmp << " -- for restoration... aborting" << std::endl;
+          throw;	
+        }      
       }
       
 

+ 7 - 16
Quantization.cpp → quantization/Quantization.cpp

@@ -16,9 +16,10 @@ Quantization::Quantization( )
   this->ui_numBins = 1;
 }
 
-Quantization::Quantization( uint _numBins )
+Quantization::Quantization( uint _numBins,
+                            NICE::Vector * v_upperBounds
+                          )
 {
-  this->ui_numBins = _numBins;
 }
 
 Quantization::~Quantization()
@@ -29,22 +30,12 @@ uint Quantization::size() const
 {
   return this->ui_numBins;
 }
-  
-double Quantization::getPrototype (uint _bin) const
-{
-  return _bin / (double)(this->ui_numBins-1);
-}
-  
-uint Quantization::quantize (double _value) const
+
+uint Quantization::getNumberOfBins() const
 {
-  if ( _value <= 0.0 ) 
-    return 0;
-  else if ( _value >= 1.0 ) 
-    return this->ui_numBins-1;
-  else 
-    return (uint)( _value * (this->ui_numBins-1) + 0.5 );
+  return this->ui_numBins;
 }
-
+ 
 // ---------------------- STORE AND RESTORE FUNCTIONS ----------------------
 
 void Quantization::restore ( std::istream & _is, 

+ 118 - 0
quantization/Quantization.h

@@ -0,0 +1,118 @@
+/** 
+* @file Quantization.h
+* @brief Quantization of signals (Interface)
+* @author Erik Rodner, Alexander Freytag
+* @date 01/09/2012
+*/
+#ifndef _NICE_QUANTIZATIONINCLUDE
+#define _NICE_QUANTIZATIONINCLUDE
+
+// NICE-core includes
+#include <core/basics/types.h>
+#include <core/basics/Persistent.h>
+// 
+#include <core/vector/VectorT.h>
+
+// gp-hik-core includes
+#include "gp-hik-core/FeatureMatrixT.h"
+
+namespace NICE {
+  
+ /** 
+ * @class Quantization
+ * @brief Quantization of signals
+ * @author Erik Rodner, Alexander Freytag
+ */
+ 
+class Quantization  : public NICE::Persistent
+{
+
+  /** TODO
+   * The current implementation only provides uniform quantization. We could extend this
+   * by giving a ParameterizedFunction object to the constructor, which would allow us to inverse transform function values
+   * before performing the binning.
+   */
+
+  protected:
+
+    uint ui_numBins;
+    
+    // NOTE: we do not need lower bounds, 
+    // since our features are required to be non-negative 
+    // (for applying the HIK as kernel function)
+    NICE::Vector v_upperBounds;    
+    
+
+  public:
+
+  /** 
+   * @brief default constructor
+   * @author Alexander Freytag
+   * @date 06-02-2014
+   */
+  
+  Quantization( );
+  
+  /**
+   * @brief simple constructor
+   * @author Erik Rodner
+   * @date 
+   */
+  Quantization( uint _numBins, 
+                NICE::Vector * v_upperBounds = NULL
+              );
+
+  /** simple destructor */
+  virtual ~Quantization();
+
+  /**
+  * @brief get the size of the vocabulary, i.e. the number of bins
+  */
+  virtual uint size() const;
+  virtual uint getNumberOfBins() const;  
+
+  /**
+  * @brief get specific word or prototype element of the quantization
+  *
+  * @param bin the index of the bin
+  *
+  * @return value of the prototype
+  */
+  virtual double getPrototype ( uint _bin, 
+                                const uint & _dim = 0    
+                              ) const = 0;
+
+  /**
+  * @brief Determine for a given signal value the bin in the vocabulary. This is not the corresponding prototype, which 
+  * has to be requested with getPrototype afterwards
+  *
+  * @param value signal function value
+  *
+  * @return index of the bin entry corresponding to the given signal value
+  */
+  virtual uint quantize ( double _value, 
+                          const uint & _dim = 0
+                        ) const = 0;
+                        
+                        
+                        
+                        
+  //FIXME should the argument _fm be templated?
+  virtual void computeParametersFromData ( const NICE::FeatureMatrix *  _fm ) = 0;                        
+  
+  ///////////////////// INTERFACE PERSISTENT /////////////////////
+  // interface specific methods for store and restore
+  ///////////////////// INTERFACE PERSISTENT /////////////////////
+  virtual void restore ( std::istream & _is, 
+                         int _format = 0 
+                       );
+  virtual void store ( std::ostream & _os, 
+                       int _format = 0 
+                     ) const; 
+  virtual void clear () {};  
+     
+};
+
+}
+
+#endif

+ 114 - 0
quantization/Quantization1DAequiDist0To1.cpp

@@ -0,0 +1,114 @@
+/** 
+* @file Quantization1DAequiDist0To1.cpp
+* @brief Quantization1DAequiDist0To1 of one-dimensional signals with a standard range of [0,1] (Implementation)
+* @author Erik Rodner, Alexander Freytag
+* @date 01/09/2012
+
+*/
+#include <iostream>
+
+#include "Quantization1DAequiDist0To1.h"
+
+using namespace NICE;
+
+Quantization1DAequiDist0To1::Quantization1DAequiDist0To1( ) 
+{
+  this->ui_numBins = 1;
+}
+
+Quantization1DAequiDist0To1::Quantization1DAequiDist0To1( 
+                               uint _numBins, 
+                               NICE::Vector * v_upperBounds
+                             )
+{
+  this->ui_numBins = _numBins;
+  //
+  // this class does not require any upper bounds...
+}
+
+Quantization1DAequiDist0To1::~Quantization1DAequiDist0To1()
+{
+}
+
+double Quantization1DAequiDist0To1::getPrototype ( uint _bin, 
+                                                   const uint & _dim       
+                                                 ) const
+{
+  //  _dim will be ignored for this type of quantization. all dimensions are treated equally...  
+  return _bin / (double)(this->ui_numBins-1);
+}
+  
+uint Quantization1DAequiDist0To1::quantize ( double _value,
+                                             const uint & _dim
+                                           ) const
+{
+  //  _dim will be ignored for this type of quantization. all dimensions are treated equally...
+  
+  if ( _value <= 0.0 ) 
+    return 0;
+  else if ( _value >= 1.0 ) 
+    return this->ui_numBins-1;
+  else 
+    return (uint)( _value * (this->ui_numBins-1) + 0.5 );
+}
+
+void Quantization1DAequiDist0To1::computeParametersFromData ( const NICE::FeatureMatrix *  _fm )
+{
+  // nothing to do here...
+}
+// ---------------------- STORE AND RESTORE FUNCTIONS ----------------------
+
+void Quantization1DAequiDist0To1::restore ( std::istream & _is, 
+                             int _format 
+                           )
+{
+  if ( _is.good() )
+  {    
+    
+    std::string tmp;  
+    
+    bool b_endOfBlock ( false ) ;
+    
+    while ( !b_endOfBlock )
+    {
+      _is >> tmp; // start of block 
+      
+      if ( this->isEndTag( tmp, "Quantization1DAequiDist0To1" ) )
+      {
+        b_endOfBlock = true;
+        continue;
+      }                  
+      
+      tmp = this->removeStartTag ( tmp );
+      
+      if ( tmp.compare("Quantization") == 0 )
+      {
+        // restore parent object
+        Quantization::restore( _is );
+      }       
+      else
+      {
+        std::cerr << "WARNING -- unexpected Quantization1DAequiDist0To1 object -- " << tmp << " -- for restoration... aborting" << std::endl;
+        throw;  
+      } 
+    }
+   }
+  else
+  {
+    std::cerr << "Quantization1DAequiDist0To1::restore -- InStream not initialized - restoring not possible!" << std::endl;
+  }
+}
+
+void Quantization1DAequiDist0To1::store ( std::ostream & _os, 
+                                          int _format 
+                                        ) const
+{
+  // show starting point
+  _os << this->createStartTag( "Quantization1DAequiDist0To1" ) << std::endl;
+  
+  // store parent object
+  Quantization::store( _os ); 
+    
+  // done
+  _os << this->createEndTag( "Quantization1DAequiDist0To1" ) << std::endl;
+}

+ 24 - 20
Quantization.h → quantization/Quantization1DAequiDist0To1.h

@@ -1,16 +1,18 @@
 /** 
-* @file Quantization.h
+* @file Quantization1DAequiDist0To1.h
 * @brief Quantization of one-dimensional signals with a standard range of [0,1] (Interface)
 * @author Erik Rodner, Alexander Freytag
 * @date 01/09/2012
 */
-#ifndef _NICE_QUANTIZATIONINCLUDE
-#define _NICE_QUANTIZATIONINCLUDE
+#ifndef _NICE_QUANTIZATION1DAEQUIDIST0TO1INCLUDE
+#define _NICE_QUANTIZATION1DAEQUIDIST0TO1INCLUDE
 
 // NICE-core includes
 #include <core/basics/types.h>
 #include <core/basics/Persistent.h>
 
+#include "gp-hik-core/quantization/Quantization.h"
+
 namespace NICE {
   
  /** 
@@ -19,7 +21,7 @@ namespace NICE {
  * @author Erik Rodner, Alexander Freytag
  */
  
-class Quantization  : public NICE::Persistent
+class Quantization1DAequiDist0To1  : public NICE::Quantization
 {
 
   /** TODO
@@ -30,8 +32,6 @@ class Quantization  : public NICE::Persistent
 
   protected:
 
-    uint ui_numBins;
-
   public:
 
   /** 
@@ -40,23 +40,20 @@ class Quantization  : public NICE::Persistent
    * @date 06-02-2014
    */
   
-  Quantization( );
+  Quantization1DAequiDist0To1( );
   
   /**
    * @brief simple constructor
    * @author Erik Rodner
    * @date 
    */
-  Quantization( uint _numBins );
+  Quantization1DAequiDist0To1( uint _numBins, 
+                               NICE::Vector * v_upperBounds = NULL
+                              );
     
   /** simple destructor */
-  virtual ~Quantization();
-
-  /**
-  * @brief get the size of the vocabulary, i.e. the number of bins
-  */
-  virtual uint size() const;
-
+  virtual ~Quantization1DAequiDist0To1();
+  
   /**
   * @brief get specific word or prototype element of the quantization
   *
@@ -64,8 +61,10 @@ class Quantization  : public NICE::Persistent
   *
   * @return value of the prototype
   */
-  virtual double getPrototype (uint _bin) const;
-
+  virtual double getPrototype ( uint _bin, 
+                                const uint & _dim = 0    
+                              ) const;    
+  
   /**
   * @brief Determine for a given signal value the bin in the vocabulary. This is not the corresponding prototype, which 
   * has to be requested with getPrototype afterwards
@@ -74,7 +73,11 @@ class Quantization  : public NICE::Persistent
   *
   * @return index of the bin entry corresponding to the given signal value
   */
-  virtual uint quantize (double _value) const;
+  virtual uint quantize ( double _value, 
+                          const uint & _dim = 0
+                        ) const;
+                        
+  virtual void computeParametersFromData ( const NICE::FeatureMatrix *  _fm ) ;                        
   
   ///////////////////// INTERFACE PERSISTENT /////////////////////
   // interface specific methods for store and restore
@@ -85,8 +88,9 @@ class Quantization  : public NICE::Persistent
   virtual void store ( std::ostream & _os, 
                        int _format = 0 
                      ) const; 
-  virtual void clear () {};  
-     
+  virtual void clear () {};    
+
+ 
 };
 
 }

+ 122 - 0
quantization/Quantization1DAequiDist0ToMax.cpp

@@ -0,0 +1,122 @@
+/** 
+* @file Quantization1DAequiDist0ToMax.cpp
+* @brief Quantization1DAequiDist0ToMax of one-dimensional signals with selectable interval [0, vMax] (Implementation)
+* @author Erik Rodner, Alexander Freytag
+* @date 13-10-2015 ( dd-mm-yyyy )
+
+*/
+#include <iostream>
+
+#include "Quantization1DAequiDist0ToMax.h"
+
+using namespace NICE;
+
+Quantization1DAequiDist0ToMax::Quantization1DAequiDist0ToMax( ) 
+{
+  this->ui_numBins = 1;
+}
+
+Quantization1DAequiDist0ToMax::Quantization1DAequiDist0ToMax( 
+                               uint _numBins, 
+                               NICE::Vector * _upperBounds
+                             )
+{
+  this->ui_numBins = _numBins;
+  this->v_upperBounds.resize ( 1 );
+  if ( (_upperBounds != NULL)  && (_upperBounds->size() > 0) )
+    this->v_upperBounds[0] = (*_upperBounds)[0];
+  else
+    this->v_upperBounds[0] = 1.0;
+}
+
+Quantization1DAequiDist0ToMax::~Quantization1DAequiDist0ToMax()
+{
+}
+
+  
+double Quantization1DAequiDist0ToMax::getPrototype ( uint _bin, 
+                                                     const uint & _dim       
+                                                   ) const
+{
+  //  _dim will be ignored for this type of quantization. all dimensions are treated equally...  
+  return (this->v_upperBounds[0]*_bin) / (double)(this->ui_numBins-1);
+}
+  
+uint Quantization1DAequiDist0ToMax::quantize ( double _value,
+                                               const uint & _dim
+                                             ) const
+{
+  //  _dim will be ignored for this type of quantization. all dimensions are treated equally...
+  
+  if ( _value <= 0.0 ) 
+    return 0;
+  else if ( _value >= this->v_upperBounds[0] ) 
+    return this->ui_numBins-1;
+  else 
+    return (uint)( _value/this->v_upperBounds[0]  * (this->ui_numBins-1) + 0.5 );
+}
+
+
+
+void Quantization1DAequiDist0ToMax::computeParametersFromData ( const NICE::FeatureMatrix *  _fm )
+{
+      double vmax = ( _fm->getLargestValue( ) );       
+      this->v_upperBounds.resize ( 1 );
+      this->v_upperBounds ( 0 ) = vmax;
+}
+// ---------------------- STORE AND RESTORE FUNCTIONS ----------------------
+
+void Quantization1DAequiDist0ToMax::restore ( std::istream & _is, 
+                             int _format 
+                           )
+{
+  if ( _is.good() )
+  {    
+    
+    std::string tmp;    
+
+    bool b_endOfBlock ( false ) ;
+    
+    while ( !b_endOfBlock )
+    {
+      _is >> tmp; // start of block 
+      
+      if ( this->isEndTag( tmp, "Quantization1DAequiDist0ToMax" ) )
+      {
+        b_endOfBlock = true;
+        continue;
+      }                  
+      
+      tmp = this->removeStartTag ( tmp );
+      
+      if ( tmp.compare("Quantization") == 0 )
+      {
+        // restore parent object
+        Quantization::restore(  _is );
+      }       
+      else
+      {
+        std::cerr << "WARNING -- unexpected Quantization1DAequiDist0ToMax object -- " << tmp << " -- for restoration... aborting" << std::endl;
+        throw;  
+      }
+    }
+   }
+  else
+  {
+    std::cerr << "Quantization1DAequiDist0ToMax::restore -- InStream not initialized - restoring not possible!" << std::endl;
+  }
+}
+
+void Quantization1DAequiDist0ToMax::store ( std::ostream & _os, 
+                                            int _format 
+                                          ) const
+{
+  // show starting point
+  _os << this->createStartTag( "Quantization1DAequiDist0ToMax" ) << std::endl;
+  
+  // store parent object
+  Quantization::store( _os ); 
+    
+  // done
+  _os << this->createEndTag( "Quantization1DAequiDist0ToMax" ) << std::endl;
+}

+ 99 - 0
quantization/Quantization1DAequiDist0ToMax.h

@@ -0,0 +1,99 @@
+/** 
+* @file Quantization1DAequiDist0ToMax.h
+* @brief Quantization of one-dimensional signals with selectable interval [0, vMax] (Interface)
+* @author Alexander Freytag
+* @date 13-10-2015 ( dd-mm-yyyy )
+*/
+#ifndef _NICE_QUANTIZATION1DAEQUIDIST0TOMAXINCLUDE
+#define _NICE_QUANTIZATION1DAEQUIDIST0TOMAXINCLUDE
+
+// NICE-core includes
+#include <core/basics/types.h>
+#include <core/basics/Persistent.h>
+
+#include "gp-hik-core/quantization/Quantization.h"
+
+namespace NICE {
+  
+ /** Quantization1DAequiDist0ToMax
+ * @class Quantization
+ * @brief Quantization of one-dimensional signals with selectable interval [0, vMax]
+ * @author Alexander Freytag
+ */
+ 
+class Quantization1DAequiDist0ToMax  : public NICE::Quantization
+{
+
+  /** TODO
+   * The current implementation only provides uniform quantization. We could extend this
+   * by giving a ParameterizedFunction object to the constructor, which would allow us to inverse transform function values
+   * before performing the binning.
+   */
+
+  protected:
+
+  public:
+
+  /** 
+   * @brief default constructor
+   * @author Alexander Freytag
+   * @date 06-02-2014
+   */
+  
+  Quantization1DAequiDist0ToMax( );
+  
+  /**
+   * @brief simple constructor
+   * @author Erik Rodner
+   * @date 
+   */
+  Quantization1DAequiDist0ToMax( uint _numBins, 
+                               NICE::Vector * v_upperBounds = NULL
+                              );
+    
+  /** simple destructor */
+  virtual ~Quantization1DAequiDist0ToMax();
+  
+  /**
+  * @brief get specific word or prototype element of the quantization
+  *
+  * @param bin the index of the bin
+  *
+  * @return value of the prototype
+  */
+  virtual double getPrototype ( uint _bin, 
+                                const uint & _dim = 0    
+                              ) const;    
+  
+  /**
+  * @brief Determine for a given signal value the bin in the vocabulary. This is not the corresponding prototype, which 
+  * has to be requested with getPrototype afterwards
+  *
+  * @param value signal function value
+  *
+  * @return index of the bin entry corresponding to the given signal value
+  */
+  virtual uint quantize ( double _value, 
+                          const uint & _dim = 0
+                        ) const;
+                        
+                        
+  virtual void computeParametersFromData ( const NICE::FeatureMatrix *  _fm ) ;
+  
+  ///////////////////// INTERFACE PERSISTENT /////////////////////
+  // interface specific methods for store and restore
+  ///////////////////// INTERFACE PERSISTENT /////////////////////
+  virtual void restore ( std::istream & _is, 
+                         int _format = 0 
+                       );
+  virtual void store ( std::ostream & _os, 
+                       int _format = 0 
+                     ) const; 
+  virtual void clear () {};    
+
+ 
+};
+
+}
+
+#endif

+ 127 - 0
quantization/QuantizationNDAequiDist0ToMax.cpp

@@ -0,0 +1,127 @@
+/** 
+* @file QuantizationNDAequiDist0ToMax.cpp
+* @brief QuantizationNDAequiDist0ToMax of one-dimensional signals with selectable interval [0, vMax] (Implementation)
+* @author Alexander Freytag
+* @date 13-10-2015 ( dd-mm-yyyy )
+
+*/
+#include <iostream>
+
+#include "QuantizationNDAequiDist0ToMax.h"
+
+using namespace NICE;
+
+QuantizationNDAequiDist0ToMax::QuantizationNDAequiDist0ToMax( ) 
+{
+  this->ui_numBins = 1;
+}
+
+QuantizationNDAequiDist0ToMax::QuantizationNDAequiDist0ToMax( 
+                               uint _numBins, 
+                               NICE::Vector * _upperBounds
+                             )
+{
+  this->ui_numBins    = _numBins;
+  if ( (_upperBounds != NULL)  && (_upperBounds->size() > 0) )
+    this->v_upperBounds = (*_upperBounds);
+  else
+    this->v_upperBounds = NICE::Vector( 1 );  
+}
+
+QuantizationNDAequiDist0ToMax::~QuantizationNDAequiDist0ToMax()
+{
+}
+
+  
+double QuantizationNDAequiDist0ToMax::getPrototype ( uint _bin, 
+                                                     const uint & _dim       
+                                                   ) const
+{
+  return (this->v_upperBounds[_dim]*_bin) / (double)(this->ui_numBins-1);
+}
+  
+uint QuantizationNDAequiDist0ToMax::quantize ( double _value,
+                                               const uint & _dim
+                                             ) const
+{
+  if ( _value <= 0.0 ) 
+    return 0;
+  else if ( _value >= this->v_upperBounds[_dim] ) 
+    return this->ui_numBins-1;
+  else 
+    return (uint)( _value/this->v_upperBounds[_dim]  * (this->ui_numBins-1) + 0.5 );
+}
+
+
+void QuantizationNDAequiDist0ToMax::computeParametersFromData ( const NICE::FeatureMatrix *  _fm )
+{     
+  // 100% quantile...
+  double d_quantile ( 1.00 ); 
+  this->v_upperBounds = _fm->getLargestValuePerDimension( d_quantile );  
+}
+
+// ---------------------- STORE AND RESTORE FUNCTIONS ----------------------
+
+void QuantizationNDAequiDist0ToMax::restore ( std::istream & _is, 
+                                              int _format 
+                                            )
+{
+  if ( _is.good() )
+  {    
+    std::string tmp;
+    _is >> tmp; //class name 
+    
+    if ( ! this->isStartTag( tmp, "Quantization1DAequiDist0ToMax" ) )
+    {
+        std::cerr << " WARNING - attempt to restore Quantization1DAequiDist0ToMax, but start flag " << tmp << " does not match! Aborting... " << std::endl;
+        throw;
+    } 
+
+    bool b_endOfBlock ( false ) ;
+    
+    while ( !b_endOfBlock )
+    {
+      _is >> tmp; // start of block 
+      
+      if ( this->isEndTag( tmp, "QuantizationNDAequiDist0ToMax" ) )
+      {
+        b_endOfBlock = true;
+        continue;
+      }                  
+      
+      tmp = this->removeStartTag ( tmp );
+      
+      if ( tmp.compare("Quantization") == 0 )
+      {
+        // restore parent object
+        Quantization::restore( _is );
+      }       
+      else
+      {
+        std::cerr << "WARNING -- unexpected QuantizationNDAequiDist0ToMax object -- " << tmp << " -- for restoration... aborting" << std::endl;
+        throw;  
+      }
+      //FIXME also store and restore the upper bounds      
+//       _is >> tmp; // end of block 
+//       tmp = this->removeEndTag ( tmp );     
+    }
+   }
+  else
+  {
+    std::cerr << "QuantizationNDAequiDist0ToMax::restore -- InStream not initialized - restoring not possible!" << std::endl;
+  }
+}
+
+void QuantizationNDAequiDist0ToMax::store ( std::ostream & _os, 
+                                            int _format 
+                                          ) const
+{
+  // show starting point
+  _os << this->createStartTag( "QuantizationNDAequiDist0ToMax" ) << std::endl;
+  
+  // store parent object
+  Quantization::store( _os ); 
+    
+  // done
+  _os << this->createEndTag( "QuantizationNDAequiDist0ToMax" ) << std::endl;
+}

+ 99 - 0
quantization/QuantizationNDAequiDist0ToMax.h

@@ -0,0 +1,99 @@
+/** 
+* @file QuantizationNDAequiDist0ToMax.h
+* @brief Dimension-specific quantization of one-dimensional signals with selectable interval [0, vMax] (Interface)
+* @author Alexander Freytag
+* @date 13-10-2015 ( dd-mm-yyyy )
+*/
+#ifndef _NICE_QUANTIZATIONNDAEQUIDIST0TOMAXINCLUDE
+#define _NICE_QUANTIZATIONNDAEQUIDIST0TOMAXINCLUDE
+
+// NICE-core includes
+#include <core/basics/types.h>
+#include <core/basics/Persistent.h>
+
+#include "gp-hik-core/quantization/Quantization.h"
+
+namespace NICE {
+  
+ /** 
+ * @class QuantizationNDAequiDist0ToMax
+ * @brief Dimension-specific quantization of one-dimensional signals with selectable interval [0, vMax]
+ * @author Alexander Freytag
+ */
+ 
+class QuantizationNDAequiDist0ToMax  : public NICE::Quantization
+{
+
+  /** TODO
+   * The current implementation only provides uniform quantization. We could extend this
+   * by giving a ParameterizedFunction object to the constructor, which would allow us to inverse transform function values
+   * before performing the binning.
+   */
+
+  protected:
+
+  public:
+
+  /** 
+   * @brief default constructor
+   * @author Alexander Freytag
+   * @date 06-02-2014
+   */
+  
+  QuantizationNDAequiDist0ToMax( );
+  
+  /**
+   * @brief simple constructor
+   * @author Erik Rodner
+   * @date 
+   */
+  QuantizationNDAequiDist0ToMax( uint _numBins, 
+                               NICE::Vector * v_upperBounds = NULL
+                              );
+    
+  /** simple destructor */
+  virtual ~QuantizationNDAequiDist0ToMax();
+  
+  /**
+  * @brief get specific word or prototype element of the quantization
+  *
+  * @param bin the index of the bin
+  *
+  * @return value of the prototype
+  */
+  virtual double getPrototype ( uint _bin, 
+                                const uint & _dim = 0    
+                              ) const;    
+  
+  /**
+  * @brief Determine for a given signal value the bin in the vocabulary. This is not the corresponding prototype, which 
+  * has to be requested with getPrototype afterwards
+  *
+  * @param value signal function value
+  *
+  * @return index of the bin entry corresponding to the given signal value
+  */
+  virtual uint quantize ( double _value, 
+                          const uint & _dim = 0
+                        ) const;
+                        
+                        
+  virtual void computeParametersFromData ( const NICE::FeatureMatrix *  _fm ) ;
+                          
+  ///////////////////// INTERFACE PERSISTENT /////////////////////
+  // interface specific methods for store and restore
+  ///////////////////// INTERFACE PERSISTENT /////////////////////
+  virtual void restore ( std::istream & _is, 
+                         int _format = 0 
+                       );
+  virtual void store ( std::ostream & _os, 
+                       int _format = 0 
+                     ) const; 
+  virtual void clear () {};    
+
+ 
+};
+
+}
+
+#endif

+ 26 - 16
tests/TestFastHIK.cpp

@@ -12,6 +12,10 @@
 #include <gp-hik-core/kernels/GeneralizedIntersectionKernelFunction.h>
 #include <gp-hik-core/parameterizedFunctions/ParameterizedFunction.h>
 #include <gp-hik-core/parameterizedFunctions/PFAbsExp.h>
+// 
+// 
+#include "gp-hik-core/quantization/Quantization.h"
+#include "gp-hik-core/quantization/Quantization1DAequiDist0To1.h"
 
 #include "TestFastHIK.h"
 
@@ -199,8 +203,11 @@ void TestFastHIK::testKernelMultiplicationFast()
   if (verboseStartEnd)
     std::cerr << "================== TestFastHIK::testKernelMultiplicationFast ===================== " << std::endl;
   
-  Quantization q_gen ( numBins );
-  Quantization q ( 2*numBins -1);
+  NICE::Quantization * q_gen;
+  q_gen = new Quantization1DAequiDist0To1 ( numBins );  
+  
+  NICE::Quantization * q;
+  q = new Quantization1DAequiDist0To1 ( 2*numBins -1 );   
 
   // data is generated, such that there is no approximation error
   vector< vector<double> > dataMatrix;
@@ -212,7 +219,7 @@ void TestFastHIK::testKernelMultiplicationFast()
       if ( drand48() < sparse_prob ) {
         v[k] = 0;
       } else {
-        v[k] = q_gen.getPrototype( (rand() % numBins) );
+        v[k] = q_gen->getPrototype( (rand() % numBins) );
       }
     }
 
@@ -239,7 +246,7 @@ void TestFastHIK::testKernelMultiplicationFast()
     y[i] = sin(i);
    
   ParameterizedFunction *pf = new PFAbsExp ( 1.0 );
-  GMHIKernel gmkFast ( &fmk, pf, &q );
+  GMHIKernel gmkFast ( &fmk, pf, q );
 
 //   pf.applyFunctionToFeatureMatrix ( fmk.featureMatrix() );
     
@@ -377,7 +384,8 @@ void TestFastHIK::testKernelSumFast()
   if (verboseStartEnd)
     std::cerr << "================== TestFastHIK::testKernelSumFast ===================== " << std::endl;
   
-  Quantization q ( numBins );
+  NICE::Quantization * q;
+  q = new Quantization1DAequiDist0To1 ( numBins );
 
   // data is generated, such that there is no approximation error
   vector< vector<double> > dataMatrix;
@@ -389,7 +397,7 @@ void TestFastHIK::testKernelSumFast()
       if ( drand48() < sparse_prob ) {
         v[k] = 0;
       } else {
-        v[k] = q.getPrototype( (rand() % numBins) );
+        v[k] = q->getPrototype( (rand() % numBins) );
       }
     }
 
@@ -414,7 +422,7 @@ void TestFastHIK::testKernelSumFast()
     if ( drand48() < sparse_prob ) {
       xstar[i] = 0;
     } else {
-      xstar[i] = q.getPrototype( (rand() % numBins) );
+      xstar[i] = q->getPrototype( (rand() % numBins) );
     }
 
   // convert to STL vector
@@ -510,7 +518,8 @@ void TestFastHIK::testLUTUpdate()
   if (verboseStartEnd)
     std::cerr << "================== TestFastHIK::testLUTUpdate ===================== " << std::endl;
 
-  Quantization q ( numBins );
+  NICE::Quantization * q;
+  q = new Quantization1DAequiDist0To1 ( numBins );
 
   // data is generated, such that there is no approximation error
   vector< vector<double> > dataMatrix;
@@ -522,7 +531,7 @@ void TestFastHIK::testLUTUpdate()
       if ( drand48() < sparse_prob ) {
         v[k] = 0;
       } else {
-        v[k] = q.getPrototype( (rand() % numBins) );
+        v[k] = q->getPrototype( (rand() % numBins) );
       }
     }
 
@@ -600,7 +609,7 @@ void TestFastHIK::testLUTUpdate()
   }
   
   
-  bool equal = compareLUTs(T, TNew, q.size()*d, 10e-8);
+  bool equal = compareLUTs(T, TNew, q->size()*d, 10e-8);
   
   if (verbose)
   {
@@ -609,16 +618,16 @@ void TestFastHIK::testLUTUpdate()
     else
     {
       std::cerr << "T are not equal :( " << std::endl;
-      for (uint i = 0; i < q.size()*d; i++)
+      for (uint i = 0; i < q->size()*d; i++)
       {
-        if ( (i % q.size()) == 0)
+        if ( (i % q->size()) == 0)
           std::cerr << std::endl;
         std::cerr << T[i] << " ";
       }
       std::cerr << "TNew: "<< std::endl;
-      for (uint i = 0; i < q.size()*d; i++)
+      for (uint i = 0; i < q->size()*d; i++)
       {
-        if ( (i % q.size()) == 0)
+        if ( (i % q->size()) == 0)
           std::cerr << std::endl;
         std::cerr << TNew[i] << " ";
       }     
@@ -641,7 +650,8 @@ void TestFastHIK::testLinSolve()
   if (verboseStartEnd)
     std::cerr << "================== TestFastHIK::testLinSolve ===================== " << std::endl;
 
-  NICE::Quantization q ( numBins );
+  NICE::Quantization * q;
+  q = new Quantization1DAequiDist0To1 ( numBins );
 
   // data is generated, such that there is no approximation error
   std::vector< std::vector<double> > dataMatrix;
@@ -653,7 +663,7 @@ void TestFastHIK::testLinSolve()
       if ( drand48() < sparse_prob ) {
         v[k] = 0;
       } else {
-        v[k] = q.getPrototype( (rand() % numBins) );
+        v[k] = q->getPrototype( (rand() % numBins) );
       }
     }
 

+ 15 - 5
tests/TestGPHIKPersistent.cpp

@@ -76,13 +76,13 @@ void TestGPHIKPersistent::testPersistentMethods()
   }  
   
   // TRAIN CLASSIFIER FROM SCRATCH
+  std::string confsection ( "GPHIKClassifier" );  
+  conf.sB ( confsection, "use_quantization", true );
+  conf.sS ( confsection, "s_quantType", "1d-aequi-0-1" );
+  conf.sS ( confsection, "transform", "identity");  
   
   classifier = new GPHIKClassifier ( &conf );  
-  
-  yBinTrain *= 2;
-  yBinTrain -= 1;
-  yBinTrain *= -1;
-  
+   
   if ( verbose )
   {
     std::cerr << yBinTrain << std::endl;
@@ -106,6 +106,11 @@ void TestGPHIKPersistent::testPersistentMethods()
   //   
   fbOut.close(); 
   
+  if ( verbose )
+  {
+    std::cerr << "store done successfully" << std::endl;    
+  }  
+  
   
   // TEST RESTORING ABILITIES
     
@@ -121,6 +126,11 @@ void TestGPHIKPersistent::testPersistentMethods()
   //   
   fbIn.close();   
   
+  if ( verbose )
+  {
+    std::cerr << "restore done successfully" << std::endl;    
+  }    
+  
   
   // TEST both classifiers to produce equal results