SpectralCluster.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /**
  2. * @file SpectralCluster.cpp
  3. * @brief spectral clustering by kmeans-clustering of eigenvectors
  4. * @author Erik Rodner
  5. * @date 11/13/2007
  6. */
  7. #ifdef NOVISUAL
  8. #include <vislearning/nice_nonvis.h>
  9. #else
  10. #include <vislearning/nice.h>
  11. #endif
  12. #include <iostream>
  13. #include <core/vector/Distance.h>
  14. #include <core/vector/Eigen.h>
  15. #include <map>
  16. #include "vislearning/math/cluster/SpectralCluster.h"
  17. using namespace OBJREC;
  18. using namespace std;
  19. // refactor-nice.pl: check this substitution
  20. // old: using namespace ice;
  21. using namespace NICE;
  22. SpectralCluster::SpectralCluster ( int _noClasses, double alpha ) : noClasses(_noClasses), kmeans(_noClasses)
  23. {
  24. this->alpha = alpha;
  25. }
  26. SpectralCluster::~SpectralCluster()
  27. {
  28. }
  29. void SpectralCluster::getSimilarityMatrix ( const VVector & features,
  30. // refactor-nice.pl: check this substitution
  31. // old: Matrix & laplacian,
  32. NICE::Matrix & laplacian,
  33. double alpha )
  34. {
  35. // refactor-nice.pl: check this substitution
  36. // old: Matrix distances ( laplacian );
  37. NICE::Matrix distances ( laplacian );
  38. double mindist = numeric_limits<double>::max();
  39. double maxdist = - numeric_limits<double>::max();
  40. long int count = 0;
  41. double mean = 0.0;
  42. double stddev = 0.0;
  43. NICE::EuclidianDistance<double> distance;
  44. for ( int i = 0 ; i < (int)features.size() ; i++ )
  45. {
  46. // refactor-nice.pl: check this substitution
  47. // old: const Vector & xi = features[i];
  48. const NICE::Vector & xi = features[i];
  49. for ( int j = i ; j < (int)features.size() ; j++ )
  50. {
  51. // refactor-nice.pl: check this substitution
  52. // old: const Vector & xj = features[j];
  53. const NICE::Vector & xj = features[j];
  54. // double sim = xi * xj;
  55. double dist = distance.calculate ( xi, xj );
  56. // refactor-nice.pl: check this substitution
  57. // old: distances[i][j] = dist;
  58. distances(i, j) = dist;
  59. if ( dist < mindist )
  60. mindist = dist;
  61. if ( dist > maxdist )
  62. maxdist = dist;
  63. count++;
  64. mean += dist;
  65. }
  66. }
  67. mean /= count;
  68. for ( int i = 0 ; i < (int)features.size() ; i++ )
  69. for ( int j = i ; j < (int)features.size() ; j++ )
  70. {
  71. // refactor-nice.pl: check this substitution
  72. // old: double d = ( mean - distances[i][j] );
  73. double d = ( mean -distances(i, j) );
  74. stddev += d*d;
  75. }
  76. stddev /= count;
  77. double norm = alpha / (2.0 * stddev);
  78. for ( int i = 0 ; i < (int)features.size() ; i++ )
  79. for ( int j = i ; j < (int)features.size() ; j++ )
  80. {
  81. // refactor-nice.pl: check this substitution
  82. // old: double sim = exp(- distances[i][j] * norm );
  83. double sim = exp(-distances(i, j) * norm );
  84. // refactor-nice.pl: check this substitution
  85. // old: laplacian[i][j] = - sim;
  86. laplacian(i, j) = - sim;
  87. // refactor-nice.pl: check this substitution
  88. // old: laplacian[j][i] = - sim;
  89. laplacian(j, i) = - sim;
  90. }
  91. }
  92. void SpectralCluster::computeLaplacian ( const VVector & features,
  93. // refactor-nice.pl: check this substitution
  94. // old: Matrix & laplacian, int method, double alpha )
  95. NICE::Matrix & laplacian, int method, double alpha )
  96. {
  97. //unused:
  98. //int n = (int)features.size();
  99. laplacian.set(0.0);
  100. getSimilarityMatrix(features, laplacian, alpha);
  101. // refactor-nice.pl: check this substitution
  102. // old: Vector d ( laplacian.rows() );
  103. NICE::Vector d ( laplacian.rows() );
  104. d.set(0.0);
  105. for ( int i = 0 ; i < (int)laplacian.rows(); i++ )
  106. {
  107. for ( int j = 0 ; j < (int)laplacian.cols(); j++ )
  108. d[i] -=laplacian(i, j);
  109. }
  110. // Now we got the negative weight matrix laplacian : -W
  111. // and the degree matrix : D
  112. // calculate normalization
  113. // D^-1 * L
  114. if ( method == L_RW_NORMALIZED )
  115. {
  116. // L = D^-1 L_unnormalized = I - D^-1*W
  117. for ( int i = 0 ; i < (int)laplacian.rows() ; i++ )
  118. for ( int j = 0 ; j < (int)laplacian.cols() ; j++ )
  119. laplacian(i, j) *= (1.0/d[i]);
  120. for ( int i = 0 ; i < (int)laplacian.rows() ; i++ )
  121. laplacian(i, i) += 1.0;
  122. } else if ( method == L_UNNORMALIZED ) {
  123. // unnormalized version
  124. // L = D - W
  125. for ( int i = 0 ; i < (int)laplacian.rows() ; i++ )
  126. laplacian(i, i) += d[i];
  127. }
  128. }
  129. void SpectralCluster::cluster ( const VVector & features,
  130. VVector & prototypes,
  131. std::vector<double> & weights,
  132. std::vector<int> & assignment )
  133. {
  134. if ( features.size() <= 0 ) {
  135. fprintf (stderr, "FATAL ERROR: not enough features vectors provided\n");
  136. exit(-1);
  137. }
  138. // refactor-nice.pl: check this substitution
  139. // old: const Vector & x = features[0];
  140. const NICE::Vector & x = features[0];
  141. int dimension = x.size();
  142. // refactor-nice.pl: check this substitution
  143. // old: Matrix laplacian ( features.size(), features.size() );
  144. NICE::Matrix laplacian ( features.size(), features.size() );
  145. computeLaplacian ( features, laplacian, L_RW_NORMALIZED, alpha );
  146. //computeLaplacian ( features, laplacian, L_UNNORMALIZED, alpha );
  147. NICE::Matrix eigvect;
  148. NICE::Vector eigvals;
  149. NICE::eigenvectorvalues ( laplacian, eigvect, eigvals );
  150. // refactor-nice.pl: check this substitution
  151. // old: Matrix eigvals_sorted ( eigvals.size(), 1 );
  152. std::map<double, int> eigvals_sorted;
  153. for ( int i = 0 ; i < (int)eigvals.size(); i++ )
  154. {
  155. // refactor-nice.pl: check this substitution
  156. // old: eigvals_sorted[i][0] = i;
  157. eigvals_sorted.insert ( make_pair( eigvals[i], i ) );
  158. }
  159. // refactor: eigvals_sorted = eigvals_sorted || eigvals;
  160. // refactor: eigvals_sorted.Sort(1);
  161. VVector spectral_features;
  162. for ( int i = 0 ; i < (int)eigvect.rows() ; i++ )
  163. {
  164. // refactor-nice.pl: check this substitution
  165. // old: Vector eigvec_k ( noClasses );
  166. NICE::Vector eigvec_k ( noClasses );
  167. map<double, int>::const_iterator k = eigvals_sorted.begin();
  168. for ( int j = 0 ; j < noClasses ; j++ )
  169. {
  170. int eigval_index = k->second;
  171. // refactor-nice.pl: check this substitution
  172. // old: eigvec_k[j] = eigvect[i][ (int)eigvals_sorted[j][0] ] ;
  173. eigvec_k[j] = eigvect(i, eigval_index ) ;
  174. k++;
  175. }
  176. spectral_features.push_back ( eigvec_k );
  177. }
  178. kmeans.cluster ( spectral_features, prototypes, weights, assignment );
  179. // recompute prototypes
  180. for ( int k = 0 ; k < noClasses ; k++ )
  181. {
  182. prototypes[k].resize( dimension );
  183. prototypes[k].set(0);
  184. weights[k] = 0;
  185. }
  186. int j = 0;
  187. for ( VVector::const_iterator i = features.begin();
  188. i != features.end();
  189. i++, j++ )
  190. {
  191. int k = assignment[j];
  192. // refactor-nice.pl: check this substitution
  193. // old: Vector & p = prototypes[k];
  194. NICE::Vector & p = prototypes[k];
  195. // refactor-nice.pl: check this substitution
  196. // old: const Vector & x = *i;
  197. const NICE::Vector & x = *i;
  198. p += x;
  199. weights[k]++;
  200. }
  201. for ( int k = 0 ; k < noClasses ; k++ )
  202. {
  203. // refactor-nice.pl: check this substitution
  204. // old: Vector & p = prototypes[k];
  205. NICE::Vector & p = prototypes[k];
  206. if ( weights[k] <= 0 ) {
  207. fprintf (stderr, "FATAL ERROR: spectral clustering produced empty cluster !\n");
  208. exit(-1);
  209. }
  210. p *= ( 1.0 / weights[k] );
  211. weights[k] = weights[k] / features.size();
  212. }
  213. }