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
261  {
262  int num_samples = X.size(); // number of rows
263  int num_features = X[0].size(); // number of columns
264  int num_out = W->size(); // output matrix size
265  int R = num_out >> 2, iter = 0;
266  double alpha = 1.f;
267 
269  for (int i = 0; i < num_out; i++) D[i] = std::valarray<double>(num_out);
270 
271  double dmin = 1.f; // average minimum distance of all samples
272  double past_dmin = 1.f; // average minimum distance of all samples
273  double dmin_ratio = 1.f; // change per step
274 
275  // Loop alpha from 1 to slpha_min
276  for (; alpha > 0 && dmin_ratio > 1e-5; alpha -= 1e-4, iter++) {
277  // Loop for each sample pattern in the data set
278  for (int sample = 0; sample < num_samples; sample++) {
279  // update weights for the current input pattern sample
280  dmin += update_weights(X[sample], W, &D, alpha, R);
281  }
282 
283  // every 100th iteration, reduce the neighborhood range
284  if (iter % 300 == 0 && R > 1)
285  R--;
286 
287  dmin /= num_samples;
288 
289  // termination condition variable -> % change in minimum distance
290  dmin_ratio = (past_dmin - dmin) / past_dmin;
291  if (dmin_ratio < 0)
292  dmin_ratio = 1.f;
293  past_dmin = dmin;
294 
295  std::cout << "iter: " << iter << "\t alpha: " << alpha << "\t R: " << R
296  << "\t d_min: " << dmin_ratio << "\r";
297  }
298 
299  std::cout << "\n";
300 }
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
134  {
135  std::ofstream fp(fname);
136  if (!fp) { // error with fopen
137  char msg[120];
138  std::snprintf(msg, sizeof(msg), "File error (%s): ", fname);
139  std::perror(msg);
140  return -1;
141  }
142 
143  // neighborhood range
144  unsigned int R = 1;
145 
146  for (int i = 0; i < W.size(); i++) { // for each x
147  for (int j = 0; j < W[0].size(); j++) { // for each y
148  double distance = 0.f;
149 
150  int from_x = std::max<int>(0, i - R);
151  int to_x = std::min<int>(W.size(), i + R + 1);
152  int from_y = std::max<int>(0, j - R);
153  int to_y = std::min<int>(W[0].size(), j + R + 1);
154  int l, m;
155 #ifdef _OPENMP
156 #pragma omp parallel for reduction(+ : distance)
157 #endif
158  for (l = from_x; l < to_x; l++) { // scan neighborhoor in x
159  for (m = from_y; m < to_y; m++) { // scan neighborhood in y
160  auto d = W[i][j] - W[l][m];
161  double d2 = std::pow(d, 2).sum();
162  distance += std::sqrt(d2);
163  // distance += d2;
164  }
165  }
166 
167  distance /= R * R; // mean distance from neighbors
168  fp << distance; // print the mean separation
169  if (j < W[0].size() - 1) { // if not the last column
170  fp << ','; // suffix comma
171  }
172  }
173  if (i < W.size() - 1) // if not the last row
174  fp << '\n'; // start a new line
175  }
176 
177  fp.close();
178  return 0;
179 }
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
194  {
195  int x, y;
196  int num_out_x = static_cast<int>(W->size()); // output nodes - in X
197  int num_out_y = static_cast<int>(W[0][0].size()); // output nodes - in Y
198  int num_features = static_cast<int>(W[0][0][0].size()); // features = in Z
199  double d_min = 0.f;
200 
201 #ifdef _OPENMP
202 #pragma omp for
203 #endif
204  // step 1: for each output point
205  for (x = 0; x < num_out_x; x++) {
206  for (y = 0; y < num_out_y; y++) {
207  (*D)[x][y] = 0.f;
208  // compute Euclidian distance of each output
209  // point from the current sample
210  auto d = ((*W)[x][y] - X);
211  (*D)[x][y] = (d * d).sum();
212  (*D)[x][y] = std::sqrt((*D)[x][y]);
213  }
214  }
215 
216  // step 2: get closest node i.e., node with snallest Euclidian distance
217  // to the current pattern
218  int d_min_x, d_min_y;
219  get_min_2d(*D, &d_min, &d_min_x, &d_min_y);
220 
221  // step 3a: get the neighborhood range
222  int from_x = std::max(0, d_min_x - R);
223  int to_x = std::min(num_out_x, d_min_x + R + 1);
224  int from_y = std::max(0, d_min_y - R);
225  int to_y = std::min(num_out_y, d_min_y + R + 1);
226 
227  // step 3b: update the weights of nodes in the
228  // neighborhood
229 #ifdef _OPENMP
230 #pragma omp for
231 #endif
232  for (x = from_x; x < to_x; x++) {
233  for (y = from_y; y < to_y; y++) {
234  /* you can enable the following normalization if needed.
235  personally, I found it detrimental to convergence */
236  // const double s2pi = sqrt(2.f * M_PI);
237  // double normalize = 1.f / (alpha * s2pi);
238 
239  /* apply scaling inversely proportional to distance from the
240  current node */
241  double d2 =
242  (d_min_x - x) * (d_min_x - x) + (d_min_y - y) * (d_min_y - y);
243  double scale_factor = std::exp(-d2 / (2.f * alpha * alpha));
244 
245  (*W)[x][y] += (X - (*W)[x][y]) * alpha * scale_factor;
246  }
247  }
248  return d_min;
249 }
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:191
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:97
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)