Algorithms_in_C  1.0.0
Set of algorithms implemented in C.
kohonen_som_topology.c File Reference

Kohonen self organizing map (topological map) More...

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
Include dependency graph for kohonen_som_topology.c:

Data Structures

struct  array_3d
 to store info regarding 3D arrays More...
 

Macros

#define _USE_MATH_DEFINES
 required for MS Visual C
 
#define max(a, b)   (((a) > (b)) ? (a) : (b))
 shorthand for maximum value
 
#define min(a, b)   (((a) < (b)) ? (a) : (b))
 shorthand for minimum value
 

Functions

double * data_3d (const struct array_3d *arr, int x, int y, int z)
 Function that returns the pointer to (x, y, z) ^th location in the linear 3D array given by: More...
 
double _random (double a, double b)
 Helper function to generate a random number in a given interval. More...
 
int save_2d_data (const char *fname, double **X, int num_points, int num_features)
 Save a given n-dimensional data martix to file. More...
 
int save_u_matrix (const char *fname, struct array_3d *W)
 Create the distance matrix or U-matrix from the trained weights and save to disk. More...
 
void get_min_2d (double **X, int N, double *val, int *x_idx, int *y_idx)
 Get minimum value and index of the value in a matrix. More...
 
double update_weights (const double *X, struct array_3d *W, double **D, int num_out, int num_features, double alpha, int R)
 Update weights of the SOM using Kohonen algorithm. More...
 
void kohonen_som (double **X, struct array_3d *W, int num_samples, int num_features, int num_out, double alpha_min)
 Apply incremental algorithm with updating neighborhood and learning rates on all samples in the given datset. More...
 
void test_2d_classes (double *const *data, int N)
 Creates a random set of points distributed in four clusters in 3D space with centroids at the points. More...
 
void test1 ()
 Test that creates a random set of points distributed in four clusters in 2D space and trains an SOM that finds the topological pattern. More...
 
void test_3d_classes1 (double *const *data, int N)
 Creates a random set of points distributed in four clusters in 3D space with centroids at the points. More...
 
void test2 ()
 Test that creates a random set of points distributed in 4 clusters in 3D space and trains an SOM that finds the topological pattern. More...
 
void test_3d_classes2 (double *const *data, int N)
 Creates a random set of points distributed in four clusters in 3D space with centroids at the points. More...
 
void test3 ()
 Test that creates a random set of points distributed in eight clusters in 3D space and trains an SOM that finds the topological pattern. More...
 
double get_clock_diff (clock_t start_t, clock_t end_t)
 Convert clock cycle difference to time in seconds. More...
 
int main (int argc, char **argv)
 Main function.
 

Detailed Description

Kohonen self organizing map (topological map)

Author
Krishna Vedala This example implements a powerful unsupervised learning algorithm called as a self organizing map. The algorithm creates a connected network of weights that closely follows the given data points. This thus creates a topological map of the given data i.e., it maintains the relationship between varipus data points in a much higher dimesional space by creating an equivalent in a 2-dimensional space. Trained topological maps for the test cases in the program
Warning
MSVC 2019 compiler generates code that does not execute as expected. However, MinGW, Clang for GCC and Clang for MSVC compilers on windows perform as expected. Any insights and suggestions should be directed to the author.
See also
kohonen_som_trace.c

Function Documentation

◆ _random()

double _random ( double  a,
double  b 
)

Helper function to generate a random number in a given interval.


Steps:

  1. r1 = rand() % 100 gets a random number between 0 and 99
  2. r2 = r1 / 100 converts random number to be between 0 and 0.99
  3. scale and offset the random number to given range of \([a,b)\)

    \[ y = (b - a) \times \frac{\text{(random number between 0 and RAND_MAX)} \; \text{mod}\; 100}{100} + a \]

Parameters
[in]alower limit
[in]bupper limit
Returns
random number in the range \([a,b)\)
81 {
82  return ((b - a) * (rand() % 100) / 100.f) + a;
83 }

◆ data_3d()

double* data_3d ( const struct array_3d arr,
int  x,
int  y,
int  z 
)

Function that returns the pointer to (x, y, z) ^th location in the linear 3D array given by:

\[ X_{i,j,k} = i\times M\times N + j\times N + k \]

where \(L\), \(M\) and \(N\) are the 3D matrix dimensions.

Parameters
[in]arrpointer to array_3d structure
[in]xfirst index
[in]ysecond index
[in]zthird index
Returns
pointer to (x,y,z)^th location of data
61 {
62  int offset = (x * arr->dim2 * arr->dim3) + (y * arr->dim3) + z;
63  return arr->data + offset;
64 }

◆ get_clock_diff()

double get_clock_diff ( clock_t  start_t,
clock_t  end_t 
)

Convert clock cycle difference to time in seconds.

Parameters
[in]start_tstart clock
[in]end_tend clock
Returns
time difference in seconds
651 {
652  return (double)(end_t - start_t) / (double)CLOCKS_PER_SEC;
653 }

◆ get_min_2d()

void get_min_2d ( double **  X,
int  N,
double *  val,
int *  x_idx,
int *  y_idx 
)

Get minimum value and index of the value in a matrix.

Parameters
[in]Xmatrix to search
[in]Nnumber of points in the vector
[out]valminimum value found
[out]x_idxx-index where minimum value was found
[out]y_idxy-index where minimum value was found
198 {
199  val[0] = INFINITY; // initial min value
200 
201  for (int i = 0; i < N; i++) // traverse each x-index
202  {
203  for (int j = 0; j < N; j++) // traverse each y-index
204  {
205  if (X[i][j] < val[0]) // if a lower value is found
206  { // save the value and its index
207  x_idx[0] = i;
208  y_idx[0] = j;
209  val[0] = X[i][j];
210  }
211  }
212  }
213 }

◆ kohonen_som()

void kohonen_som ( double **  X,
struct array_3d W,
int  num_samples,
int  num_features,
int  num_out,
double  alpha_min 
)

Apply incremental algorithm with updating neighborhood and learning rates on all samples in the given datset.

Parameters
[in]Xdata set
[in,out]Wweights matrix
[in]num_samplesnumber of output points
[in]num_featuresnumber of features per input sample
[in]num_outnumber of output points
[in]alpha_minterminal value of alpha
308 {
309  int R = num_out >> 2, iter = 0;
310  double **D = (double **)malloc(num_out * sizeof(double *));
311  for (int i = 0; i < num_out; i++)
312  D[i] = (double *)malloc(num_out * sizeof(double));
313 
314  double dmin = 1.f; // average minimum distance of all samples
315 
316  // Loop alpha from 1 to slpha_min
317  for (double alpha = 1.f; alpha > alpha_min && dmin > 1e-3;
318  alpha -= 0.001, iter++)
319  {
320  dmin = 0.f;
321  // Loop for each sample pattern in the data set
322  for (int sample = 0; sample < num_samples; sample++)
323  {
324  // update weights for the current input pattern sample
325  dmin += update_weights(X[sample], W, D, num_out, num_features,
326  alpha, R);
327  }
328 
329  // every 20th iteration, reduce the neighborhood range
330  if (iter % 100 == 0 && R > 1)
331  R--;
332 
333  dmin /= num_samples;
334  printf("iter: %5d\t alpha: %.4g\t R: %d\td_min: %.4g\r", iter, alpha, R,
335  dmin);
336  }
337  putchar('\n');
338 
339  for (int i = 0; i < num_out; i++) free(D[i]);
340  free(D);
341 }
Here is the call graph for this function:

◆ save_2d_data()

int save_2d_data ( const char *  fname,
double **  X,
int  num_points,
int  num_features 
)

Save a given n-dimensional data martix to file.

Parameters
[in]fnamefilename to save in (gets overwriten without confirmation)
[in]Xmatrix to save
[in]num_pointsrows in the matrix = number of points
[in]num_featurescolumns in the matrix = dimensions of points
Returns
0 if all ok
-1 if file creation failed
97 {
98  FILE *fp = fopen(fname, "wt");
99  if (!fp) // error with fopen
100  {
101  char msg[120];
102  sprintf(msg, "File error (%s): ", fname);
103  perror(msg);
104  return -1;
105  }
106 
107  for (int i = 0; i < num_points; i++) // for each point in the array
108  {
109  for (int j = 0; j < num_features; j++) // for each feature in the array
110  {
111  fprintf(fp, "%.4g", X[i][j]); // print the feature value
112  if (j < num_features - 1) // if not the last feature
113  fputc(',', fp); // suffix comma
114  }
115  if (i < num_points - 1) // if not the last row
116  fputc('\n', fp); // start a new line
117  }
118  fclose(fp);
119  return 0;
120 }

◆ save_u_matrix()

int save_u_matrix ( const char *  fname,
struct array_3d W 
)

Create the distance matrix or U-matrix from the trained weights and save to disk.

Parameters
[in]fnamefilename to save in (gets overwriten without confirmation)
[in]Wmodel matrix to save
Returns
0 if all ok
-1 if file creation failed
133 {
134  FILE *fp = fopen(fname, "wt");
135  if (!fp) // error with fopen
136  {
137  char msg[120];
138  sprintf(msg, "File error (%s): ", fname);
139  perror(msg);
140  return -1;
141  }
142 
143  int R = max(W->dim1 >> 3, 2); /* neighborhood range */
144 
145  for (int i = 0; i < W->dim1; i++) // for each x
146  {
147  for (int j = 0; j < W->dim2; j++) // for each y
148  {
149  double distance = 0.f;
150  int k;
151 
152  int from_x = max(0, i - R);
153  int to_x = min(W->dim1, i + R + 1);
154  int from_y = max(0, j - R);
155  int to_y = min(W->dim2, j + R + 1);
156  int l;
157 #ifdef _OPENMP
158 #pragma omp parallel for reduction(+ : distance)
159 #endif
160  for (l = from_x; l < to_x; l++) // scan neighborhoor in x
161  {
162  for (int m = from_y; m < to_y; m++) // scan neighborhood in y
163  {
164  double d = 0.f;
165  for (k = 0; k < W->dim3; k++) // for each feature
166  {
167  double *w1 = data_3d(W, i, j, k);
168  double *w2 = data_3d(W, l, m, k);
169  d += (w1[0] - w2[0]) * (w1[0] - w2[0]);
170  // distance += w1[0] * w1[0];
171  }
172  distance += sqrt(d);
173  // distance += d;
174  }
175  }
176 
177  distance /= R * R; // mean distance from neighbors
178  fprintf(fp, "%.4g", distance); // print the mean separation
179  if (j < W->dim2 - 1) // if not the last column
180  fputc(',', fp); // suffix comma
181  }
182  if (i < W->dim1 - 1) // if not the last row
183  fputc('\n', fp); // start a new line
184  }
185  fclose(fp);
186  return 0;
187 }
Here is the call graph for this function:

◆ test1()

void test1 ( )

Test that creates a random set of points distributed in four clusters in 2D space and trains an SOM that finds the topological pattern.

The following CSV files are created to validate the execution:

  • test1.csv: random test samples points with a circular pattern
  • w11.csv: initial random U-matrix
  • w12.csv: trained SOM U-matrix
394 {
395  int j, N = 300;
396  int features = 2;
397  int num_out = 30; // image size - N x N
398 
399  // 2D space, hence size = number of rows * 2
400  double **X = (double **)malloc(N * sizeof(double *));
401 
402  // cluster nodex in 'x' * cluster nodes in 'y' * 2
403  struct array_3d W;
404  W.dim1 = num_out;
405  W.dim2 = num_out;
406  W.dim3 = features;
407  W.data = (double *)malloc(num_out * num_out * features *
408  sizeof(double)); // assign rows
409 
410  for (int i = 0; i < max(num_out, N); i++) // loop till max(N, num_out)
411  {
412  if (i < N) // only add new arrays if i < N
413  X[i] = (double *)malloc(features * sizeof(double));
414  if (i < num_out) // only add new arrays if i < num_out
415  {
416  for (int k = 0; k < num_out; k++)
417  {
418 #ifdef _OPENMP
419 #pragma omp for
420 #endif
421  // preallocate with random initial weights
422  for (j = 0; j < features; j++)
423  {
424  double *w = data_3d(&W, i, k, j);
425  w[0] = _random(-5, 5);
426  }
427  }
428  }
429  }
430 
431  test_2d_classes(X, N); // create test data around circumference of a circle
432  save_2d_data("test1.csv", X, N, features); // save test data points
433  save_u_matrix("w11.csv", &W); // save initial random weights
434  kohonen_som(X, &W, N, features, num_out, 1e-4); // train the SOM
435  save_u_matrix("w12.csv", &W); // save the resultant weights
436 
437  for (int i = 0; i < N; i++) free(X[i]);
438  free(X);
439  free(W.data);
440 }
Here is the call graph for this function:

◆ test2()

void test2 ( )

Test that creates a random set of points distributed in 4 clusters in 3D space and trains an SOM that finds the topological pattern.

The following CSV files are created to validate the execution:

  • test2.csv: random test samples points
  • w21.csv: initial random U-matrix
  • w22.csv: trained SOM U-matrix
494 {
495  int j, N = 500;
496  int features = 3;
497  int num_out = 30; // image size - N x N
498 
499  // 3D space, hence size = number of rows * 3
500  double **X = (double **)malloc(N * sizeof(double *));
501 
502  // cluster nodex in 'x' * cluster nodes in 'y' * 2
503  struct array_3d W;
504  W.dim1 = num_out;
505  W.dim2 = num_out;
506  W.dim3 = features;
507  W.data = (double *)malloc(num_out * num_out * features *
508  sizeof(double)); // assign rows
509 
510  for (int i = 0; i < max(num_out, N); i++) // loop till max(N, num_out)
511  {
512  if (i < N) // only add new arrays if i < N
513  X[i] = (double *)malloc(features * sizeof(double));
514  if (i < num_out) // only add new arrays if i < num_out
515  {
516  for (int k = 0; k < num_out; k++)
517  {
518 #ifdef _OPENMP
519 #pragma omp for
520 #endif
521  for (j = 0; j < features; j++)
522  { // preallocate with random initial weights
523  double *w = data_3d(&W, i, k, j);
524  w[0] = _random(-5, 5);
525  }
526  }
527  }
528  }
529 
530  test_3d_classes1(X, N); // create test data
531  save_2d_data("test2.csv", X, N, features); // save test data points
532  save_u_matrix("w21.csv", &W); // save initial random weights
533  kohonen_som(X, &W, N, features, num_out, 1e-4); // train the SOM
534  save_u_matrix("w22.csv", &W); // save the resultant weights
535 
536  for (int i = 0; i < N; i++) free(X[i]);
537  free(X);
538  free(W.data);
539 }
Here is the call graph for this function:

◆ test3()

void test3 ( )

Test that creates a random set of points distributed in eight clusters in 3D space and trains an SOM that finds the topological pattern.

The following CSV files are created to validate the execution:

  • test3.csv: random test samples points
  • w31.csv: initial random U-matrix
  • w32.csv: trained SOM U-matrix
597 {
598  int j, N = 500;
599  int features = 3;
600  int num_out = 30;
601  double **X = (double **)malloc(N * sizeof(double *));
602 
603  // cluster nodex in 'x' * cluster nodes in 'y' * 2
604  struct array_3d W;
605  W.dim1 = num_out;
606  W.dim2 = num_out;
607  W.dim3 = features;
608  W.data = (double *)malloc(num_out * num_out * features *
609  sizeof(double)); // assign rows
610 
611  for (int i = 0; i < max(num_out, N); i++) // loop till max(N, num_out)
612  {
613  if (i < N) // only add new arrays if i < N
614  X[i] = (double *)malloc(features * sizeof(double));
615  if (i < num_out) // only add new arrays if i < num_out
616  {
617  for (int k = 0; k < num_out; k++)
618  {
619 #ifdef _OPENMP
620 #pragma omp for
621 #endif
622  // preallocate with random initial weights
623  for (j = 0; j < features; j++)
624  {
625  double *w = data_3d(&W, i, k, j);
626  w[0] = _random(-5, 5);
627  }
628  }
629  }
630  }
631 
632  test_3d_classes2(X, N); // create test data around the lamniscate
633  save_2d_data("test3.csv", X, N, features); // save test data points
634  save_u_matrix("w31.csv", &W); // save initial random weights
635  kohonen_som(X, &W, N, features, num_out, 0.01); // train the SOM
636  save_u_matrix("w32.csv", &W); // save the resultant weights
637 
638  for (int i = 0; i < N; i++) free(X[i]);
639  free(X);
640  free(W.data);
641 }
Here is the call graph for this function:

◆ test_2d_classes()

void test_2d_classes ( double *const *  data,
int  N 
)

Creates a random set of points distributed in four clusters in 3D space with centroids at the points.

  • \((0,5, 0.5, 0.5)\)
  • \((0,5,-0.5, -0.5)\)
  • \((-0,5, 0.5, 0.5)\)
  • \((-0,5,-0.5, -0.5)\)
Parameters
[out]datamatrix to store data in
[in]Nnumber of points required
354 {
355  const double R = 0.3; // radius of cluster
356  int i;
357  const int num_classes = 4;
358  const double centres[][2] = {
359  // centres of each class cluster
360  {.5, .5}, // centre of class 1
361  {.5, -.5}, // centre of class 2
362  {-.5, .5}, // centre of class 3
363  {-.5, -.5} // centre of class 4
364  };
365 
366 #ifdef _OPENMP
367 #pragma omp for
368 #endif
369  for (i = 0; i < N; i++)
370  {
371  int class =
372  rand() % num_classes; // select a random class for the point
373 
374  // create random coordinates (x,y,z) around the centre of the class
375  data[i][0] = _random(centres[class][0] - R, centres[class][0] + R);
376  data[i][1] = _random(centres[class][1] - R, centres[class][1] + R);
377 
378  /* The follosing can also be used
379  for (int j = 0; j < 2; j++)
380  data[i][j] = _random(centres[class][j] - R, centres[class][j] + R);
381  */
382  }
383 }
Here is the call graph for this function:

◆ test_3d_classes1()

void test_3d_classes1 ( double *const *  data,
int  N 
)

Creates a random set of points distributed in four clusters in 3D space with centroids at the points.

  • \((0,5, 0.5, 0.5)\)
  • \((0,5,-0.5, -0.5)\)
  • \((-0,5, 0.5, 0.5)\)
  • \((-0,5,-0.5, -0.5)\)
Parameters
[out]datamatrix to store data in
[in]Nnumber of points required
453 {
454  const double R = 0.2; // radius of cluster
455  int i;
456  const int num_classes = 4;
457  const double centres[][3] = {
458  // centres of each class cluster
459  {.5, .5, .5}, // centre of class 1
460  {.5, -.5, -.5}, // centre of class 2
461  {-.5, .5, .5}, // centre of class 3
462  {-.5, -.5 - .5} // centre of class 4
463  };
464 
465 #ifdef _OPENMP
466 #pragma omp for
467 #endif
468  for (i = 0; i < N; i++)
469  {
470  int class =
471  rand() % num_classes; // select a random class for the point
472 
473  // create random coordinates (x,y,z) around the centre of the class
474  data[i][0] = _random(centres[class][0] - R, centres[class][0] + R);
475  data[i][1] = _random(centres[class][1] - R, centres[class][1] + R);
476  data[i][2] = _random(centres[class][2] - R, centres[class][2] + R);
477 
478  /* The follosing can also be used
479  for (int j = 0; j < 3; j++)
480  data[i][j] = _random(centres[class][j] - R, centres[class][j] + R);
481  */
482  }
483 }
Here is the call graph for this function:

◆ test_3d_classes2()

void test_3d_classes2 ( double *const *  data,
int  N 
)

Creates a random set of points distributed in four clusters in 3D space with centroids at the points.

  • \((0,5, 0.5, 0.5)\)
  • \((0,5,-0.5, -0.5)\)
  • \((-0,5, 0.5, 0.5)\)
  • \((-0,5,-0.5, -0.5)\)
Parameters
[out]datamatrix to store data in
[in]Nnumber of points required
552 {
553  const double R = 0.2; // radius of cluster
554  int i;
555  const int num_classes = 8;
556  const double centres[][3] = {
557  // centres of each class cluster
558  {.5, .5, .5}, // centre of class 1
559  {.5, .5, -.5}, // centre of class 2
560  {.5, -.5, .5}, // centre of class 3
561  {.5, -.5, -.5}, // centre of class 4
562  {-.5, .5, .5}, // centre of class 5
563  {-.5, .5, -.5}, // centre of class 6
564  {-.5, -.5, .5}, // centre of class 7
565  {-.5, -.5, -.5} // centre of class 8
566  };
567 
568 #ifdef _OPENMP
569 #pragma omp for
570 #endif
571  for (i = 0; i < N; i++)
572  {
573  int class =
574  rand() % num_classes; // select a random class for the point
575 
576  // create random coordinates (x,y,z) around the centre of the class
577  data[i][0] = _random(centres[class][0] - R, centres[class][0] + R);
578  data[i][1] = _random(centres[class][1] - R, centres[class][1] + R);
579  data[i][2] = _random(centres[class][2] - R, centres[class][2] + R);
580 
581  /* The follosing can also be used
582  for (int j = 0; j < 3; j++)
583  data[i][j] = _random(centres[class][j] - R, centres[class][j] + R);
584  */
585  }
586 }
Here is the call graph for this function:

◆ update_weights()

double update_weights ( const double *  X,
struct array_3d W,
double **  D,
int  num_out,
int  num_features,
double  alpha,
int  R 
)

Update weights of the SOM using Kohonen algorithm.

Parameters
[in]Xdata point
[in,out]Wweights matrix
[in,out]Dtemporary vector to store distances
[in]num_outnumber of output points
[in]num_featuresnumber of features per input sample
[in]alphalearning rate \(0<\alpha\le1\)
[in]Rneighborhood range
Returns
minimum distance of sample and trained weights
229 {
230  int x, y, k;
231  double d_min = 0.f;
232 
233 #ifdef _OPENMP
234 #pragma omp for
235 #endif
236  // step 1: for each 2D output point
237  for (x = 0; x < num_out; x++)
238  {
239  for (y = 0; y < num_out; y++)
240  {
241  D[x][y] = 0.f;
242  // compute Euclidian distance of each output
243  // point from the current sample
244  for (k = 0; k < num_features; k++)
245  {
246  double *w = data_3d(W, x, y, k);
247  D[x][y] += (w[0] - X[k]) * (w[0] - X[k]);
248  }
249  D[x][y] = sqrt(D[x][y]);
250  }
251  }
252 
253  // step 2: get closest node i.e., node with smallest Euclidian distance to
254  // the current pattern
255  int d_min_x, d_min_y;
256  get_min_2d(D, num_out, &d_min, &d_min_x, &d_min_y);
257 
258  // step 3a: get the neighborhood range
259  int from_x = max(0, d_min_x - R);
260  int to_x = min(num_out, d_min_x + R + 1);
261  int from_y = max(0, d_min_y - R);
262  int to_y = min(num_out, d_min_y + R + 1);
263 
264  // step 3b: update the weights of nodes in the
265  // neighborhood
266 #ifdef _OPENMP
267 #pragma omp for
268 #endif
269  for (x = from_x; x < to_x; x++)
270  {
271  for (y = from_y; y < to_y; y++)
272  {
273  /* you can enable the following normalization if needed.
274  personally, I found it detrimental to convergence */
275  // const double s2pi = sqrt(2.f * M_PI);
276  // double normalize = 1.f / (alpha * s2pi);
277 
278  /* apply scaling inversely proportional to distance from the
279  current node */
280  double d2 =
281  (d_min_x - x) * (d_min_x - x) + (d_min_y - y) * (d_min_y - y);
282  double scale_factor = exp(-d2 / (2.f * alpha * alpha));
283 
284  for (k = 0; k < num_features; k++)
285  {
286  double *w = data_3d(W, x, y, k);
287  // update weights of nodes in the neighborhood
288  w[0] += alpha * scale_factor * (X[k] - w[0]);
289  }
290  }
291  }
292  return d_min;
293 }
Here is the call graph for this function:
min
#define min(a, b)
shorthand for minimum value
Definition: kohonen_som_topology.c:36
update_weights
double update_weights(const double *X, struct array_3d *W, double **D, int num_out, int num_features, double alpha, int R)
Update weights of the SOM using Kohonen algorithm.
Definition: kohonen_som_topology.c:227
array_3d::data
double * data
pointer to data
Definition: kohonen_som_topology.c:45
data
Definition: prime_factoriziation.c:25
data_3d
double * data_3d(const struct array_3d *arr, int x, int y, int z)
Function that returns the pointer to (x, y, z) ^th location in the linear 3D array given by:
Definition: kohonen_som_topology.c:60
test_3d_classes1
void test_3d_classes1(double *const *data, int N)
Creates a random set of points distributed in four clusters in 3D space with centroids at the points.
Definition: kohonen_som_topology.c:452
test_3d_classes2
void test_3d_classes2(double *const *data, int N)
Creates a random set of points distributed in four clusters in 3D space with centroids at the points.
Definition: kohonen_som_topology.c:551
N
#define N
number of digits of the large number
Definition: sol1.c:109
save_u_matrix
int save_u_matrix(const char *fname, struct array_3d *W)
Create the distance matrix or U-matrix from the trained weights and save to disk.
Definition: kohonen_som_topology.c:132
array_3d::dim3
int dim3
lengths of thirddimension
Definition: kohonen_som_topology.c:44
array_3d::dim1
int dim1
lengths of first dimension
Definition: kohonen_som_topology.c:42
get_min_2d
void get_min_2d(double **X, int N, double *val, int *x_idx, int *y_idx)
Get minimum value and index of the value in a matrix.
Definition: kohonen_som_topology.c:197
_random
double _random(double a, double b)
Helper function to generate a random number in a given interval.
Definition: kohonen_som_topology.c:80
array_3d
to store info regarding 3D arrays
Definition: kohonen_som_topology.c:41
save_2d_data
int save_2d_data(const char *fname, double **X, int num_points, int num_features)
Save a given n-dimensional data martix to file.
Definition: kohonen_som_topology.c:95
max
#define max(a, b)
shorthand for maximum value
Definition: kohonen_som_topology.c:32
array_3d::dim2
int dim2
lengths of second dimension
Definition: kohonen_som_topology.c:43
kohonen_som
void kohonen_som(double **X, struct array_3d *W, int num_samples, int num_features, int num_out, double alpha_min)
Apply incremental algorithm with updating neighborhood and learning rates on all samples in the given...
Definition: kohonen_som_topology.c:306
test_2d_classes
void test_2d_classes(double *const *data, int N)
Creates a random set of points distributed in four clusters in 3D space with centroids at the points.
Definition: kohonen_som_topology.c:353