Xmipp  v3.23.11-Nereus
kerdensom.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 // KerDenSOM.cc
28 // Implements Smoothly Distributed Kernel Probability Density Estimator Self-Organizing Map
29 // This is an abstract base class for different variants of the KerDenSOM algorithm
30 //-----------------------------------------------------------------------------
31 
32 #include <fstream>
33 
34 #include "kerdensom.h"
35 
40 void KerDenSOM::nSteps(const unsigned long& _nSteps)
41 {
42  somNSteps = _nSteps;
43 }
44 
45 #ifdef UNUSED // detected as unused 29.6.2018
46 
49 double KerDenSOM::getSigma()
50 {
51  return sigma;
52 }
53 #endif
54 
55 //-----------------------------------------------------------------------------
56 
61 void KerDenSOM::setAnnSteps(const unsigned long& _annSteps)
62 {
63  annSteps = _annSteps;
64 }
65 
66 
67 //-----------------------------------------------------------------------------
68 
74 double KerDenSOM::test(const FuzzyMap& _som, const TS& _examples) const
75 {
76 
77  // Defines verbosity level
78  int verbosity = listener->getVerbosity();
79  if (verbosity)
80  {
81  listener->OnReportOperation((std::string) "\nEstimating quantization error....\n");
82  listener->OnInitOperation(_examples.size());
83  }
84 
85 
86  /* Scan all data entries */
87  double qerror = 0.0;
88  for (size_t i = 0; i < _examples.size(); i++)
89  {
90  SomIn& theBest = _som.fuzzyTest(i); // get the best
91  qerror += euclideanDistance(theBest, _examples.theItems[i]);
92  if (verbosity)
93  {
94  auto tmp = (int)((_examples.size() * 5) / 100);
95  if ((tmp == 0) && (i != 0))
96  tmp = i;
97  else
98  tmp = 1;
99  if ((i % tmp) == 0)
101  }
102  }
103  if (verbosity)
104  listener->OnProgress(_examples.size());
105  return (qerror / (double) _examples.size());
106 
107 }
108 
109 
110 //-----------------------------------------------------------------------------
111 
112 
116 void KerDenSOM::updateV(FuzzyMap* _som, const TS* _examples, const double& _reg)
117 {
118  unsigned t2 = 0; // Iteration index
119 
120  // Calculate Temporal scratch values
121  for (size_t cc = 0; cc < numNeurons; cc++)
122  {
123  double *ptrTmpMap_cc=&(tmpMap[cc][0]);
124  memset(ptrTmpMap_cc,0,dim*sizeof(double));
125  double &tmpDens_cc=tmpDens[cc];
126  if (_reg != 0)
127  tmpDens_cc = _reg * _som->getLayout().numNeig(_som, (SomPos) _som->indexToPos(cc));
128  else
129  tmpDens_cc = 0.;
130  for (size_t vv = 0; vv < numVectors; vv++)
131  {
132  auto tmpU = (double) _som->memb[vv][cc];
133  tmpDens_cc += tmpU;
134  const floatFeature * ptrExample=&(_examples->theItems[vv][0]);
135  for (size_t j = 0; j < dim; j++)
136  ptrTmpMap_cc[j] += tmpU * ptrExample[j];
137  }
138  }
139 
140  // Update Code vectors using a sort of Gauss-Seidel iterative algorithm.
141  // Usually 100 iterations are enough.
142  double convergence = 1;
143  double stopError2;
144  double stopError1;
145  double *ptrTmpV=&(tmpV[0]);
146  while ((convergence > 1e-5) && (t2 < 100))
147  {
148  t2++;
149  stopError2 = 0;
150  stopError1 = 0;
151  for (size_t cc = 0; cc < numNeurons; cc++)
152  {
153  if (_reg != 0)
154  _som->localAve(_som->indexToPos(cc), tmpV);
155  double *ptrTmpMap_cc=&(tmpMap[cc][0]);
156  double iTmpDens_cc=1.0/tmpDens[cc];
157  floatFeature *ptrCodeVector_cc=&(_som->theItems[cc][0]);
158  for (size_t j = 0; j < dim; j++)
159  {
160  double tmpU = (ptrTmpMap_cc[j] + ptrTmpV[j] * _reg) * iTmpDens_cc;
161  stopError1 += fabs(ptrCodeVector_cc[j] - tmpU);
162  stopError2 += fabs(tmpU);
163  ptrCodeVector_cc[j] = (floatFeature) tmpU;
164  }
165  } // for
166  convergence = stopError1 / stopError2;
167  } // while
168 }
169 
170 //-----------------------------------------------------------------------------
171 
172 // Main iterations
173 double KerDenSOM::mainIterations(FuzzyMap* _som, const TS* _examples, double& _sigma, const double& _reg)
174 {
175  int verbosity = listener->getVerbosity();
176  double stopError = 1e10;
177  double alpha;
178  double ts2;
179  size_t iter = 0;
180  if (somNSteps == 0)
181  return stopError;
182  if (verbosity == 1 || verbosity == 3)
184  do
185  {
186  iter++;
187  updateU(_som, _examples, _sigma, alpha);
188  ts2 = updateSigmaII(_som, _examples, _reg, alpha);
189  stopError = fabs(_sigma / ts2 - 1.);
190  _sigma = ts2;
191  updateV(_som, _examples, _reg);
192  if (verbosity == 1 || verbosity == 3)
193  listener->OnProgress(iter);
194  if (verbosity >= 2)
195  {
196  char s[100];
197  sprintf(s, "Iteration %d of %d. variation: %g\n", (int)iter, (int)somNSteps, stopError);
198  listener->OnReportOperation((std::string) s);
199  }
200  }
201  while ((stopError > epsilon) && (iter < somNSteps));
202  if (verbosity == 1 || verbosity == 3)
204  return stopError;
205 }
206 
207 
208 //-----------------------------------------------------------------------------
209 
210 // Estimate Sigma Part I
211 double KerDenSOM::updateSigmaI(FuzzyMap* _som, const TS* _examples)
212 {
213  double t = 0;
214 
215  // Computing Sigma (Part I)
216  for (size_t vv = 0; vv < numVectors; vv++)
217  {
218  const FeatureVector &example=_examples->theItems[vv];
219  const floatFeature *ptrExample0=&example[0];
220  for (size_t cc = 0; cc < numNeurons; cc++)
221  {
222  double r = 0.0;
223  const floatFeature *ptrExample=ptrExample0;
224  const floatFeature *ptrCodeVector=&(_som->theItems[cc][0]);
225  for (size_t j = 0; j < dim; j++)
226  {
227  double diff=(double)(*ptrExample++) - (double)(*ptrCodeVector++);
228  r += diff*diff;
229  }
230  t += r * (double)(_som->memb[vv][cc]);
231  }
232  }
233  return (double)(t / (double)(numVectors*dim));
234 }
235 
236 //-----------------------------------------------------------------------------
237 /**************** Necessary stuff ***************************************/
238 //-----------------------------------------------------------------------------
239 
240 
241 //-----------------------------------------------------------------------------
242 
246 void KerDenSOM::updateV1(FuzzyMap* _som, const TS* _examples)
247 {
248  for (size_t cc = 0; cc < numNeurons; cc++)
249  {
250  std::vector<double> &tmpMap_cc=tmpMap[cc];
251  double *ptrTmpMap_cc0=&tmpMap_cc[0];
252  memset(ptrTmpMap_cc0,0,dim*sizeof(double));
253  double &tmpDens_cc=tmpDens[cc];
254  tmpDens_cc = 0.0;
255  for (size_t vv = 0; vv < numVectors; vv++)
256  {
257  double tmpU = _som->memb[vv][cc];
258  tmpDens_cc += tmpU;
259  const floatFeature *ptrExample=&(_examples->theItems[vv][0]);
260  double *ptrTmpMap_cc=ptrTmpMap_cc0;
261  for (size_t j = 0; j < dim; j++)
262  {
263  *ptrTmpMap_cc += tmpU * (*ptrExample);
264  ++ptrExample;
265  ++ptrTmpMap_cc;
266  }
267  }
268  }
269 
270  for (size_t cc = 0; cc < numNeurons; cc++)
271  {
272  const std::vector<double> &tmpMap_cc=tmpMap[cc];
273  double itmpDens_cc=1.0/tmpDens[cc];
274  FeatureVector &codevector=_som->theItems[cc];
275  for (size_t j = 0; j < dim; j++)
276  {
277  double tmpU =tmpMap_cc[j] * itmpDens_cc;
278  codevector[j] = (floatFeature) tmpU;
279  }
280  } // for
281 }
282 
283 //-----------------------------------------------------------------------------
287 void KerDenSOM::updateU1(FuzzyMap* _som, const TS* _examples)
288 {
289 
290  double auxProd;
291  double auxDist;
292  double tmp;
293  size_t k;
294  size_t j;
295  size_t i;
296 
297  // Update Membership matrix
298  for (k = 0; k < numVectors; k++)
299  {
300  auxProd = 1;
301  for (j = 0; j < numNeurons; j++)
302  auxProd *= euclideanDistance(_som->theItems[j], _examples->theItems[k]);
303 
304  if (auxProd == 0.)
305  { // Apply k-means criterion (Data-CB) must be > 0
306  for (j = 0; j < numNeurons; j ++)
307  if (euclideanDistance(_som->theItems[j], _examples->theItems[k]) == 0.)
308  _som->memb[k][j] = 1.0;
309  else
310  _som->memb[k][j] = 0.0;
311  }
312  else
313  {
314  for (i = 0; i < numNeurons; i ++)
315  {
316  auxDist = 0;
317  for (j = 0; j < numNeurons; j ++)
318  {
319  tmp = euclideanDistance(_som->theItems[i], _examples->theItems[k]) /
320  euclideanDistance(_som->theItems[j], _examples->theItems[k]);
321  auxDist += pow(tmp, 2);
322  } // for j
323  _som->memb[k][i] = (floatFeature) 1.0 / auxDist;
324  } // for i
325  } // if auxProd
326  } // for k
327 }
328 
329 //-----------------------------------------------------------------------------
330 
335 {
336  unsigned cc;
337  unsigned vv;
338 
339  // Take random samples
341  for (vv = 0; vv < numVectors; vv++)
342  {
343  double t = 0.;
344  for (cc = 0; cc < numNeurons; cc++)
345  {
346  _som->memb[vv][cc] = (floatFeature) rnd_unif();
347  t += _som->memb[vv][cc];
348  }
349  for (cc = 0; cc < numNeurons; cc++)
350  _som->memb[vv][cc] /= (floatFeature) t;
351  }
352 }
353 
354 
355 //-----------------------------------------------------------------------------
356 
357 #ifdef UNUSED // detected as unused 29.6.2018
358 
362 double KerDenSOM::randApproxGVC(const TS* _examples, const FuzzyMap* _som, double _dataSD, double _reg)
363 {
364  unsigned j, vv, cc;
365  double num, den, r;
366  FeatureVector VV;
367  VV.resize(dim, 0.0);
368  FuzzyMap tmpSOM(*_som);
369  TS tmpTS(*_examples);
370  num = 0;
371 
372  for (vv = 0; vv < numVectors; vv++)
373  {
374  for (j = 0; j < dim; j++)
375  VV[j] = 0.0;
376  for (cc = 0; cc < numNeurons; cc++)
377  {
378  for (j = 0; j < dim; j++)
379  VV[j] += (_examples->theItems[vv][j] - _som->theItems[cc][j]) * _som->memb[vv][cc];
380  }
381  for (j = 0; j < dim; j++)
382  num += VV[j] * VV[j];
383  }
384 
386  for (vv = 0; vv < numVectors; vv++)
387  {
388  for (j = 0; j < dim; j++)
389  tmpTS.theItems[vv][j] += rnd_gaus() * _dataSD;
390  }
391  updateV(&tmpSOM, &tmpTS, _reg);
392  den = 0.0;
393 
395  for (vv = 0; vv < numVectors; vv++)
396  {
397  for (j = 0; j < dim; j++)
398  VV[j] = 0.0;
399  for (cc = 0; cc < numNeurons; cc++)
400  {
401  for (j = 0; j < dim; j++)
402  VV[j] += (tmpTS.theItems[vv][j] - tmpSOM.theItems[cc][j] - _examples->theItems[vv][j] + _som->theItems[cc][j]) * _som->memb[vv][cc];
403  }
404  r = 0.;
405  for (j = 0; j < dim; j++)
406  r += VV[j] * rnd_gaus() * _dataSD;
407  den += r * r;
408  }
409  if (den != 0)
410  return (double) num / den;
411  else
412  return 0.;
413 }
414 #endif
415 
416 //-----------------------------------------------------------------------------
417 /**************** Visualization methods ***************************************/
418 //-----------------------------------------------------------------------------
419 
420 
421 //-----------------------------------------------------------------------------
422 
427 void KerDenSOM::showX(const TS* _ts)
428 {
429  std::cout << "Data (1..nd, 1..nv) " << std::endl;
430  for (size_t i = 0; i < _ts->size(); i++)
431  {
432  for (size_t j = 0; j < _ts->theItems[0].size(); j++)
433  {
434  std::cout << i + 1 << " " << j + 1 << " " << _ts->theItems[i][j] << std::endl;
435  }
436  }
437 }
438 
439 //-----------------------------------------------------------------------------
440 
446 {
447  std::cout << "Code vectors (1..ni, 1..nj, 1..nv) " << std::endl;
448  for (size_t i = 0; i < _som->size(); i++)
449  {
450  int tmpj = _som->indexToPos(i).first;
451  int tmpi = _som->indexToPos(i).second;
452  for (size_t j = 0; j < _som->theItems[0].size(); j++)
453  std::cout << tmpi + 1 << " " << tmpj + 1 << " " << j + 1 << " " << _som->theItems[i][j] << std::endl;
454  }
455 }
456 
457 //-----------------------------------------------------------------------------
462 void KerDenSOM::showU(FuzzyMap* _som, const TS* _ts)
463 {
464  std::cout << " Memberships (1..nd,1..ni,1..nj)" << std::endl;
465  for (size_t i = 0; i < _ts->size(); i++)
466  {
467  for (size_t j = 0; j < _som->size(); j++)
468  {
469  int tmpj = _som->indexToPos(j).first;
470  int tmpi = _som->indexToPos(j).second;
471  std::cout << i + 1 << " " << tmpi + 1 << " " << tmpj + 1 << " " << _som->memb[i][j] << std::endl;
472  }
473  }
474 }
475 
476 #ifdef UNUSED // detected as unused 29.6.2018
477 //-----------------------------------------------------------------------------
482 void KerDenSOM::printV(FuzzyMap* _som, const TS* _ts, FileName& _fname)
483 {
484  using namespace std;
485  FILE* F = fopen(_fname.c_str(), "w");
486  if (F == NULL)
487  {
488  return;
489  }
490 
491  fprintf(F, "%d %s %d %d gaussian\n", (int)dim, _som->layout().c_str(), (int)_som->width(), (int)_som->height());
492  if (_ts->isNormalized())
493  {
494  if (_ts->getNormalizationInfo().size() != _som->theItems[0].size())
495  {
496  std::stringstream msg;
497  msg << "Normalization information does not coincide with codebook structure";
498  throw std::runtime_error(msg.str());
499  }
500  for (unsigned it = 0; it < _som->size(); it++)
501  {
502  for (unsigned i = 0; i < _som->theItems[0].size(); i++)
503  {
504  if (!isnan(_som->theItems[it][i]))
505  _som->theItems[it][i] = _som->theItems[it][i] * _ts->getNormalizationInfo()[i].sd + _ts->getNormalizationInfo()[i].mean;
506  fprintf(F, "%g ", _som->theItems[it][i]);
507  }
508  fprintf(F, "\n");
509  }
510  }
511  else
512  {
513  for (size_t i = 0; i < _som->size(); i++)
514  {
515  for (size_t j = 0; j < _som->theItems[0].size(); j++)
516  fprintf(F, "%g ", _som->theItems[i][j]);
517  fprintf(F, "\n");
518  }
519  }
520 
521  fclose(F);
522 
523 }
524 #endif
525 //-----------------------------------------------------------------------------
void showU(FuzzyMap *_som, const TS *_ts)
Definition: kerdensom.cpp:462
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.
size_t dim
Definition: kerdensom.h:135
void localAve(const SomPos &_center, std::vector< double > &_aveVector) const
Definition: map.cpp:896
SomPos indexToPos(const unsigned &_i) const
Definition: map.cpp:1033
const std::string & layout() const
Definition: map.cpp:865
virtual void OnReportOperation(const std::string &_rsOp)=0
virtual double updateSigmaII(FuzzyMap *_som, const TS *_examples, const double &_reg, const double &_alpha)=0
size_t somNSteps
Definition: kerdensom.h:128
virtual void OnInitOperation(unsigned long _est_it)=0
double epsilon
Definition: kerdensom.h:127
virtual const unsigned & getVerbosity() const
Definition: xmipp_funcs.h:1065
size_t annSteps
Definition: kerdensom.h:124
virtual const Layout & getLayout() const
Definition: map.h:539
float floatFeature
Definition: data_types.h:72
virtual double test(const FuzzyMap &_som, const TS &_examples) const
Definition: kerdensom.cpp:74
unsigned width() const
Definition: map.cpp:916
size_t numNeurons
Definition: kerdensom.h:133
glob_prnt iter
virtual void updateV1(FuzzyMap *_som, const TS *_examples)
Definition: kerdensom.cpp:246
FeatureVector SomIn
Definition: map.h:44
#define i
void init_random_generator(int seed)
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
virtual double updateU(FuzzyMap *_som, const TS *_examples, const double &_sigma, double &_alpha)=0
double rnd_unif()
double vv
void showV(FuzzyMap *_som)
Definition: kerdensom.cpp:445
std::vector< std::vector< double > > tmpMap
Definition: kerdensom.h:136
virtual void initU(FuzzyMap *_som)
Definition: kerdensom.cpp:334
std::vector< Item > theItems
Definition: training_set.h:84
std::pair< long, long > SomPos
Definition: map.h:45
unsigned height() const
Definition: map.cpp:924
void setAnnSteps(const unsigned long &_annSteps)
Definition: kerdensom.cpp:61
virtual void OnProgress(unsigned long _it)=0
double sigma
Definition: kerdensom.h:123
#define j
virtual double mainIterations(FuzzyMap *_som, const TS *_examples, double &_sigma, const double &_reg)
Definition: kerdensom.cpp:173
virtual double numNeig(const FuzzyMap *_som, const SomPos &_center) const =0
virtual void updateV(FuzzyMap *_som, const TS *_examples, const double &_sigma)
Definition: kerdensom.cpp:116
virtual FeatureVector & fuzzyTest(unsigned _in) const
double rnd_gaus()
virtual double updateSigmaI(FuzzyMap *_som, const TS *_examples)
Definition: kerdensom.cpp:211
fprintf(glob_prnt.io, "\)
void showX(const TS *_ts)
Definition: kerdensom.cpp:427
std::vector< double > tmpDens
Definition: kerdensom.h:139
unsigned int randomize_random_generator()
std::vector< double > tmpV
Definition: kerdensom.h:140
virtual void updateU1(FuzzyMap *_som, const TS *_examples)
Definition: kerdensom.cpp:287
size_t numVectors
Definition: kerdensom.h:134
std::vector< floatFeature > FeatureVector
Definition: data_types.h:86
void nSteps(const unsigned long &_nSteps)
Definition: kerdensom.cpp:40