ソースを参照

Merge branch 'master' of dbv.inf-cv.uni-jena.de:nice/nice-vislearning into cmake_mergemaster

Johannes Ruehle 11 年 前
コミット
65e09863dd

+ 44 - 13
classifier/fpclassifier/FPCGPHIK.cpp

@@ -3,13 +3,16 @@
 * @brief feature pool interface for our GP HIK classifier
 * @author Alexander Freytag
 * @date 02/01/2012
-
 */
+
+// STL includes
 #include <iostream>
 
-#include "core/basics/numerictools.h"
+// NICE-core includes
+#include <core/basics/numerictools.h>
 #include <core/basics/Timer.h>
 
+// NICE-vislearning includes
 #include "FPCGPHIK.h"
 
 using namespace std;
@@ -34,12 +37,37 @@ FPCGPHIK::~FPCGPHIK()
 }
 
 ClassificationResult FPCGPHIK::classify ( Example & pe )
-{
-  const SparseVector *svec = pe.svec;
+{  
 
-  if ( svec == NULL )
-    fthrow(Exception, "FPCGPHIK requires example.svec (SparseVector stored in an Example struct)");
- return this->classify( svec ); 
+  NICE::SparseVector *svec;// = pe.svec;  
+  
+  // was only a NICE::Vector given?
+  // Than we had to allocate a new NICE::SparseVector and converted the given NICE::Vector into it.
+  bool newvec = false;  
+  
+  if ( pe.svec != NULL )
+  {
+    svec = pe.svec;
+  }
+  else
+  {
+    NICE::Vector x;
+
+    x = * ( pe.vec );
+
+    svec = new NICE::SparseVector ( x );
+
+    svec->setDim ( x.size() );
+
+    newvec = true;
+  }  
+    
+  ClassificationResult result ( this->classify( svec )  );
+    
+  if ( newvec )
+    delete svec;
+
+  return result;  
 }
 
 ClassificationResult FPCGPHIK::classify ( const NICE::SparseVector * example )
@@ -118,7 +146,7 @@ void FPCGPHIK::train ( FeaturePool & fp, Examples & examples )
   Vector y ( examples.size() /* maximum size */ );
 
   // flat structure of our training data
-  std::vector< SparseVector * > sparseExamples;
+  std::vector< const SparseVector * > sparseExamples;
 
   if (verbose)
     cerr << "Converting (and sampling) feature vectors" << endl;
@@ -147,9 +175,12 @@ void FPCGPHIK::train ( FeaturePool & fp, Examples & examples )
 }
 
 /** training process */
-void FPCGPHIK::train ( const std::vector< SparseVector *> & examples, std::map<int, NICE::Vector> & binLabels )
+void FPCGPHIK::train ( const std::vector< const SparseVector *> & examples, std::map<int, NICE::Vector> & binLabels )
 {
+  
+  std::cerr << "call internal train method " << std::endl;
   classifier->train(examples, binLabels);
+  std::cerr << "training done" << std::endl;
 }
 
 void FPCGPHIK::clear ()
@@ -166,17 +197,17 @@ FeaturePoolClassifier *FPCGPHIK::clone () const
   return NULL;
 }
 
-void FPCGPHIK::predictUncertainty( Example & pe, NICE::Vector & uncertainties )
+void FPCGPHIK::predictUncertainty( Example & pe, double & uncertainty )
 {
   const SparseVector *svec = pe.svec;  
   if ( svec == NULL )
     fthrow(Exception, "FPCGPHIK requires example.svec (SparseVector stored in an Example struct)");
-  classifier->predictUncertainty(svec, uncertainties);
+  classifier->predictUncertainty(svec, uncertainty);
 }
    
-void FPCGPHIK::predictUncertainty( const NICE::SparseVector * example, NICE::Vector & uncertainties )
+void FPCGPHIK::predictUncertainty( const NICE::SparseVector * example, double & uncertainty )
 {  
-  classifier->predictUncertainty(example, uncertainties);
+  classifier->predictUncertainty(example, uncertainty);
 }
 
 //---------------------------------------------------------------------

+ 18 - 6
classifier/fpclassifier/FPCGPHIK.h

@@ -7,14 +7,20 @@
 #ifndef _NICE_FPCGPHIKCLASSIFIERNICEINCLUDE
 #define _NICE_FPCGPHIKCLASSIFIERNICEINCLUDE
 
+// STL includes
 #include <string>
-#include "core/basics/Config.h"
-#include "vislearning/classifier/classifierbase/FeaturePoolClassifier.h"
 
+// NICE-core includes
+#include <core/basics/Config.h>
+
+// NICE-gp-hik-core includes
 #include <gp-hik-core/GPHIKClassifier.h>
 #include <gp-hik-core/FMKGPHyperparameterOptimization.h>
 #include <gp-hik-core/parameterizedFunctions/ParameterizedFunction.h>
 
+// NICE-vislearning includes
+#include "vislearning/classifier/classifierbase/FeaturePoolClassifier.h"
+
 namespace OBJREC {
   
 /** @class FPCGPHIK
@@ -69,9 +75,11 @@ class FPCGPHIK : public FeaturePoolClassifier
      * @param examples examples to use given in a sparse data structure
      * @param binLabels corresponding binary labels with class no. There is no need here that every examples has only on positive entry in this set (1,-1)
      */
-    void train ( const std::vector< NICE::SparseVector *> & examples, std::map<int, NICE::Vector> & binLabels );
+    void train ( const std::vector< const NICE::SparseVector *> & examples, std::map<int, NICE::Vector> & binLabels );
     
-    /** Persistent interface */
+    ///////////////////// 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 ();
@@ -79,7 +87,7 @@ class FPCGPHIK : public FeaturePoolClassifier
     virtual FeaturePoolClassifier *clone () const;
     
     /** prediction of classification uncertainty */
-    void predictUncertainty( OBJREC::Example & pe, NICE::Vector & uncertainties );
+    void predictUncertainty( OBJREC::Example & pe, double & uncertainty );
     /** 
      * @brief prediction of classification uncertainty
      * @date 19-06-2012 (dd-mm-yyyy)
@@ -87,7 +95,11 @@ class FPCGPHIK : public FeaturePoolClassifier
      * @param examples example for which the classification uncertainty shall be predicted, given in a sparse representation
      * @param uncertainties contains the resulting classification uncertainties (1 entry for standard setting, m entries for binary-balanced setting)
      */       
-    void predictUncertainty( const NICE::SparseVector * example, NICE::Vector & uncertainties );
+    void predictUncertainty( const NICE::SparseVector * example, double & uncertainty );
+    
+    ///////////////////// INTERFACE ONLINE LEARNABLE (SIMILAR) /////////////////////
+    // interface specific methods for incremental extensions
+    ///////////////////// INTERFACE ONLINE LEARNABLE (SIMILAR) /////////////////////       
     
     void addExample( const OBJREC::Example & pe, const double & label);
     virtual void addMultipleExamples( OBJREC::Examples & newExamples);

+ 2 - 0
math/cluster/GenericClusterAlgorithmSelection.h

@@ -49,6 +49,8 @@ namespace OBJREC {
         
           // string which defines the clustering technique
           std::string clusterTechnique = conf->gS(section, "clusterTechnique", "");
+          
+          std::cerr << "clusterTechnique: " << clusterTechnique << std::endl;
                   
           if ( clusterTechnique == "kmeans" )
           {

+ 41 - 25
math/cluster/KMeans.cpp

@@ -5,12 +5,17 @@
  * @date 29-10-2007 (dd-mm-yyyy)
  */
 
+#ifdef NICE_USELIB_OPENMP
+#include <omp.h>
+#endif
+
+
+#include <set>
 #include <iostream>
 
 #include "vislearning/math/cluster/KMeans.h"
 #include "vislearning/math/distances/genericDistance.h"
 
-#include <set>
 
 using namespace OBJREC;
 
@@ -20,8 +25,8 @@ using namespace NICE;
 
 #undef DEBUG_KMEANS
 
-KMeans::KMeans(const int & _noClasses, const std::string & _distanceType) :
-        noClasses(_noClasses), distanceType(_distanceType)
+KMeans::KMeans(const int & _noClusters, const std::string & _distanceType) :
+        noClusters(_noClusters), distanceType(_distanceType)
 {
     //srand(time(NULL));
     this->distancefunction = GenericDistanceSelection::selectDistance(distanceType);
@@ -35,7 +40,9 @@ KMeans::KMeans( const NICE::Config *conf, const std::string & _section)
   this->d_minDelta  = conf->gD( _section, "minDelta", 1e-5 );
   this->i_maxIterations = conf->gI( _section, "maxIterations", 200);
   
-  this->noClasses = conf->gI( _section, "noClasses", 20);
+  this->noClusters = conf->gI( _section, "noClusters", 20);
+  std::cerr << "KMeans::KMeans -- noClusters: " << this->noClusters << std::endl;
+  
 }
 
 KMeans::~KMeans()
@@ -66,8 +73,8 @@ int KMeans::compute_prototypes(const VVector & features, VVector & prototypes,
                                std::vector<double> & weights, const std::vector<int> & assignment)
 {
     int j = 0;
-    // fprintf (stderr, "KMeans::compute_prototypes: init noClasses=%d\n", noClasses);
-    for (int k = 0; k < this->noClasses; k++)
+    // fprintf (stderr, "KMeans::compute_prototypes: init noClusters=%d\n", noClusters);
+    for (int k = 0; k < this->noClusters; k++)
     {
         prototypes[k].set(0);
         weights[k] = 0;
@@ -100,7 +107,8 @@ int KMeans::compute_prototypes(const VVector & features, VVector & prototypes,
     }
 
     // fprintf (stderr, "KMeans::compute_prototypes: scaling\n");
-    for (int k = 0; k < this->noClasses; k++)
+    #pragma omp parallel for
+    for (int k = 0; k < this->noClusters; k++)
     {
 
         NICE::Vector & p = prototypes[k];
@@ -109,19 +117,21 @@ int KMeans::compute_prototypes(const VVector & features, VVector & prototypes,
           std::cerr << "prototype for this class before scaling : " << p << std::endl;
         #endif
 
-        if (weights[k] <= 0)
+//         if (weights[k] <= 0)
+//         {
+//             return -1;
+//         }
+        if (weights[k] > 0)
         {
-            return -1;
-        }
+          p *= (1.0 / weights[k]);
 
-        p *= (1.0 / weights[k]);
+          weights[k] = weights[k] / features.size();
 
-        weights[k] = weights[k] / features.size();
-
-        #ifdef DEBUG_KMEANS
-          std::cerr << "prototype for this class after scaling with " << weights[k]
-             << " : " << p << std::endl;
-        #endif
+          #ifdef DEBUG_KMEANS
+            std::cerr << "prototype for this class after scaling with " << weights[k]
+              << " : " << p << std::endl;
+          #endif
+        }               
     }
 
     return 0;
@@ -147,11 +157,16 @@ double KMeans::compute_delta(const NICE::VVector & oldprototypes,
 double KMeans::compute_assignments(const NICE::VVector & features,
                                    const NICE::VVector & prototypes, std::vector<int> & assignment)
 {
-    int index = 0;
-    for (VVector::const_iterator i = features.begin(); i != features.end(); i++, index++)
+//     int index = 0;
+//     for (VVector::const_iterator i = features.begin(); i != features.end(); i++, index++)
+    
+    uint noFeatures ( features.size() );
+    #pragma omp parallel for
+    for (int index = 0; index < noFeatures; index++)
     {
 
-        const NICE::Vector & x = *i;
+//         const NICE::Vector & x = *i;
+        const NICE::Vector & x = features[index];
         double mindist = std::numeric_limits<double>::max();
         int minclass = 0;
 
@@ -194,7 +209,7 @@ double KMeans::compute_assignments(const NICE::VVector & features,
 double KMeans::compute_weights(const NICE::VVector & features,
                                std::vector<double> & weights, std::vector<int> & assignment)
 {
-    for (int k = 0; k < this->noClasses; k++)
+    for (int k = 0; k < this->noClusters; k++)
         weights[k] = 0;
 
     int j = 0;
@@ -205,7 +220,8 @@ double KMeans::compute_weights(const NICE::VVector & features,
         weights[k]++;
     }
 
-    for (int k = 0; k < this->noClasses; k++)
+    #pragma omp parallel for
+    for (int k = 0; k < this->noClusters; k++)
         weights[k] = weights[k] / features.size();
 
     return 0.0;
@@ -219,12 +235,12 @@ void KMeans::cluster(const NICE::VVector & features, NICE::VVector & prototypes,
   prototypes.clear();
   weights.clear();
   assignment.clear();
-  weights.resize(noClasses, 0);
+  weights.resize(noClusters, 0);
   assignment.resize(features.size(), 0);
 
   int dimension;
 
-  if ((int) features.size() >= this->noClasses)
+  if ((int) features.size() >= this->noClusters)
       dimension = features[0].size();
   else
   {
@@ -233,7 +249,7 @@ void KMeans::cluster(const NICE::VVector & features, NICE::VVector & prototypes,
       exit(-1);
   }
 
-  for (int k = 0; k < this->noClasses; k++)
+  for (int k = 0; k < this->noClusters; k++)
   {
       prototypes.push_back(Vector(dimension));
       prototypes[k].set(0);

+ 3 - 3
math/cluster/KMeans.h

@@ -36,7 +36,7 @@ namespace OBJREC {
         **************************/         
           
           //! desired number of clusters
-          int noClasses;
+          int noClusters;
           
           //! specify which distance to use for calculating assignments
           std::string distanceType;
@@ -91,10 +91,10 @@ namespace OBJREC {
 
         /**
         * @brief simple constructor
-        * @param _noClasses the number of clusters to be computed
+        * @param _noClusters the number of clusters to be computed
         * @param _distanceMode a string specifying the distance function to be used (default: euclidean)
         */
-        KMeans( const int & _noClasses , const std::string & _distanceMode="euclidean");
+        KMeans( const int & _noClusters , const std::string & _distanceMode="euclidean");
       
         /**
         * @brief standard constructor

+ 1 - 0
math/cluster/RandomClustering.cpp

@@ -34,6 +34,7 @@ RandomClustering::RandomClustering(const int & _noClusters, const std::string &
 RandomClustering::RandomClustering( const NICE::Config *conf, const std::string & _section)
 {  
   this->noClusters = conf->gI( _section, "noClusters", 20);
+  std::cerr << "RandomClustering::RandomClustering -- noClusters: " << this->noClusters << std::endl;
   
   this->distanceType = conf->gS( _section, "distanceType", "euclidean" );
   this->distancefunction = GenericDistanceSelection::selectDistance(distanceType);  

+ 112 - 104
math/kernels/KernelData.h

@@ -1,4 +1,4 @@
-/** 
+/**
 * @file KernelData.h
 * @author Erik Rodner
 * @date 01/19/2010
@@ -12,115 +12,123 @@
 #include "core/vector/MatrixT.h"
 
 namespace OBJREC {
-  
+
 /** @class KernelData
- * caching some kernel data 
+ * caching some kernel data
  *
  * @author Erik Rodner
  */
 class KernelData
 {
-	public:
-		enum {
-			QUADRATIC_DISTANCES = 0
-		};
-
-	protected:
-		bool verbose;
-
-		NICE::CholeskyRobust *cr;
-
-    protected:
-		NICE::Matrix kernelMatrix;
-
-		NICE::Matrix inverseKernelMatrix;
-
-		NICE::Matrix choleskyMatrix;
-
-	 std::map<int, NICE::Matrix *> cachedMatrices;
-
-		double logdet;
-
-		void initFromConfig ( const NICE::Config *conf, const std::string & section );
-
-		NICE::Matrix B;
-		NICE::Matrix U;
-		NICE::Matrix V;
-		NICE::Matrix F;
-		NICE::Matrix F_inv;
-
-    public:
-  
-  		/** standard stuff */
-  		KernelData();
-
-		/** copy constructor */
-  		KernelData( const KernelData & src );
-
-		/** simple constructor using config settings for numerical details */
-		KernelData( const NICE::Config *conf, const std::string & section = "Kernel" );
-		
-		/** the config contains information about numerical setting of the cholesky factorization etc. */
-		KernelData( const NICE::Config *conf, const NICE::Matrix & kernelMatrix, const std::string & section = "Kernel", bool updateCholesky = true );
-		  
-		/** simple destructor */
-		virtual ~KernelData();
-
-		/** update the cholesky factorization necessary to use computeInverseKernelMultiply */
-		virtual void updateCholeskyFactorization ();
-
-		/** in nearly all cases computeInverseKernelMultiply can be used instead */
-		virtual void updateInverseKernelMatrix ();
-		
-		/** compute K^{-1} * x */
-		virtual void computeInverseKernelMultiply ( const NICE::Vector & x, NICE::Vector & result ) const;
-
-		/** standard const and non-const get functions */
-		virtual const NICE::Matrix & getKernelMatrix() const;
-		virtual NICE::Matrix & getKernelMatrix();
-		virtual const NICE::Matrix & getInverseKernelMatrix() const;
-		virtual NICE::Matrix & getInverseKernelMatrix();
-		virtual const NICE::Matrix & getCholeskyMatrix() const;
-
-		/** get the logdet of the current kernel matrix (cholesky factorization has to be computed in advance) */
-		double getLogDetKernelMatrix () const { return logdet; };
-		
-		/** get the numbers of rows (and columns) of the kernel matrix */
-		virtual uint getKernelMatrixSize () const;
-
-		/** get a pre-cached matrix */
-		const NICE::Matrix & getCachedMatrix (int i) const;
-		/** set a pre-cached matrix */
-		void setCachedMatrix (int i, NICE::Matrix *m);
-
-		/** did we already start updateCholeskyFactorization() */
-		bool hasCholeskyFactorization () const { return (choleskyMatrix.rows() == kernelMatrix.rows()); };
-
-		/** get efficient GP regression loo estimates and corresponding variances, which can be used
-		  * to perform model selection (cf. Rasmussen and Williams) */
-		void getLooEstimates ( const NICE::Vector & y, NICE::Vector & muLoo, NICE::Vector & sigmaLoo ) const;
-
-		/** clone this object */
-		virtual KernelData *clone(void) const;
-
-		void getGPLikelihoodWithOneNewRow( const NICE::Vector & y, const double & oldLogdetK, const int & rowIndex, const NICE::Vector & newRow, const NICE::Vector & oldAlpha, NICE::Vector & newAlpha, double & loglike);
-
-		void getGPLikelihoodWithOneNewRow_FirstPart( const int & rowIndex, const NICE::Vector & newRow);
-
-		void getGPLikelihoodWithOneNewRow_SecondPart( const NICE::Vector & y, const double & oldLogdetK, const NICE::Vector & oldAlpha, NICE::Vector & newAlpha, double & loglike);
-		
-		void perform_Rank_2_Update(const int & rowIndex, const NICE::Vector & newRow);
-		void perform_Rank_2k_Update(const std::vector<int> & rowIndices, const std::vector<NICE::Vector> & newRows);
-		void delete_one_row(const int & rowIndex);
-		void delete_multiple_rows(std::vector<int> & indices);
-		
-		void setKernelMatrix(const NICE::Matrix & k_matrix);
-		
-		void increase_size_by_One();
-		void increase_size_by_k(const uint & k);
-		
-		void set_verbose(const bool & _verbose){ verbose = _verbose;};
-		bool get_verbose(){ return verbose;};
+public:
+    enum {
+        QUADRATIC_DISTANCES = 0
+    };
+
+protected:
+    bool verbose;
+
+    NICE::CholeskyRobust *cr;
+
+protected:
+    NICE::Matrix kernelMatrix;
+
+    NICE::Matrix inverseKernelMatrix;
+
+    NICE::Matrix choleskyMatrix;
+
+    std::map<int, NICE::Matrix *> cachedMatrices;
+
+    double logdet;
+
+    void initFromConfig ( const NICE::Config *conf, const std::string & section );
+
+    NICE::Matrix B;
+    NICE::Matrix U;
+    NICE::Matrix V;
+    NICE::Matrix F;
+    NICE::Matrix F_inv;
+
+public:
+
+    /** standard stuff */
+    KernelData();
+
+    /** copy constructor */
+    KernelData( const KernelData & src );
+
+    /** simple constructor using config settings for numerical details */
+    KernelData( const NICE::Config *conf, const std::string & section = "Kernel" );
+
+    /** the config contains information about numerical setting of the cholesky factorization etc. */
+    KernelData( const NICE::Config *conf, const NICE::Matrix & kernelMatrix, const std::string & section = "Kernel", bool updateCholesky = true );
+
+    /** simple destructor */
+    virtual ~KernelData();
+
+    /** update the cholesky factorization necessary to use computeInverseKernelMultiply */
+    virtual void updateCholeskyFactorization ();
+
+    /** in nearly all cases computeInverseKernelMultiply can be used instead */
+    virtual void updateInverseKernelMatrix ();
+
+    /** compute K^{-1} * x */
+    virtual void computeInverseKernelMultiply ( const NICE::Vector & x, NICE::Vector & result ) const;
+
+    /** standard const and non-const get functions */
+    virtual const NICE::Matrix & getKernelMatrix() const;
+    virtual NICE::Matrix & getKernelMatrix();
+    virtual const NICE::Matrix & getInverseKernelMatrix() const;
+    virtual NICE::Matrix & getInverseKernelMatrix();
+    virtual const NICE::Matrix & getCholeskyMatrix() const;
+
+    /** get the logdet of the current kernel matrix (cholesky factorization has to be computed in advance) */
+    double getLogDetKernelMatrix () const {
+        return logdet;
+    };
+
+    /** get the numbers of rows (and columns) of the kernel matrix */
+    virtual uint getKernelMatrixSize () const;
+
+    /** get a pre-cached matrix */
+    const NICE::Matrix & getCachedMatrix (int i) const;
+    /** set a pre-cached matrix */
+    void setCachedMatrix (int i, NICE::Matrix *m);
+
+    /** did we already start updateCholeskyFactorization() */
+    bool hasCholeskyFactorization () const {
+        return (choleskyMatrix.rows() == kernelMatrix.rows());
+    };
+
+    /** get efficient GP regression loo estimates and corresponding variances, which can be used
+      * to perform model selection (cf. Rasmussen and Williams) */
+    void getLooEstimates ( const NICE::Vector & y, NICE::Vector & muLoo, NICE::Vector & sigmaLoo ) const;
+
+    /** clone this object */
+    virtual KernelData *clone(void) const;
+
+    void getGPLikelihoodWithOneNewRow( const NICE::Vector & y, const double & oldLogdetK, const int & rowIndex, const NICE::Vector & newRow, const NICE::Vector & oldAlpha, NICE::Vector & newAlpha, double & loglike);
+
+    void getGPLikelihoodWithOneNewRow_FirstPart( const int & rowIndex, const NICE::Vector & newRow);
+
+    void getGPLikelihoodWithOneNewRow_SecondPart( const NICE::Vector & y, const double & oldLogdetK, const NICE::Vector & oldAlpha, NICE::Vector & newAlpha, double & loglike);
+
+    void perform_Rank_2_Update(const int & rowIndex, const NICE::Vector & newRow);
+    void perform_Rank_2k_Update(const std::vector<int> & rowIndices, const std::vector<NICE::Vector> & newRows);
+    void delete_one_row(const int & rowIndex);
+    void delete_multiple_rows(std::vector<int> & indices);
+
+    void setKernelMatrix(const NICE::Matrix & k_matrix);
+
+    void increase_size_by_One();
+    void increase_size_by_k(const uint & k);
+
+    void set_verbose(const bool & _verbose) {
+        verbose = _verbose;
+    };
+    bool get_verbose() {
+        return verbose;
+    };
 };
 
 }

+ 26 - 10
progs/evaluateCompleteBoWPipeline.cpp

@@ -19,6 +19,7 @@
 //vislearning -- basic stuff
 #include <vislearning/baselib/Globals.h>
 #include <vislearning/baselib/ICETools.h>
+#include <vislearning/baselib/ProgressBar.h>
 #include <vislearning/cbaselib/MultiDataset.h>
 #include <vislearning/cbaselib/Example.h>
 #include <vislearning/cbaselib/ClassificationResult.h>
@@ -94,7 +95,6 @@ int main( int argc, char **argv )
   //this again is somehow redundant, but we need the labels lateron for easy access - change this to a better solution :)
   NICE::VectorT<int> labelsTrain ( numberOfTrainingImages, 0 );
   
-  //TODO replace the nasty makro by a suitable for-loop to make it omp-ready (parallelization)
   int imgCnt ( 0 );
    
   // the corresponding nasty makro: LOOP_ALL_S( *trainFiles )
@@ -198,9 +198,7 @@ int main( int argc, char **argv )
   
   std::string classifierType = conf->gS( "main", "classifierType", "GPHIK" );
   OBJREC::VecClassifier * classifier = OBJREC::GenericClassifierSelection::selectVecClassifier( conf, classifierType );
-  
-  //TODO integrate GP-HIK-NICE into vislearning and add it into genericClassifierSelection
-  
+    
   //this method adds the training data to the temporary knowledge of our classifier
   classifier->teach( trainSet );
   //now the actual training step starts (e.g., parameter estimation, ... )
@@ -216,15 +214,32 @@ int main( int argc, char **argv )
   delete featureExtractor;
   featureExtractor = OBJREC::GenericLFSelection::selectLocalFeatureRep ( conf, "features", OBJREC::GenericLFSelection::TESTING );  
   
-  NICE::Matrix confusionMat ( trainFiles->size() /* number of classes in training */, testFiles->size() /* number of classes for testing*/, 0.0 );
+  NICE::Matrix confusionMat ( testFiles->size() /* number of classes for testing*/, trainFiles->size() /* number of classes in training */, 0.0 );
   NICE::Timer t;
   
   ClassificationResults results;
   
-  LOOP_ALL_S( *testFiles )
+  ProgressBar pbClasses;
+  
+  // the corresponding nasty makro: LOOP_ALL_S( *testFiles )
+  for(LabeledSet::const_iterator classIt = testFiles->begin() ; classIt != testFiles->end() ; classIt++)
   {
-      EACH_INFO( classno, info );
-      std::string filename = info.img();
+    std::cerr <<" \n\nOverall update bar: " << std::endl;
+    pbClasses.update ( testFiles->size() );
+    std::cerr << "\nStart next class " << std::endl;
+    ProgressBar pbClassExamples;
+    for ( std::vector<ImageInfo *>::const_iterator imgIt = classIt->second.begin(); 
+          imgIt != classIt->second.end(); 
+          imgIt++, imgCnt++
+        ) 
+    {  
+      pbClassExamples.update ( classIt->second.size() );
+    
+      // the corresponding nasty makro: EACH_INFO( classno, info );
+      int classno ( classIt->first );
+      const ImageInfo imgInfo = *(*imgIt);   
+      
+      std::string filename = imgInfo.img();
   
       //**********************************************
       //
@@ -282,10 +297,11 @@ int main( int argc, char **argv )
         results.push_back( r );
       }      
       
-      confusionMat( classno_estimated, classno_groundtruth ) += 1;
+      confusionMat( classno_groundtruth, classno_estimated ) += 1;
+    }
   }
   
-  confusionMat.normalizeColumnsL1();
+  confusionMat.normalizeRowsL1();
   std::cerr << confusionMat << std::endl;
 
   std::cerr << "average recognition rate: " << confusionMat.trace()/confusionMat.rows() << std::endl;