Xmipp  v3.23.11-Nereus
fuzzy_som.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 //-----------------------------------------------------------------------------
27 // SOM.cc
28 // Implements Smoothly Distributed Fuzzy c-means Self-Organizing Map
29 //-----------------------------------------------------------------------------
30 
31 #include "fuzzy_som.h"
32 
33 #ifdef __sun
34 #include <ieeefp.h>
35 #endif
36 
37 #ifdef UNUSED // detected as unused 29.6.2018
38 //-----------------------------------------------------------------------------
43 void FuzzySOM::nSteps(const unsigned long& _nSteps)
44 {
45  somNSteps = _nSteps;
46 }
47 
48 //-----------------------------------------------------------------------------
53 void FuzzySOM::initialFuzzyMembership(const double& _m0)
54 {
55  m0 = _m0;
56 }
57 
58 
59 //-----------------------------------------------------------------------------
64 void FuzzySOM::finalFuzzyMembership(const double& _m1)
65 {
66  m1 = _m1;
67 }
68 
69 //-----------------------------------------------------------------------------
74 void FuzzySOM::setAnnSteps(const unsigned long& _annSteps)
75 {
76  annSteps = _annSteps;
77 }
78 
79 
80 //-----------------------------------------------------------------------------
85 void FuzzySOM::regularization(const double& _reg)
86 {
87  reg = _reg;
88 }
89 #endif
90 
91 //-----------------------------------------------------------------------------
97 void FuzzySOM::train(FuzzyMap& _som, const TS& _examples)
98 {
99 
100  numNeurons = _som.size();
101  numVectors = _examples.size();
102  dim = _examples.theItems[0].size();
103  tmpV.resize(dim, 0.);
104  tmpDens.resize(numNeurons, 0.);
105  tmpMap.resize(numNeurons);
106  for (size_t i = 0; i < numNeurons; i++)
107  tmpMap[i].resize(dim, 0.);
108 
109  tmpD.resize(numNeurons);
110  double stopError;
111 
112  int verbosity = listener->getVerbosity();
113  if (verbosity)
114  listener->OnReportOperation((std::string) "\nTraining Fuzzy SOM....\n");
115 
116  // Deterministic annealing step
117  if (annSteps)
118  {
119 
120  for (size_t i = 0; i < _examples.size(); i++)
121  for (size_t j = 0; j < _som.size(); j++)
122  _som.memb[i][j] = 0.;
123 
124  if (verbosity)
125  listener->OnReportOperation((std::string) "\nDeterministic annealing steps....\n");
126  if (verbosity == 1 || verbosity == 3)
127  listener->OnInitOperation(annSteps);
128 
129  double fuzz;
130  for (size_t iter = 0; iter < annSteps; iter++)
131  {
132 
133  fuzz = m0 - iter * (m0 - m1) / (annSteps - 1);
134  stopError = updateU(_som, _examples, fuzz);
135  updateV(_som, _examples, fuzz);
136  if (verbosity == 1 || verbosity == 3)
137  listener->OnProgress(iter);
138  if (verbosity >= 2)
139  {
140  char s[100];
141  sprintf(s, "Iteration %d of %d. Code vectors variation: %g\n", (int)(iter + 1), (int)annSteps, stopError);
142  listener->OnReportOperation((std::string) s);
143  }
144  }
145  if (verbosity == 1 || verbosity == 3)
146  listener->OnProgress(annSteps);
147  }
148 
149 
150  // Fixed steps
151 
152 
153  for (size_t i = 0; i < _examples.size(); i++)
154  for (size_t j = 0; j < _som.size(); j++)
155  _som.memb[i][j] = 0.;
156 
157 
158  if (verbosity)
159  listener->OnReportOperation((std::string) "\nFinal steps....\n");
160  if (verbosity == 1 || verbosity == 3)
161  listener->OnInitOperation(somNSteps);
162 
163  unsigned t = 0; // Iteration index
164  stopError = epsilon + 1; // Initially must be higher
165 
166  while ((stopError > epsilon) && (t < somNSteps))
167  {
168  stopError = updateU(_som, _examples, m1);
169  updateV(_som, _examples, m1);
170  t++;
171  if (verbosity == 1 || verbosity == 3)
172  listener->OnProgress(t);
173  if (verbosity >= 2)
174  {
175  char s[100];
176  sprintf(s, "Iteration %d of %d. Code vectors variation: %g\n", (int)t, (int)somNSteps, stopError);
177  listener->OnReportOperation((std::string) s);
178  }
179  } // while
180  if (verbosity == 1 || verbosity == 3)
181  listener->OnProgress(somNSteps);
182 
183 
184  tmpV.clear();
185  tmpDens.clear();
186  tmpMap.clear();
187  tmpD.clear();
188 
189 }
190 
191 
192 //-----------------------------------------------------------------------------
198 double FuzzySOM::test(const FuzzyMap& _som, const TS& _examples) const
199 {
200 
201  // Defines verbosity level
202  int verbosity = listener->getVerbosity();
203  if (verbosity)
204  {
205  listener->OnReportOperation((std::string) "\nEstimating quantization error....\n");
206  listener->OnInitOperation(_examples.size());
207  }
208 
209 
210  /* Scan all data entries */
211  double qerror = 0.0;
212  for (size_t i = 0; i < _examples.size(); i++)
213  {
214  SomIn& theBest = _som.fuzzyTest(i); // get the best
215  qerror += euclideanDistance(theBest, _examples.theItems[i]);
216  if (verbosity)
217  {
218  if ((i % (int)((_examples.size()*5) / 100)) == 0)
220  }
221  }
222  if (verbosity)
223  listener->OnProgress(_examples.size());
224  return (qerror / (double) _examples.size());
225 
226 }
227 
228 
229 //-----------------------------------------------------------------------------
233 double FuzzySOM::updateU(FuzzyMap& _som, const TS& _examples, const double& _m)
234 {
235 
236  // Create auxiliar stuff
237 
238  unsigned i;
239  unsigned j;
240  unsigned k;
241  double var = 0;
242  double auxDist;
243  double auxProd;
244  double auxExp;
245 
246  auxExp = 1. / (_m - 1.);
247  // Update Membership matrix
248 
249  for (k = 0; k < numVectors; k++)
250  {
251  auxProd = 0;
252  for (i = 0; i < numNeurons; i ++)
253  {
254  auxDist = 0;
255  for (j = 0; j < dim; j++)
256  auxDist += (double)((double)(_examples.theItems[k][j]) - (double)(_som.theItems[i][j])) * ((double)(_examples.theItems[k][j]) - (double)(_som.theItems[i][j]));
257  auxDist = pow(auxDist, auxExp);
258  if (!finite(auxDist))
259  auxDist = MAXFLOAT;
260  if (auxDist < MAXZERO)
261  auxDist = MAXZERO;
262  auxProd += (double) 1. / auxDist;
263  tmpD[i] = auxDist;
264  }
265  for (j = 0; j < numNeurons; j ++)
266  {
267  double tmp = 1. / (auxProd * tmpD[j]);
268  var += fabs((double)(_som.memb[k][j]) - tmp);
269  _som.memb[k][j] = (floatFeature) tmp;
270  }
271 
272 
273  } // for k
274 
275  var /= (double) numNeurons * numVectors;
276 
277  return var;
278 
279 }
280 
281 
282 //-----------------------------------------------------------------------------
286 void FuzzySOM::updateV(FuzzyMap& _som, const TS& _examples, const double& _m)
287 {
288  unsigned j;
289  unsigned cc;
290  unsigned vv;
291  unsigned t2 = 0; // Iteration index
292 
293  // Calculate Temporal scratch values
294  for (cc = 0; cc < numNeurons; cc++)
295  {
296  for (j = 0; j < dim; j++)
297  tmpMap[cc][j] = 0.;
298  tmpDens[cc] = reg;
299  for (vv = 0; vv < numVectors; vv++)
300  {
301  auto tmpU = (double) pow((double)(_som.memb[vv][cc]), (double)_m);
302  tmpDens[cc] += tmpU;
303  for (j = 0; j < dim; j++)
304  {
305  tmpMap[cc][j] += (double)((double) tmpU * (double)(_examples.theItems[vv][j]));
306  }
307  }
308  }
309 
310 
311  // Update Code vectors using a sort of Gauss-Seidel iterative algorithm.
312  // Usually 100 iterations are enough.
313 
314 
315  double stopError2 = 1;
316  while ((stopError2 > 1e-5) && (t2 < 100))
317  {
318  t2++;
319  stopError2 = 0;
320  for (cc = 0; cc < numNeurons; cc++)
321  {
322  if (reg != 0)
323  _som.localAve(_som.indexToPos(cc), tmpV);
324  for (j = 0; j < dim; j++)
325  {
326  tmpV[j] *= reg;
327  double tmpU = (tmpMap[cc][j] + tmpV[j]) / tmpDens[cc];
328  stopError2 += fabs((double)(_som.theItems[cc][j]) - tmpU);
329  _som.theItems[cc][j] = (floatFeature) tmpU;
330  }
331  } // for
332  stopError2 /= (double)(numNeurons * dim);
333  } // while
334 
335 }
336 
337 
338 //-----------------------------------------------------------------------------
339 
344 double FuzzySOM::functional(const TS& _examples, const FuzzyMap& _som, double _m, double _reg, double& _fidelity, double& _penalty)
345 {
346  unsigned j;
347  unsigned vv;
348  unsigned cc;
349  double t;
350  double t1;
351  double t2 = 0;
352  _fidelity = 0;
353  for (vv = 0; vv < numVectors; vv++)
354  {
355  for (cc = 0; cc < numNeurons; cc++)
356  {
357  t = 0;
358  for (size_t j = 0; j < dim; j++)
359  t += ((double)(_examples.theItems[vv][j]) - (double)(_som.theItems[cc][j])) * ((double)(_examples.theItems[vv][j]) - (double)(_som.theItems[cc][j]));
360  t1 = (double) pow((double)_som.memb[vv][cc], (double) _m);
361  t2 += t1;
362  _fidelity += t1 * t;
363  }
364  }
365  _fidelity /= t2;
366  _penalty = 0;
367 
368  if (reg != 0)
369  {
370  for (cc = 0; cc < numNeurons; cc++)
371  {
372  _som.localAve(_som.indexToPos(cc), tmpV);
373  for (j = 0; j < dim; j++)
374  {
375  _penalty += (_som.theItems[cc][j] - tmpV[j]) * (_som.theItems[cc][j] - tmpV[j]);
376  }
377  }
378  _penalty /= (double)(numNeurons);
379  }
380 
381  return (_fidelity - _reg*_penalty);
382 }
383 
384 #ifdef UNUSED // detected as unused 29.6.2018
385 //-----------------------------------------------------------------------------
386 void FuzzySOM::showX(const TS& _ts)
387 {
388  std::cout << "Data (1..nd, 1..nv) " << std::endl;
389  for (size_t i = 0; i < _ts.size(); i++)
390  {
391  for (size_t j = 0; j < _ts.theItems[0].size(); j++)
392  {
393  std::cout << i + 1 << " " << j + 1 << " " << _ts.theItems[i][j] << std::endl;
394  }
395  }
396 }
397 
398 //-----------------------------------------------------------------------------
399 void FuzzySOM::showV(FuzzyMap& _som)
400 {
401  std::cout << "Code vectors (1..ni, 1..nj, 1..nv) " << std::endl;
402  for (size_t i = 0; i < _som.size(); i++)
403  {
404  int tmpj = _som.indexToPos(i).first;
405  int tmpi = _som.indexToPos(i).second;
406  for (size_t j = 0; j < _som.theItems[0].size(); j++)
407  std::cout << tmpi + 1 << " " << tmpj + 1 << " " << j + 1 << " " << _som.theItems[i][j] << std::endl;
408  }
409 }
410 
411 //-----------------------------------------------------------------------------
412 void FuzzySOM::showU(FuzzyMap& _som, const TS& _ts)
413 {
414  std::cout << " Memberships (1..nd,1..ni,1..nj)" << std::endl;
415  for (size_t i = 0; i < _ts.size(); i++)
416  {
417  for (size_t j = 0; j < _som.size(); j++)
418  {
419  int tmpj = _som.indexToPos(j).first;
420  int tmpi = _som.indexToPos(j).second;
421  std::cout << i + 1 << " " << tmpi + 1 << " " << tmpj + 1 << " " << _som.memb[i][j] << std::endl;
422  }
423  }
424 
425 
426 }
427 #endif
Definition: map.h:308
double euclideanDistance(const std::vector< T > &_v1, const std::vector< T > &_v2)
Definition: vector_ops.h:377
MM memb
Alias for Fuzzy vectors.
void localAve(const SomPos &_center, std::vector< double > &_aveVector) const
Definition: map.cpp:896
SomPos indexToPos(const unsigned &_i) const
Definition: map.cpp:1033
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
virtual double test(const FuzzyMap &_som, const TS &_examples) const
Definition: fuzzy_som.cpp:198
float floatFeature
Definition: data_types.h:72
glob_prnt iter
FeatureVector SomIn
Definition: map.h:44
#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
double vv
#define MAXZERO
Definition: data_types.h:59
if(fabs(c[*nmax+ *nmax *c_dim1])==0.e0)
std::vector< Item > theItems
Definition: training_set.h:84
virtual void OnProgress(unsigned long _it)=0
#define MAXFLOAT
Definition: data_types.h:47
#define j
virtual FeatureVector & fuzzyTest(unsigned _in) const
virtual void train(FuzzyMap &_som, const TS &_examples)
Definition: fuzzy_som.cpp:97
virtual double functional(const TS &_examples, const FuzzyMap &_som, double _m, double _reg, double &_fidelity, double &_penalty)
Definition: fuzzy_som.cpp:344