SpectralCluster.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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. #include <iostream>
  8. #include <core/vector/Distance.h>
  9. #include <core/vector/Eigen.h>
  10. #include <map>
  11. #include "vislearning/math/cluster/SpectralCluster.h"
  12. using namespace OBJREC;
  13. using namespace std;
  14. using namespace NICE;
  15. SpectralCluster::SpectralCluster ( int _noClusters, double alpha ) : noClusters(_noClusters), kmeans(_noClusters)
  16. {
  17. this->alpha = alpha;
  18. }
  19. SpectralCluster::SpectralCluster( const NICE::Config *conf, const std::string & _section) : kmeans(conf)
  20. {
  21. this->noClusters = conf->gI( _section, "noClusters", 20);
  22. this->alpha = conf->gD( _section, "alpha", 1.0);
  23. }
  24. SpectralCluster::~SpectralCluster()
  25. {
  26. }
  27. void SpectralCluster::getSimilarityMatrix ( const VVector & features,
  28. NICE::Matrix & laplacian,
  29. double alpha )
  30. {
  31. NICE::Matrix distances ( laplacian );
  32. double mindist = numeric_limits<double>::max();
  33. double maxdist = - numeric_limits<double>::max();
  34. long int count = 0;
  35. double mean = 0.0;
  36. double stddev = 0.0;
  37. NICE::EuclidianDistance<double> distance;
  38. for ( int i = 0 ; i < (int)features.size() ; i++ )
  39. {
  40. const NICE::Vector & xi = features[i];
  41. for ( int j = i ; j < (int)features.size() ; j++ )
  42. {
  43. const NICE::Vector & xj = features[j];
  44. // double sim = xi * xj;
  45. double dist = distance.calculate ( xi, xj );
  46. distances(i, j) = dist;
  47. if ( dist < mindist )
  48. mindist = dist;
  49. if ( dist > maxdist )
  50. maxdist = dist;
  51. count++;
  52. mean += dist;
  53. }
  54. }
  55. mean /= count;
  56. for ( int i = 0 ; i < (int)features.size() ; i++ )
  57. {
  58. for ( int j = i ; j < (int)features.size() ; j++ )
  59. {
  60. double d = ( mean - distances(i, j) );
  61. stddev += d*d;
  62. }
  63. }
  64. stddev /= count;
  65. double norm = alpha / (2.0 * stddev);
  66. for ( int i = 0 ; i < (int)features.size() ; i++ )
  67. {
  68. for ( int j = i ; j < (int)features.size() ; j++ )
  69. {
  70. double sim = exp(-distances(i, j) * norm );
  71. laplacian(i, j) = - sim;
  72. laplacian(j, i) = - sim;
  73. }
  74. }
  75. }
  76. void SpectralCluster::computeLaplacian ( const NICE::VVector & features,
  77. NICE::Matrix & laplacian,
  78. int method, double alpha )
  79. {
  80. laplacian.set(0.0);
  81. getSimilarityMatrix(features, laplacian, alpha);
  82. NICE::Vector d ( laplacian.rows() );
  83. d.set(0.0);
  84. for ( int i = 0 ; i < (int)laplacian.rows(); i++ )
  85. {
  86. for ( int j = 0 ; j < (int)laplacian.cols(); j++ )
  87. {
  88. d[i] -=laplacian(i, j);
  89. }
  90. }
  91. // Now we got the negative weight matrix laplacian : -W
  92. // and the degree matrix : D
  93. // calculate normalization
  94. // D^-1 * L
  95. if ( method == L_RW_NORMALIZED )
  96. {
  97. // L = D^-1 L_unnormalized = I - D^-1*W
  98. for ( int i = 0 ; i < (int)laplacian.rows() ; i++ )
  99. {
  100. for ( int j = 0 ; j < (int)laplacian.cols() ; j++ )
  101. {
  102. laplacian(i, j) *= (1.0/d[i]);
  103. }
  104. }
  105. for ( int i = 0 ; i < (int)laplacian.rows() ; i++ )
  106. {
  107. laplacian(i, i) += 1.0;
  108. }
  109. }
  110. else if ( method == L_UNNORMALIZED )
  111. {
  112. // unnormalized version
  113. // L = D - W
  114. for ( int i = 0 ; i < (int)laplacian.rows() ; i++ )
  115. {
  116. laplacian(i, i) += d[i];
  117. }
  118. }
  119. }
  120. void SpectralCluster::cluster ( const NICE::VVector & features,
  121. NICE::VVector & prototypes,
  122. std::vector<double> & weights,
  123. std::vector<int> & assignment )
  124. {
  125. if ( features.size() <= 0 ) {
  126. fprintf (stderr, "FATAL ERROR: not enough features vectors provided\n");
  127. exit(-1);
  128. }
  129. const NICE::Vector & x = features[0];
  130. int dimension = x.size();
  131. NICE::Matrix laplacian ( features.size(), features.size() );
  132. computeLaplacian ( features, laplacian, L_RW_NORMALIZED, alpha );
  133. //computeLaplacian ( features, laplacian, L_UNNORMALIZED, alpha );
  134. NICE::Matrix eigvect;
  135. NICE::Vector eigvals;
  136. try {
  137. NICE::eigenvectorvalues ( laplacian, eigvect, eigvals );
  138. }
  139. catch (...)
  140. {
  141. std::cerr << "You should adjust the alpha parameter, or the features are somehow weird" << std::endl;
  142. std::cerr << "Laplacian = " << laplacian(0, 0, min((int)laplacian.rows()-1, 5), min((int)laplacian.cols()-1, 5)) << std::endl;
  143. throw Exception ("Laplacian matrix is singular or not well-conditioned!");
  144. }
  145. std::map<double, int> eigvals_sorted;
  146. for ( int i = 0 ; i < (int)eigvals.size(); i++ )
  147. {
  148. eigvals_sorted.insert ( make_pair( eigvals[i], i ) );
  149. }
  150. NICE::VVector spectral_features;
  151. for ( int i = 0 ; i < (int)eigvect.rows() ; i++ )
  152. {
  153. NICE::Vector eigvec_k ( noClusters );
  154. map<double, int>::const_iterator k = eigvals_sorted.begin();
  155. for ( int j = 0 ; j < noClusters ; j++ )
  156. {
  157. int eigval_index = k->second;
  158. eigvec_k[j] = eigvect(i, eigval_index ) ;
  159. k++;
  160. }
  161. spectral_features.push_back ( eigvec_k );
  162. }
  163. this->kmeans.cluster ( spectral_features, prototypes, weights, assignment );
  164. // recompute prototypes
  165. for ( int k = 0 ; k < noClusters ; k++ )
  166. {
  167. prototypes[k].resize( dimension );
  168. prototypes[k].set(0);
  169. weights[k] = 0;
  170. }
  171. int j = 0;
  172. for ( VVector::const_iterator i = features.begin();
  173. i != features.end();
  174. i++, j++ )
  175. {
  176. int k = assignment[j];
  177. NICE::Vector & p = prototypes[k];
  178. const NICE::Vector & x = *i;
  179. p += x;
  180. weights[k]++;
  181. }
  182. for ( int k = 0 ; k < noClusters ; k++ )
  183. {
  184. NICE::Vector & p = prototypes[k];
  185. if ( weights[k] <= 0 )
  186. {
  187. fprintf (stderr, "FATAL ERROR: spectral clustering produced empty cluster !\n");
  188. exit(-1);
  189. }
  190. p *= ( 1.0 / weights[k] );
  191. weights[k] = weights[k] / features.size();
  192. }
  193. }