/** * @file KMeansMatlab.cpp * @brief K-Means * @author Erik Rodner * @date 02/04/2008 */ #include <iostream> #include "vislearning/math/cluster/KMeansMatlab.h" #include <set> using namespace OBJREC; using namespace std; // refactor-nice.pl: check this substitution // old: using namespace ice; using namespace NICE; #undef DEBUG_KMeansMatlab ///////////////////// ///////////////////// ///////////////////// // CONSTRUCTORS / DESTRUCTORS ///////////////////// ///////////////////// ///////////////////// KMeansMatlab::KMeansMatlab() : ClusterAlgorithm() { this->noClusters = 20; this->kmeansDir = "/home/rodner/osl/labor/cvs/osl/kernel/"; this->inputFN = "/tmp/KMeansMatlab.input"; this->outputFN = "/tmp/KMeansMatlab.output" ; this->matlabExec = "matlab"; this->matlabArgs = "-nosplash -nojvm -nodesktop"; } KMeansMatlab::KMeansMatlab( const NICE::Config * _conf, const std::string & _confSection ) { this->initFromConfig ( _conf, _confSection ); } KMeansMatlab::~KMeansMatlab() { if ( matlabPipe != NULL ) pclose (matlabPipe); } void KMeansMatlab::initFromConfig( const NICE::Config* _conf, const std::string& _confSection ) { this->noClusters = _conf->gI( _confSection, "noClusters", 20); this->kmeansDir = _conf->gS(_confSection, "source_root", "/home/rodner/osl/labor/cvs/osl/") + "/kernel/"; this->inputFN = _conf->gS(_confSection, "tmpInput", "/tmp/KMeansMatlab.input" ); this->outputFN = _conf->gS(_confSection, "tmpOutput", "/tmp/KMeansMatlab.output" ); this->matlabExec = _conf->gS(_confSection, "matlab_exec", "matlab"); this->matlabArgs = _conf->gS(_confSection, "matlab_args", "-nosplash -nojvm -nodesktop"); } ///////////////////// ///////////////////// ///////////////////// // CLUSTERING STUFF ///////////////////// ///////////////////// ////////////////// int KMeansMatlab::compute_prototypes ( const VVector & features, VVector & prototypes, std::vector<double> & weights, const std::vector<int> & assignment ) { int j = 0; // fprintf (stderr, "KMeansMatlab::compute_prototypes: init noClusters=%d\n", noClusters); for ( int k = 0 ; k < noClusters ; k++ ) { prototypes[k].set(0); weights[k] = 0; } // fprintf (stderr, "KMeansMatlab::compute_prototypes: compute means\n"); for ( VVector::const_iterator i = features.begin(); i != features.end(); i++, j++ ) { int k = assignment[j]; // refactor-nice.pl: check this substitution // old: Vector & p = prototypes[k]; NICE::Vector & p = prototypes[k]; // refactor-nice.pl: check this substitution // old: const Vector & x = *i; const NICE::Vector & x = *i; #ifdef DEBUG_KMeansMatlab // refactor-nice.pl: check this substitution // old: fprintf (stderr, "KMeansMatlab::compute_prototypes: vector %d has assignment %d\n", j, k ); fprintf (stderr, "KMeansMatlab::compute_prototypes: std::vector %d has assignment %d\n", j, k ); #endif p += x; #ifdef DEBUG_KMeansMatlab cerr << "vector was : " << x << endl; cerr << "prototype for this class is now : " << p << endl; #endif weights[k]++; } // fprintf (stderr, "KMeansMatlab::compute_prototypes: scaling\n"); for ( int k = 0 ; k < noClusters ; k++ ) { // refactor-nice.pl: check this substitution // old: Vector & p = prototypes[k]; NICE::Vector & p = prototypes[k]; #ifdef DEBUG_KMeansMatlab cerr << "prototype for this class before scaling : " << p << endl; #endif if ( weights[k] <= 0 ) { return -1; } p *= ( 1.0 / weights[k] ); weights[k] = weights[k] / features.size(); #ifdef DEBUG_KMeansMatlab cerr << "prototype for this class after scaling with " << weights[k] << " : " << p << endl; #endif } return 0; } void KMeansMatlab::cluster ( const VVector & features, VVector & prototypes, std::vector<double> & weights, std::vector<int> & assignment ) { prototypes.clear(); weights.clear(); assignment.clear (); weights.resize ( noClusters, 0 ); assignment.resize ( features.size(), 0 ); // ----------- routine argument ------------- // refactor-nice.pl: check this substitution // old: string routineCMD = "W = KMeansInterface('" + inputFN + "', '" + outputFN + "');\n"; std::string routineCMD = "W = KMeansInterface('" + inputFN + "', '" + outputFN + "');\n"; int dimension; if ( (int)features.size() >= noClusters ) dimension = features[0].size(); else { fprintf (stderr, "FATAL ERROR: Not enough feature vectors provided for KMeansMatlab\n"); exit(-1); } FILE *fi = fopen ( inputFN.c_str(), "w" ); if ( fi == NULL ) { fprintf (stderr, "KMeansMatlab: FATAL ERROR cannot write features!\n"); exit(-1); } fwrite (&noClusters, sizeof(int), 1, fi ); int n = features.size(); fwrite (&n, sizeof(int), 1, fi ); int d = features[0].size(); fwrite (&d, sizeof(int), 1, fi ); for ( size_t i = 0 ; i < features.size() ; i++ ) for ( size_t k = 0 ; k < features[i].size() ; k++ ) // refactor-nice.pl: check this substitution fwrite ( &(features[i][k]), sizeof(double), 1, fi); fclose(fi); // refactor-nice.pl: check this substitution // old: string chdirCMD = "cd '" + kmeansDir + "'\n"; std::string chdirCMD = "cd '" + kmeansDir + "'\n"; // refactor-nice.pl: check this substitution // old: string execCMD = matlabExec + " " + matlabArgs; std::string execCMD = matlabExec + " " + matlabArgs; matlabPipe = popen ( execCMD.c_str(), "w"); if ( matlabPipe == NULL ) { fprintf (stderr, "KMeansMatlab: FATAL ERROR cannot execute matlab!\n"); exit(-1); } fputs (chdirCMD.c_str(), matlabPipe); fputs (routineCMD.c_str(), matlabPipe); pclose ( matlabPipe ); FILE *g = fopen ( outputFN.c_str(), "r" ); if ( g == NULL ) { fprintf (stderr, "KMeansMatlab::teach: FATAL ERROR cannot read matlab result!\n"); exit(-1); } for ( size_t j = 0 ; j < features.size() ; j++ ) { int val = 0; if ( fread ( &val, sizeof(int), 1, g) <= 0 ) { // refactor-nice.pl: check this substitution // old: fprintf (stderr, "KMeansMatlab::cluster: FATAL ERROR reading vector file\n"); fprintf (stderr, "KMeansMatlab::cluster: FATAL ERROR reading std::vector file\n"); exit(-1); } assignment[j] = val-1; } fclose(g); for ( int k = 0 ; k < noClusters ; k++ ) { // fprintf (stderr, "KMeansMatlab::cluster prototype init constructor\n"); prototypes.push_back( Vector( dimension ) ); prototypes[k].set(0); } if ( compute_prototypes ( features, prototypes, weights, assignment ) < 0 ) { fprintf (stderr, "KMeansMatlab::cluster failure !!\n"); exit(-1); } } ///////////////////// INTERFACE PERSISTENT ///////////////////// // interface specific methods for store and restore ///////////////////// INTERFACE PERSISTENT ///////////////////// void KMeansMatlab::restore ( std::istream & is, int format ) { //delete everything we knew so far... this->clear(); if ( is.good() ) { std::string tmp; is >> tmp; //class name if ( ! this->isStartTag( tmp, "KMeansMatlab" ) ) { std::cerr << " WARNING - attempt to restore KMeansMatlab, 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, "KMeansMatlab" ) ) { b_endOfBlock = true; continue; } tmp = this->removeStartTag ( tmp ); if ( tmp.compare("noClusters") == 0 ) { is >> this->noClusters; is >> tmp; // end of block tmp = this->removeEndTag ( tmp ); } else if ( tmp.compare("kmeansDir") == 0 ) { is >> this->kmeansDir; is >> tmp; // end of block tmp = this->removeEndTag ( tmp ); } else if ( tmp.compare("inputFN") == 0 ) { is >> this->inputFN; is >> tmp; // end of block tmp = this->removeEndTag ( tmp ); } else if ( tmp.compare("outputFN") == 0 ) { is >> this->outputFN; is >> tmp; // end of block tmp = this->removeEndTag ( tmp ); } else if ( tmp.compare("matlabExec") == 0 ) { is >> this->matlabExec; is >> tmp; // end of block tmp = this->removeEndTag ( tmp ); } else if ( tmp.compare("matlabArgs") == 0 ) { is >> this->matlabArgs; is >> tmp; // end of block tmp = this->removeEndTag ( tmp ); } else { std::cerr << "WARNING -- unexpected KMeansMatlab object -- " << tmp << " -- for restoration... aborting" << std::endl; throw; } } } else { std::cerr << "KMeansMatlab::restore -- InStream not initialized - restoring not possible!" << std::endl; throw; } } void KMeansMatlab::store ( std::ostream & os, int format ) const { if (os.good()) { // show starting point os << this->createStartTag( "KMeansMatlab" ) << std::endl; os << this->createStartTag( "noClusters" ) << std::endl; os << this->noClusters << std::endl; os << this->createEndTag( "noClusters" ) << std::endl; os << this->createStartTag( "kmeansDir" ) << std::endl; os << this->kmeansDir << std::endl; os << this->createEndTag( "kmeansDir" ) << std::endl; os << this->createStartTag( "inputFN" ) << std::endl; os << this->inputFN << std::endl; os << this->createEndTag( "inputFN" ) << std::endl; os << this->createStartTag( "outputFN" ) << std::endl; os << this->outputFN << std::endl; os << this->createEndTag( "outputFN" ) << std::endl; os << this->createStartTag( "matlabExec" ) << std::endl; os << this->matlabExec << std::endl; os << this->createEndTag( "matlabExec" ) << std::endl; os << this->createStartTag( "matlabArgs" ) << std::endl; os << this->matlabArgs << std::endl; os << this->createEndTag( "matlabArgs" ) << std::endl; // done os << this->createEndTag( "KMeansMatlab" ) << std::endl; } else { std::cerr << "OutStream not initialized - storing not possible!" << std::endl; } } void KMeansMatlab::clear () { }