Bläddra i källkod

support non-sparse vector in FPC when VecClassifiers are called

Alexander Freytag 12 år sedan
förälder
incheckning
f8c977d5cc

+ 33 - 5
classifier/fpclassifier/FPCGPHIK.cpp

@@ -34,12 +34,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 )
@@ -149,7 +174,10 @@ void FPCGPHIK::train ( FeaturePool & fp, Examples & examples )
 /** training process */
 void FPCGPHIK::train ( const std::vector< 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 ()

+ 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);  

+ 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;