Algorithms_in_C++  1.0.0
Set of algorithms implemented in C++.
machine_learning Namespace Reference

Machine learning algorithms. More...

Classes

class  adaline
 

Functions

int save_u_matrix (const char *fname, const std::vector< std::vector< std::valarray< double >>> &W)
 
double update_weights (const std::valarray< double > &X, std::vector< std::vector< std::valarray< double >>> *W, std::vector< std::valarray< double >> *D, double alpha, int R)
 
void kohonen_som (const std::vector< std::valarray< double >> &X, std::vector< std::vector< std::valarray< double >>> *W, double alpha_min)
 
void update_weights (const std::valarray< double > &x, std::vector< std::valarray< double >> *W, std::valarray< double > *D, double alpha, int R)
 
void kohonen_som_tracer (const std::vector< std::valarray< double >> &X, std::vector< std::valarray< double >> *W, double alpha_min)
 

Detailed Description

Machine learning algorithms.

Function Documentation

◆ kohonen_som()

void machine_learning::kohonen_som ( const std::vector< std::valarray< double >> &  X,
std::vector< std::vector< std::valarray< double >>> *  W,
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]alpha_minterminal value of alpha
263  {
264  int num_samples = X.size(); // number of rows
265  int num_features = X[0].size(); // number of columns
266  int num_out = W->size(); // output matrix size
267  int R = num_out >> 2, iter = 0;
268  double alpha = 1.f;
269 
271  for (int i = 0; i < num_out; i++) D[i] = std::valarray<double>(num_out);
272 
273  double dmin = 1.f; // average minimum distance of all samples
274  double past_dmin = 1.f; // average minimum distance of all samples
275  double dmin_ratio = 1.f; // change per step
276 
277  // Loop alpha from 1 to slpha_min
278  for (; alpha > 0 && dmin_ratio > 1e-5; alpha -= 1e-4, iter++) {
279  // Loop for each sample pattern in the data set
280  for (int sample = 0; sample < num_samples; sample++) {
281  // update weights for the current input pattern sample
282  dmin += update_weights(X[sample], W, &D, alpha, R);
283  }
284 
285  // every 100th iteration, reduce the neighborhood range
286  if (iter % 300 == 0 && R > 1)
287  R--;
288 
289  dmin /= num_samples;
290 
291  // termination condition variable -> % change in minimum distance
292  dmin_ratio = (past_dmin - dmin) / past_dmin;
293  if (dmin_ratio < 0)
294  dmin_ratio = 1.f;
295  past_dmin = dmin;
296 
297  std::cout << "iter: " << iter << "\t alpha: " << alpha << "\t R: " << R
298  << "\t d_min: " << dmin_ratio << "\r";
299  }
300 
301  std::cout << "\n";
302 }
Here is the call graph for this function:

◆ kohonen_som_tracer()

void machine_learning::kohonen_som_tracer ( const std::vector< std::valarray< double >> &  X,
std::vector< std::valarray< double >> *  W,
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]alpha_minterminal value of alpha
147  {
148  int num_samples = X.size(); // number of rows
149  int num_features = X[0].size(); // number of columns
150  int num_out = W->size(); // number of rows
151  int R = num_out >> 2, iter = 0;
152  double alpha = 1.f;
153 
154  std::valarray<double> D(num_out);
155 
156  // Loop alpha from 1 to slpha_min
157  for (; alpha > alpha_min; alpha -= 0.01, iter++) {
158  // Loop for each sample pattern in the data set
159  for (int sample = 0; sample < num_samples; sample++) {
160  // update weights for the current input pattern sample
161  update_weights(X[sample], W, &D, alpha, R);
162  }
163 
164  // every 10th iteration, reduce the neighborhood range
165  if (iter % 10 == 0 && R > 1)
166  R--;
167  }
168 }
Here is the call graph for this function:

◆ save_u_matrix()

int machine_learning::save_u_matrix ( const char *  fname,
const std::vector< std::vector< std::valarray< double >>> &  W 
)

Create the distance matrix or U-matrix from the trained 3D weiths matrix 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
136  {
137  std::ofstream fp(fname);
138  if (!fp) { // error with fopen
139  char msg[120];
140  std::snprintf(msg, sizeof(msg), "File error (%s): ", fname);
141  std::perror(msg);
142  return -1;
143  }
144 
145  // neighborhood range
146  unsigned int R = 1;
147 
148  for (int i = 0; i < W.size(); i++) { // for each x
149  for (int j = 0; j < W[0].size(); j++) { // for each y
150  double distance = 0.f;
151 
152  int from_x = std::max<int>(0, i - R);
153  int to_x = std::min<int>(W.size(), i + R + 1);
154  int from_y = std::max<int>(0, j - R);
155  int to_y = std::min<int>(W[0].size(), j + R + 1);
156  int l, m;
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  for (m = from_y; m < to_y; m++) { // scan neighborhood in y
162  auto d = W[i][j] - W[l][m];
163  double d2 = std::pow(d, 2).sum();
164  distance += std::sqrt(d2);
165  // distance += d2;
166  }
167  }
168 
169  distance /= R * R; // mean distance from neighbors
170  fp << distance; // print the mean separation
171  if (j < W[0].size() - 1) { // if not the last column
172  fp << ','; // suffix comma
173  }
174  }
175  if (i < W.size() - 1) // if not the last row
176  fp << '\n'; // start a new line
177  }
178 
179  fp.close();
180  return 0;
181 }
Here is the call graph for this function:

◆ update_weights() [1/2]

void machine_learning::update_weights ( const std::valarray< double > &  x,
std::vector< std::valarray< double >> *  W,
std::valarray< double > *  D,
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]alphalearning rate \(0<\alpha\le1\)
[in]Rneighborhood range
102  {
103  int j, k;
104  int num_out = W->size(); // number of SOM output nodes
105  int num_features = x.size(); // number of data features
106 
107 #ifdef _OPENMP
108 #pragma omp for
109 #endif
110  // step 1: for each output point
111  for (j = 0; j < num_out; j++) {
112  // compute Euclidian distance of each output
113  // point from the current sample
114  (*D)[j] = (((*W)[j] - x) * ((*W)[j] - x)).sum();
115  }
116 
117  // step 2: get closest node i.e., node with snallest Euclidian distance to
118  // the current pattern
119  auto result = std::min_element(std::begin(*D), std::end(*D));
120  double d_min = *result;
121  int d_min_idx = std::distance(std::begin(*D), result);
122 
123  // step 3a: get the neighborhood range
124  int from_node = std::max(0, d_min_idx - R);
125  int to_node = std::min(num_out, d_min_idx + R + 1);
126 
127  // step 3b: update the weights of nodes in the
128  // neighborhood
129 #ifdef _OPENMP
130 #pragma omp for
131 #endif
132  for (j = from_node; j < to_node; j++)
133  // update weights of nodes in the neighborhood
134  (*W)[j] += alpha * (x - (*W)[j]);
135 }
Here is the call graph for this function:

◆ update_weights() [2/2]

double machine_learning::update_weights ( const std::valarray< double > &  X,
std::vector< std::vector< std::valarray< double >>> *  W,
std::vector< std::valarray< double >> *  D,
double  alpha,
int  R 
)

Update weights of the SOM using Kohonen algorithm

Parameters
[in]Xdata point - N features
[in,out]Wweights matrix - PxQxN
[in,out]Dtemporary vector to store distances PxQ
[in]alphalearning rate \(0<\alpha\le1\)
[in]Rneighborhood range
Returns
minimum distance of sample and trained weights
196  {
197  int x, y;
198  int num_out_x = static_cast<int>(W->size()); // output nodes - in X
199  int num_out_y = static_cast<int>(W[0][0].size()); // output nodes - in Y
200  int num_features = static_cast<int>(W[0][0][0].size()); // features = in Z
201  double d_min = 0.f;
202 
203 #ifdef _OPENMP
204 #pragma omp for
205 #endif
206  // step 1: for each output point
207  for (x = 0; x < num_out_x; x++) {
208  for (y = 0; y < num_out_y; y++) {
209  (*D)[x][y] = 0.f;
210  // compute Euclidian distance of each output
211  // point from the current sample
212  auto d = ((*W)[x][y] - X);
213  (*D)[x][y] = (d * d).sum();
214  (*D)[x][y] = std::sqrt((*D)[x][y]);
215  }
216  }
217 
218  // step 2: get closest node i.e., node with snallest Euclidian distance
219  // to the current pattern
220  int d_min_x, d_min_y;
221  get_min_2d(*D, &d_min, &d_min_x, &d_min_y);
222 
223  // step 3a: get the neighborhood range
224  int from_x = std::max(0, d_min_x - R);
225  int to_x = std::min(num_out_x, d_min_x + R + 1);
226  int from_y = std::max(0, d_min_y - R);
227  int to_y = std::min(num_out_y, d_min_y + R + 1);
228 
229  // step 3b: update the weights of nodes in the
230  // neighborhood
231 #ifdef _OPENMP
232 #pragma omp for
233 #endif
234  for (x = from_x; x < to_x; x++) {
235  for (y = from_y; y < to_y; y++) {
236  /* you can enable the following normalization if needed.
237  personally, I found it detrimental to convergence */
238  // const double s2pi = sqrt(2.f * M_PI);
239  // double normalize = 1.f / (alpha * s2pi);
240 
241  /* apply scaling inversely proportional to distance from the
242  current node */
243  double d2 =
244  (d_min_x - x) * (d_min_x - x) + (d_min_y - y) * (d_min_y - y);
245  double scale_factor = std::exp(-d2 / (2.f * alpha * alpha));
246 
247  (*W)[x][y] += (X - (*W)[x][y]) * alpha * scale_factor;
248  }
249  }
250  return d_min;
251 }
Here is the call graph for this function:
f
uint64_t f[MAX]
Definition: fibonacci_fast.cpp:27
machine_learning::update_weights
void update_weights(const std::valarray< double > &x, std::vector< std::valarray< double >> *W, std::valarray< double > *D, double alpha, int R)
Definition: kohonen_som_trace.cpp:100
std::vector
STL class.
std::vector::size
T size(T... args)
std::distance
T distance(T... args)
machine_learning::update_weights
double update_weights(const std::valarray< double > &X, std::vector< std::vector< std::valarray< double >>> *W, std::vector< std::valarray< double >> *D, double alpha, int R)
Definition: kohonen_som_topology.cpp:193
get_min_2d
void get_min_2d(const std::vector< std::valarray< double >> &X, double *val, int *x_idx, int *y_idx)
Definition: kohonen_som_topology.cpp:99
std::sqrt
T sqrt(T... args)
std::snprintf
T snprintf(T... args)
std::cout
std::ofstream
STL class.
k
ll k
Definition: matrix_exponentiation.cpp:48
std::min_element
T min_element(T... args)
std::perror
T perror(T... args)
std::valarray
STL class.
std::min
T min(T... args)
std::exp
T exp(T... args)
std::begin
T begin(T... args)
std::end
T end(T... args)
std::max
T max(T... args)
std::pow
T pow(T... args)