KMeansMatlab.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /**
  2. * @file KMeansMatlab.cpp
  3. * @brief K-Means
  4. * @author Erik Rodner
  5. * @date 02/04/2008
  6. */
  7. #include <iostream>
  8. #include "vislearning/math/cluster/KMeansMatlab.h"
  9. #include <set>
  10. using namespace OBJREC;
  11. using namespace std;
  12. // refactor-nice.pl: check this substitution
  13. // old: using namespace ice;
  14. using namespace NICE;
  15. #undef DEBUG_KMeansMatlab
  16. ///////////////////// ///////////////////// /////////////////////
  17. // CONSTRUCTORS / DESTRUCTORS
  18. ///////////////////// ///////////////////// /////////////////////
  19. KMeansMatlab::KMeansMatlab() : ClusterAlgorithm()
  20. {
  21. this->noClusters = 20;
  22. this->kmeansDir = "/home/rodner/osl/labor/cvs/osl/kernel/";
  23. this->inputFN = "/tmp/KMeansMatlab.input";
  24. this->outputFN = "/tmp/KMeansMatlab.output" ;
  25. this->matlabExec = "matlab";
  26. this->matlabArgs = "-nosplash -nojvm -nodesktop";
  27. }
  28. KMeansMatlab::KMeansMatlab( const NICE::Config * _conf, const std::string & _confSection )
  29. {
  30. this->initFromConfig ( _conf, _confSection );
  31. }
  32. KMeansMatlab::~KMeansMatlab()
  33. {
  34. if ( matlabPipe != NULL )
  35. pclose (matlabPipe);
  36. }
  37. void KMeansMatlab::initFromConfig( const NICE::Config* _conf, const std::string& _confSection )
  38. {
  39. this->noClusters = _conf->gI( _confSection, "noClusters", 20);
  40. this->kmeansDir = _conf->gS(_confSection, "source_root", "/home/rodner/osl/labor/cvs/osl/") + "/kernel/";
  41. this->inputFN = _conf->gS(_confSection, "tmpInput", "/tmp/KMeansMatlab.input" );
  42. this->outputFN = _conf->gS(_confSection, "tmpOutput", "/tmp/KMeansMatlab.output" );
  43. this->matlabExec = _conf->gS(_confSection, "matlab_exec", "matlab");
  44. this->matlabArgs = _conf->gS(_confSection, "matlab_args", "-nosplash -nojvm -nodesktop");
  45. }
  46. ///////////////////// ///////////////////// /////////////////////
  47. // CLUSTERING STUFF
  48. ///////////////////// ///////////////////// //////////////////
  49. int KMeansMatlab::compute_prototypes ( const VVector & features,
  50. VVector & prototypes,
  51. std::vector<double> & weights,
  52. const std::vector<int> & assignment )
  53. {
  54. int j = 0;
  55. // fprintf (stderr, "KMeansMatlab::compute_prototypes: init noClusters=%d\n", noClusters);
  56. for ( int k = 0 ; k < noClusters ; k++ )
  57. {
  58. prototypes[k].set(0);
  59. weights[k] = 0;
  60. }
  61. // fprintf (stderr, "KMeansMatlab::compute_prototypes: compute means\n");
  62. for ( VVector::const_iterator i = features.begin();
  63. i != features.end();
  64. i++, j++ )
  65. {
  66. int k = assignment[j];
  67. // refactor-nice.pl: check this substitution
  68. // old: Vector & p = prototypes[k];
  69. NICE::Vector & p = prototypes[k];
  70. // refactor-nice.pl: check this substitution
  71. // old: const Vector & x = *i;
  72. const NICE::Vector & x = *i;
  73. #ifdef DEBUG_KMeansMatlab
  74. // refactor-nice.pl: check this substitution
  75. // old: fprintf (stderr, "KMeansMatlab::compute_prototypes: vector %d has assignment %d\n", j, k );
  76. fprintf (stderr, "KMeansMatlab::compute_prototypes: std::vector %d has assignment %d\n", j, k );
  77. #endif
  78. p += x;
  79. #ifdef DEBUG_KMeansMatlab
  80. cerr << "vector was : " << x << endl;
  81. cerr << "prototype for this class is now : " << p << endl;
  82. #endif
  83. weights[k]++;
  84. }
  85. // fprintf (stderr, "KMeansMatlab::compute_prototypes: scaling\n");
  86. for ( int k = 0 ; k < noClusters ; k++ )
  87. {
  88. // refactor-nice.pl: check this substitution
  89. // old: Vector & p = prototypes[k];
  90. NICE::Vector & p = prototypes[k];
  91. #ifdef DEBUG_KMeansMatlab
  92. cerr << "prototype for this class before scaling : " << p << endl;
  93. #endif
  94. if ( weights[k] <= 0 ) {
  95. return -1;
  96. }
  97. p *= ( 1.0 / weights[k] );
  98. weights[k] = weights[k] / features.size();
  99. #ifdef DEBUG_KMeansMatlab
  100. cerr << "prototype for this class after scaling with " << weights[k] << " : " << p << endl;
  101. #endif
  102. }
  103. return 0;
  104. }
  105. void KMeansMatlab::cluster ( const VVector & features,
  106. VVector & prototypes,
  107. std::vector<double> & weights,
  108. std::vector<int> & assignment )
  109. {
  110. prototypes.clear();
  111. weights.clear();
  112. assignment.clear ();
  113. weights.resize ( noClusters, 0 );
  114. assignment.resize ( features.size(), 0 );
  115. // ----------- routine argument -------------
  116. // refactor-nice.pl: check this substitution
  117. // old: string routineCMD = "W = KMeansInterface('" + inputFN + "', '" + outputFN + "');\n";
  118. std::string routineCMD = "W = KMeansInterface('" + inputFN + "', '" + outputFN + "');\n";
  119. int dimension;
  120. if ( (int)features.size() >= noClusters )
  121. dimension = features[0].size();
  122. else {
  123. fprintf (stderr, "FATAL ERROR: Not enough feature vectors provided for KMeansMatlab\n");
  124. exit(-1);
  125. }
  126. FILE *fi = fopen ( inputFN.c_str(), "w" );
  127. if ( fi == NULL )
  128. {
  129. fprintf (stderr, "KMeansMatlab: FATAL ERROR cannot write features!\n");
  130. exit(-1);
  131. }
  132. fwrite (&noClusters, sizeof(int), 1, fi );
  133. int n = features.size();
  134. fwrite (&n, sizeof(int), 1, fi );
  135. int d = features[0].size();
  136. fwrite (&d, sizeof(int), 1, fi );
  137. for ( size_t i = 0 ; i < features.size() ; i++ )
  138. for ( size_t k = 0 ; k < features[i].size() ; k++ )
  139. // refactor-nice.pl: check this substitution
  140. fwrite ( &(features[i][k]), sizeof(double), 1, fi);
  141. fclose(fi);
  142. // refactor-nice.pl: check this substitution
  143. // old: string chdirCMD = "cd '" + kmeansDir + "'\n";
  144. std::string chdirCMD = "cd '" + kmeansDir + "'\n";
  145. // refactor-nice.pl: check this substitution
  146. // old: string execCMD = matlabExec + " " + matlabArgs;
  147. std::string execCMD = matlabExec + " " + matlabArgs;
  148. matlabPipe = popen ( execCMD.c_str(), "w");
  149. if ( matlabPipe == NULL )
  150. {
  151. fprintf (stderr, "KMeansMatlab: FATAL ERROR cannot execute matlab!\n");
  152. exit(-1);
  153. }
  154. fputs (chdirCMD.c_str(), matlabPipe);
  155. fputs (routineCMD.c_str(), matlabPipe);
  156. pclose ( matlabPipe );
  157. FILE *g = fopen ( outputFN.c_str(), "r" );
  158. if ( g == NULL )
  159. {
  160. fprintf (stderr, "KMeansMatlab::teach: FATAL ERROR cannot read matlab result!\n");
  161. exit(-1);
  162. }
  163. for ( size_t j = 0 ; j < features.size() ; j++ )
  164. {
  165. int val = 0;
  166. if ( fread ( &val, sizeof(int), 1, g) <= 0 )
  167. {
  168. // refactor-nice.pl: check this substitution
  169. // old: fprintf (stderr, "KMeansMatlab::cluster: FATAL ERROR reading vector file\n");
  170. fprintf (stderr, "KMeansMatlab::cluster: FATAL ERROR reading std::vector file\n");
  171. exit(-1);
  172. }
  173. assignment[j] = val-1;
  174. }
  175. fclose(g);
  176. for ( int k = 0 ; k < noClusters ; k++ )
  177. {
  178. // fprintf (stderr, "KMeansMatlab::cluster prototype init constructor\n");
  179. prototypes.push_back( Vector( dimension ) );
  180. prototypes[k].set(0);
  181. }
  182. if ( compute_prototypes ( features, prototypes, weights, assignment ) < 0 )
  183. {
  184. fprintf (stderr, "KMeansMatlab::cluster failure !!\n");
  185. exit(-1);
  186. }
  187. }
  188. ///////////////////// INTERFACE PERSISTENT /////////////////////
  189. // interface specific methods for store and restore
  190. ///////////////////// INTERFACE PERSISTENT /////////////////////
  191. void KMeansMatlab::restore ( std::istream & is, int format )
  192. {
  193. //delete everything we knew so far...
  194. this->clear();
  195. if ( is.good() )
  196. {
  197. std::string tmp;
  198. is >> tmp; //class name
  199. if ( ! this->isStartTag( tmp, "KMeansMatlab" ) )
  200. {
  201. std::cerr << " WARNING - attempt to restore KMeansMatlab, but start flag " << tmp << " does not match! Aborting... " << std::endl;
  202. throw;
  203. }
  204. bool b_endOfBlock ( false ) ;
  205. while ( !b_endOfBlock )
  206. {
  207. is >> tmp; // start of block
  208. if ( this->isEndTag( tmp, "KMeansMatlab" ) )
  209. {
  210. b_endOfBlock = true;
  211. continue;
  212. }
  213. tmp = this->removeStartTag ( tmp );
  214. if ( tmp.compare("noClusters") == 0 )
  215. {
  216. is >> this->noClusters;
  217. is >> tmp; // end of block
  218. tmp = this->removeEndTag ( tmp );
  219. }
  220. else if ( tmp.compare("kmeansDir") == 0 )
  221. {
  222. is >> this->kmeansDir;
  223. is >> tmp; // end of block
  224. tmp = this->removeEndTag ( tmp );
  225. }
  226. else if ( tmp.compare("inputFN") == 0 )
  227. {
  228. is >> this->inputFN;
  229. is >> tmp; // end of block
  230. tmp = this->removeEndTag ( tmp );
  231. }
  232. else if ( tmp.compare("outputFN") == 0 )
  233. {
  234. is >> this->outputFN;
  235. is >> tmp; // end of block
  236. tmp = this->removeEndTag ( tmp );
  237. }
  238. else if ( tmp.compare("matlabExec") == 0 )
  239. {
  240. is >> this->matlabExec;
  241. is >> tmp; // end of block
  242. tmp = this->removeEndTag ( tmp );
  243. }
  244. else if ( tmp.compare("matlabArgs") == 0 )
  245. {
  246. is >> this->matlabArgs;
  247. is >> tmp; // end of block
  248. tmp = this->removeEndTag ( tmp );
  249. }
  250. else
  251. {
  252. std::cerr << "WARNING -- unexpected KMeansMatlab object -- " << tmp << " -- for restoration... aborting" << std::endl;
  253. throw;
  254. }
  255. }
  256. }
  257. else
  258. {
  259. std::cerr << "KMeansMatlab::restore -- InStream not initialized - restoring not possible!" << std::endl;
  260. throw;
  261. }
  262. }
  263. void KMeansMatlab::store ( std::ostream & os, int format ) const
  264. {
  265. if (os.good())
  266. {
  267. // show starting point
  268. os << this->createStartTag( "KMeansMatlab" ) << std::endl;
  269. os << this->createStartTag( "noClusters" ) << std::endl;
  270. os << this->noClusters << std::endl;
  271. os << this->createEndTag( "noClusters" ) << std::endl;
  272. os << this->createStartTag( "kmeansDir" ) << std::endl;
  273. os << this->kmeansDir << std::endl;
  274. os << this->createEndTag( "kmeansDir" ) << std::endl;
  275. os << this->createStartTag( "inputFN" ) << std::endl;
  276. os << this->inputFN << std::endl;
  277. os << this->createEndTag( "inputFN" ) << std::endl;
  278. os << this->createStartTag( "outputFN" ) << std::endl;
  279. os << this->outputFN << std::endl;
  280. os << this->createEndTag( "outputFN" ) << std::endl;
  281. os << this->createStartTag( "matlabExec" ) << std::endl;
  282. os << this->matlabExec << std::endl;
  283. os << this->createEndTag( "matlabExec" ) << std::endl;
  284. os << this->createStartTag( "matlabArgs" ) << std::endl;
  285. os << this->matlabArgs << std::endl;
  286. os << this->createEndTag( "matlabArgs" ) << std::endl;
  287. // done
  288. os << this->createEndTag( "KMeansMatlab" ) << std::endl;
  289. }
  290. else
  291. {
  292. std::cerr << "OutStream not initialized - storing not possible!" << std::endl;
  293. }
  294. }
  295. void KMeansMatlab::clear ()
  296. {
  297. }