Xmipp  v3.23.11-Nereus
fcmeans.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Alberto Pascual Montano (pascual@cnb.csic.es)
4  *
5  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20  * 02111-1307 USA
21  *
22  * All comments concerning this program package may be sent to the
23  * e-mail address 'xmipp@cnb.csic.es'
24  ***************************************************************************/
25 //-----------------------------------------------------------------------------
26 // FuzzyCMeans.cc
27 // Fuzzy c-means clustering algorithm
28 //-----------------------------------------------------------------------------
29 
30 #include "fcmeans.h"
31 
36 /*FuzzyCMeans::FuzzyCMeans( std::istream& _is )
37  :ClassificationAlgorithm< FuzzyCodeBook >( "FuzzyCMeans") {
38  _is >> m;
39  _is >> epsilon;
40  _is >> epochs;
41 };
42 */
43 
50 void FuzzyCMeans::train(FuzzyCodeBook& _xmippDS, TS& _examples) const
51 {
52 
53  // Defines verbosity
54 
55  int verbosity = listener->getVerbosity();
56  if (verbosity)
57  listener->OnReportOperation((std::string) "Training....\n");
58  if (verbosity == 1 || verbosity == 3)
60 
61  // Create auxiliar Codebook
62 
63  FuzzyCodeBook auxCB;
64 
65 
66  // Create auxiliar stuff
67 
68  unsigned numClusters = _xmippDS.size();
69  unsigned numVectors = _examples.size();
70  unsigned i;
71  unsigned j;
72  unsigned k;
73  double stopError = 0;
74  double auxError = 0;
75  double auxDist;
76  double auxProd;
77  double tmp;
78  double auxExp;
79  double auxSum;
80  unsigned t = 0; // Iteration index
81  FeatureVector zero(_xmippDS.theItems[0].size()) ;
82  fill(zero.begin(), zero.end(), 0.0);
83 
84 
85  // Initialize auxiliary Codebook
86 
87  auxCB = _xmippDS;
88 
89  // Set auxExp
90 
91  auxExp = 2 / (m - 1);
92 
93  // This is the main code of the algorithm. Iterates "epochs" times
94 
95 
96  stopError = epsilon + 1; // Initially must be higher
97 
98  while ((stopError > epsilon) && (t < epochs))
99  {
100 
101  // Update Membership matrix
102 
103  for (k = 0; k < numVectors; k++)
104  {
105 
106  auxProd = 1;
107  for (j = 0; j < numClusters; j++)
108  auxProd *= euclideanDistance(_xmippDS.theItems[j], _examples.theItems[k]);
109 
110  if (auxProd == 0.)
111  { // Apply k-means criterion (Data-CB) must be > 0
112  for (j = 0; j < numClusters; j ++)
113  if (euclideanDistance(_xmippDS.theItems[j], _examples.theItems[k]) == 0.)
114  _xmippDS.memb[k][j] = 1.0;
115  else
116  _xmippDS.memb[k][j] = 0.0;
117  }
118  else
119  {
120  for (i = 0; i < numClusters; i ++)
121  {
122  auxDist = 0;
123  for (j = 0; j < numClusters; j ++)
124  {
125  tmp = euclideanDistance(_xmippDS.theItems[i], _examples.theItems[k]) /
126  euclideanDistance(_xmippDS.theItems[j], _examples.theItems[k]);
127  auxDist += pow(tmp, auxExp);
128  } // for j
129  _xmippDS.memb[k][i] = (floatFeature) 1.0 / auxDist;
130  } // for i
131  } // if auxProd
132  } // for k
133 
134 
135  // Update code vectors (Cluster Centers)
136 
137  for (i = 0; i < numClusters; i++)
138  {
139  _xmippDS.theItems[i] = zero;
140  auxSum = 0;
141  for (k = 0; k < numVectors; k++)
142  {
143  _xmippDS.theItems[i] += (floatFeature) pow((double)(_xmippDS.memb[k][i]), m) * _examples.theItems[k];
144  auxSum += pow((double)(_xmippDS.memb[k][i]), m);
145  } // for i
146  _xmippDS.theItems[i] /= (floatFeature) auxSum;
147  } // for k
148 
149  // Compute stopping criterion
150  stopError = 0;
151  for (i = 0; i < numClusters; i ++)
152  {
153  auxError = euclideanDistance(_xmippDS.theItems[i], auxCB.theItems[i]);
154  stopError += auxError * auxError;
155  } // for i
156 
157 
158  // Update iteration index
159 
160  t++;
161  auxCB = _xmippDS;
162 
163  if (verbosity == 1 || verbosity == 3)
164  listener->OnProgress(t);
165  if (verbosity >= 2)
166  {
167  char s[100];
168  sprintf(s, "Iteration %d of %d. Code vectors variation: %g\n", t + 1, epochs, stopError);
169  listener->OnReportOperation((std::string) s);
170  }
171 
172  } // while
173 
174  if (verbosity == 1 || verbosity == 3)
176 
177 }// FuzzyCMeans::train
178 
184 double FuzzyCMeans::test(const FuzzyCodeBook& _xmippDS,
185  const TS& _examples) const
186 {
187 
188  // Defines verbosity
189 
190  int verbosity = listener->getVerbosity();
191  if (verbosity)
192  {
193  listener->OnReportOperation((std::string) "Testing....\n");
194  listener->OnInitOperation(_examples.size());
195  }
196 
197  double distortion = 0;
198  for (unsigned i = 0; i < _examples.size(); i ++)
199  {
200  const FeatureVector& auxS = _examples.theItems[i];
201  unsigned best = _xmippDS.output(auxS);
202  distortion += euclideanDistance(_xmippDS.theItems[best], _examples.theItems[i]);
203  if (verbosity)
205  };
206 
207  if (verbosity)
208  listener->OnProgress(_examples.size());
209 
210  return distortion / (double) _examples.size();
211 }
212 
218 double FuzzyCMeans::fuzzyTest(const FuzzyCodeBook& _xmippDS,
219  const TS& _examples) const
220 {
221 
222  // Defines verbosity
223 
224  int verbosity = listener->getVerbosity();
225  if (verbosity)
226  {
227  listener->OnReportOperation((std::string) "Testing....\n");
228  listener->OnInitOperation(_examples.size());
229  }
230 
231  double distortion = 0;
232  for (unsigned i = 0; i < _examples.size(); i ++)
233  {
234  unsigned best = _xmippDS.fuzzyOutput(i);
235  distortion += euclideanDistance(_xmippDS.theItems[best], _examples.theItems[i]);
236  if (verbosity)
238  };
239  if (verbosity)
240  listener->OnProgress(_examples.size());
241 
242  return distortion / (double)_examples.size();
243 }
244 
262 double FuzzyCMeans::F(const FuzzyCodeBook& _xmippDS) const
263 {
264  double F = 0.;
265  for (unsigned k = 0; k < _xmippDS.membVectors(); k++)
266  for (unsigned i = 0; i < _xmippDS.membClusters(); i++)
267  F += pow((double)(_xmippDS.memb[k][i]), 2);
268  return (F / (double)(_xmippDS.membVectors()));
269 }
270 
289 double FuzzyCMeans::H(const FuzzyCodeBook& _xmippDS) const
290 {
291  double H = 0.;
292  for (unsigned k = 0; k < _xmippDS.membVectors(); k++)
293  for (unsigned i = 0; i < _xmippDS.membClusters(); i++)
294  if (_xmippDS.memb[k][i] != 0.)
295  H += (double)(_xmippDS.memb[k][i]) * log((double)(_xmippDS.memb[k][i]));
296  return (-H / (double)(_xmippDS.membVectors()));
297 }
298 
299 #ifdef UNUSED // detected as unused 29.6.2018
300 
312 double FuzzyCMeans::NFI(const FuzzyCodeBook& _xmippDS) const
313 {
314  double F = 0.;
315  for (unsigned k = 0; k < _xmippDS.membVectors(); k++)
316  for (unsigned i = 0; i < _xmippDS.membClusters(); i++)
317  F += pow((double)(_xmippDS.memb[k][i]), 2);
318 
319  double NFI = (((double)(_xmippDS.membClusters()) * F - (double)(_xmippDS.membVectors())) / (double)(_xmippDS.membVectors())) / (double)(_xmippDS.membClusters() - 1);
320  return NFI;
321 }
322 #endif
323 
337 double FuzzyCMeans::S(const FuzzyCodeBook& _xmippDS,
338  const TS& _examples) const
339 {
340 
341  std::vector< std::vector< floatFeature > > ICD; // Intercluster distance
342  std::vector< std::vector< floatFeature > > D; // Distance from each data to cluster centers
343 
344  unsigned i;
345  D.resize(_xmippDS.membClusters());
346  for (i = 0; i < _xmippDS.membClusters(); i++)
347  {
348  std::vector <floatFeature> d;
349  d.resize(_xmippDS.membVectors());
350  for (unsigned k = 0; k < _xmippDS.membVectors(); k++)
351  d[k] = (floatFeature)euclideanDistance(_xmippDS.theItems[i], _examples.theItems[k]);
352  D[i] = d;
353  } // for i
354 
355  ICD.resize(_xmippDS.membClusters());
356  for (i = 0; i < _xmippDS.membClusters(); i++)
357  {
358  std::vector <floatFeature> v;
359  v.resize(_xmippDS.membVectors());
360  for (unsigned j = 0; j < _xmippDS.membClusters(); j++)
361  v[j] = (floatFeature)euclideanDistance(_xmippDS.theItems[i], _xmippDS.theItems[j]);
362  ICD[i] = v;
363  } // for i
364 
365  floatFeature auxSum = 0;
366  for (i = 0; i < _xmippDS.membClusters(); i++)
367  for (unsigned k = 0; k < _xmippDS.membVectors(); k++)
368  auxSum += (floatFeature) pow((double)(D[i][k] * _xmippDS.memb[k][i]), (double)m);
369 
370  floatFeature auxMin = MAXFLOAT;
371  for (i = 0; i < _xmippDS.membClusters(); i++)
372  for (unsigned j = i + 1; j < _xmippDS.membClusters(); j++)
373  if (auxMin > ICD[i][j])
374  auxMin = ICD[i][j];
375 
376  double S = auxSum / (double)(_xmippDS.membVectors()) / (double)(auxMin);
377  return S;
378 
379 }
380 
382 void FuzzyCMeans::printSelf(std::ostream& _os) const
383 {
384  // Call base class, which will print ID
385  _os << "Class (Algorithm): " << std::endl;
387  _os << std::endl;
388  // Print parameters in the same order they are declared
389  _os << "Fuzzy constant m = " << m << std::endl;
390  _os << "Epsilon eps = " << epsilon << std::endl;
391  _os << "Iterations iter = " << epochs << std::endl << std::endl;
392 }
virtual unsigned output(const FeatureVector &_in) const
Definition: code_book.cpp:350
double euclideanDistance(const std::vector< T > &_v1, const std::vector< T > &_v2)
Definition: vector_ops.h:377
MM memb
Alias for Fuzzy vectors.
double m
Definition: fcmeans.h:163
double S(const FuzzyCodeBook &_xmippDS, const TS &_examples) const
Definition: fcmeans.cpp:337
virtual void train(FuzzyCodeBook &_xmippDS, TS &_examples) const
Definition: fcmeans.cpp:50
virtual void OnReportOperation(const std::string &_rsOp)=0
virtual void OnInitOperation(unsigned long _est_it)=0
virtual const unsigned & getVerbosity() const
Definition: xmipp_funcs.h:1065
float floatFeature
Definition: data_types.h:72
unsigned membVectors() const
#define i
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
doublereal * d
void log(Image< double > &op)
virtual unsigned fuzzyOutput(unsigned _in) const
std::vector< Item > theItems
Definition: training_set.h:84
void printSelf(std::ostream &_os) const
print itself on standard output
Definition: fcmeans.cpp:382
virtual double test(const FuzzyCodeBook &_xmippDS, const TS &_examples) const
Definition: fcmeans.cpp:184
virtual void OnProgress(unsigned long _it)=0
double F(const FuzzyCodeBook &_xmippDS) const
Definition: fcmeans.cpp:262
#define MAXFLOAT
Definition: data_types.h:47
#define j
unsigned membClusters() const
virtual void printSelf(std::ostream &_os) const
double H(const FuzzyCodeBook &_xmippDS) const
Definition: fcmeans.cpp:289
virtual double fuzzyTest(const FuzzyCodeBook &_xmippDS, const TS &_examples) const
Definition: fcmeans.cpp:218
std::vector< floatFeature > FeatureVector
Definition: data_types.h:86
double epsilon
Definition: fcmeans.h:164
ql0001_ & zero(ctemp+1),(cvec+1),(a+1),(b+1),(bl+1),(bu+1),(x+1),(w+1), &iout, ifail, &zero,(w+3), &lwar2,(iw+1), &leniw, &glob_grd.epsmac
unsigned epochs
Definition: fcmeans.h:165