Kohonen self organizing map (data tracing)
More...
#include <algorithm>
#include <array>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <fstream>
#include <iostream>
#include <valarray>
#include <vector>
|
double | _random (double a, double b) |
|
int | save_nd_data (const char *fname, const std::vector< std::valarray< double > > &X) |
|
void | machine_learning::update_weights (const std::valarray< double > &x, std::vector< std::valarray< double > > *W, std::valarray< double > *D, double alpha, int R) |
|
void | machine_learning::kohonen_som_tracer (const std::vector< std::valarray< double > > &X, std::vector< std::valarray< double > > *W, double alpha_min) |
|
void | test_circle (std::vector< std::valarray< double > > *data) |
|
void | test1 () |
|
void | test_lamniscate (std::vector< std::valarray< double > > *data) |
|
void | test2 () |
|
void | test_3d_classes (std::vector< std::valarray< double > > *data) |
|
void | test3 () |
|
double | get_clock_diff (clock_t start_t, clock_t end_t) |
|
int | main (int argc, char **argv) |
|
Kohonen self organizing map (data tracing)
This example implements a powerful self organizing map algorithm. The algorithm creates a connected network of weights that closely follows the given data points. This this creates a chain of nodes that resembles the given input shape.
- Author
- Krishna Vedala
- Note
- This C++ version of the program is considerable slower than its C counterpart
-
The compiled code is much slower when compiled with MS Visual C++ 2019 than with GCC on windows
- See also
- kohonen_som_topology.cpp
◆ 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_t | start clock |
[in] | end_t | end clock |
- Returns
- time difference in seconds
452 {
453 return static_cast<double>(end_t - start_t) / CLOCKS_PER_SEC;
454}
◆ main()
int main |
( |
int | argc, |
|
|
char ** | argv ) |
Main function
457 {
458#ifdef _OPENMP
459 std::cout <<
"Using OpenMP based parallelization\n";
460#else
461 std::cout <<
"NOT using OpenMP based parallelization\n";
462#endif
463
465
470 << " sec\n";
471
476 << " sec\n";
477
482 << " sec\n";
483
485 << "(Note: Calculated times include: creating test sets, training "
486 "model and writing files to disk.)\n\n";
487 return 0;
488}
void test2()
Definition kohonen_som_trace.cpp:315
void test1()
Definition kohonen_som_trace.cpp:233
double get_clock_diff(clock_t start_t, clock_t end_t)
Definition kohonen_som_trace.cpp:452
void test3()
Definition kohonen_som_trace.cpp:414
◆ test1()
Test that creates a random set of points distributed near the circumference of a circle and trains an SOM that finds that circular 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 map
w12.csv
: trained SOM map
The outputs can be readily plotted in gnuplot using the following snippet
set datafile separator ','
plot "test1.csv" title "original", \
"w11.csv" title "w1", \
"w12.csv" title "w2"
233 {
235 int features = 2;
236 int num_out = 50;
239 for (
int i = 0; i <
std::max(num_out, N); i++) {
240
241 if (i < N) {
243 }
244 if (i < num_out) {
246
247#ifdef _OPENMP
248#pragma omp for
249#endif
250 for (j = 0; j < features; j++) {
251
253 }
254 }
255 }
256
260 kohonen_som_tracer(X, &W, 0.1);
262}
constexpr uint32_t N
A struct to represent sparse table for min() as their invariant function, for the given array A....
Definition sparse_table.cpp:47
int save_nd_data(const char *fname, const std::vector< std::valarray< double > > &X)
Definition kohonen_som_trace.cpp:58
double _random(double a, double b)
Definition kohonen_som_topology.cpp:53
void test_circle(std::vector< std::valarray< double > > *data)
Definition kohonen_som_trace.cpp:196
◆ test2()
Test that creates a random set of points distributed near the locus of the Lamniscate of Gerono and trains an SOM that finds that circular pattern. The following CSV files are created to validate the execution:
test2.csv
: random test samples points with a lamniscate pattern
w21.csv
: initial random map
w22.csv
: trained SOM map
The outputs can be readily plotted in gnuplot using the following snippet
set datafile separator ','
plot "test2.csv" title "original", \
"w21.csv" title "w1", \
"w22.csv" title "w2"
315 {
317 int features = 2;
318 int num_out = 20;
321 for (
int i = 0; i <
std::max(num_out, N); i++) {
322
323 if (i < N) {
325 }
326 if (i < num_out) {
328
329#ifdef _OPENMP
330#pragma omp for
331#endif
332 for (j = 0; j < features; j++) {
333
335 }
336 }
337 }
338
342 kohonen_som_tracer(X, &W, 0.01);
344}
void test_lamniscate(std::vector< std::valarray< double > > *data)
Definition kohonen_som_trace.cpp:277
◆ test3()
Test that creates a random set of points distributed in six clusters in 3D space. The following CSV files are created to validate the execution:
test3.csv
: random test samples points with a circular pattern
w31.csv
: initial random map
w32.csv
: trained SOM map
The outputs can be readily plotted in gnuplot using the following snippet
set datafile separator ','
plot "test3.csv" title "original", \
"w31.csv" title "w1", \
"w32.csv" title "w2"
414 {
416 int features = 3;
417 int num_out = 20;
420 for (
int i = 0; i <
std::max(num_out, N); i++) {
421
422 if (i < N) {
424 }
425 if (i < num_out) {
427
428#ifdef _OPENMP
429#pragma omp for
430#endif
431 for (j = 0; j < features; j++) {
432
434 }
435 }
436 }
437
441 kohonen_som_tracer(X, &W, 0.01);
443}
void test_3d_classes(std::vector< std::valarray< double > > *data)
Definition kohonen_som_trace.cpp:359
◆ test_3d_classes()
Creates a random set of points distributed in six 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}\)
- \({-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] | data | matrix to store data in |
359 {
360 const int N =
data->size();
361 const double R = 0.1;
362 int i = 0;
363 const int num_classes = 8;
365
374 };
375
376#ifdef _OPENMP
377#pragma omp for
378#endif
379 for (i = 0; i <
N; i++) {
380 int cls =
382
383
384 data[0][i][0] =
_random(centres[cls][0] - R, centres[cls][0] + R);
385 data[0][i][1] =
_random(centres[cls][1] - R, centres[cls][1] + R);
386 data[0][i][2] =
_random(centres[cls][2] - R, centres[cls][2] + R);
387
388
389
390
391
392 }
393}
int data[MAX]
test data
Definition hash_search.cpp:24
◆ test_circle()
Creates a random set of points distributed near the circumference of a circle and trains an SOM that finds that circular pattern. The generating function is
\begin{eqnarray*}
r &\in& [1-\delta r, 1+\delta r)\\
\theta &\in& [0, 2\pi)\\
x &=& r\cos\theta\\
y &=& r\sin\theta
\end{eqnarray*}
- Parameters
-
[out] | data | matrix to store data in |
196 {
197 const int N =
data->size();
198 const double R = 0.75, dr = 0.3;
199 double a_t = 0., b_t = 2.f * M_PI;
200 double a_r = R - dr, b_r = R + dr;
201 int i = 0;
202
203#ifdef _OPENMP
204#pragma omp for
205#endif
206 for (i = 0; i <
N; i++) {
208 double theta =
_random(a_t, b_t);
209 data[0][i][0] = r *
cos(theta);
210 data[0][i][1] = r *
sin(theta);
211 }
212}
◆ test_lamniscate()
Creates a random set of points distributed near the locus of the Lamniscate of Gerono.
\begin{eqnarray*}
\delta r &=& 0.2\\
\delta x &\in& [-\delta r, \delta r)\\
\delta y &\in& [-\delta r, \delta r)\\
\theta &\in& [0, \pi)\\
x &=& \delta x + \cos\theta\\
y &=& \delta y + \frac{\sin(2\theta)}{2}
\end{eqnarray*}
- Parameters
-
[out] | data | matrix to store data in |
277 {
278 const int N =
data->size();
279 const double dr = 0.2;
280 int i = 0;
281
282#ifdef _OPENMP
283#pragma omp for
284#endif
285 for (i = 0; i <
N; i++) {
288 double theta =
_random(0, M_PI);
289 data[0][i][0] = dx +
cos(theta);
290 data[0][i][1] = dy +
sin(2. * theta) / 2.f;
291 }
292}