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)
 

Variables

constexpr double MIN_DISTANCE = 1e-4
 

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
271  {
272  size_t num_samples = X.size(); // number of rows
273  // size_t num_features = X[0].size(); // number of columns
274  size_t num_out = W->size(); // output matrix size
275  size_t R = num_out >> 2, iter = 0;
276  double alpha = 1.f;
277 
279  for (int i = 0; i < num_out; i++) D[i] = std::valarray<double>(num_out);
280 
281  double dmin = 1.f; // average minimum distance of all samples
282  double past_dmin = 1.f; // average minimum distance of all samples
283  double dmin_ratio = 1.f; // change per step
284 
285  // Loop alpha from 1 to slpha_min
286  for (; alpha > 0 && dmin_ratio > 1e-5; alpha -= 1e-4, iter++) {
287  // Loop for each sample pattern in the data set
288  for (int sample = 0; sample < num_samples; sample++) {
289  // update weights for the current input pattern sample
290  dmin += update_weights(X[sample], W, &D, alpha, R);
291  }
292 
293  // every 100th iteration, reduce the neighborhood range
294  if (iter % 300 == 0 && R > 1) {
295  R--;
296  }
297 
298  dmin /= num_samples;
299 
300  // termination condition variable -> % change in minimum distance
301  dmin_ratio = (past_dmin - dmin) / past_dmin;
302  if (dmin_ratio < 0) {
303  dmin_ratio = 1.f;
304  }
305  past_dmin = dmin;
306 
307  std::cout << "iter: " << iter << "\t alpha: " << alpha << "\t R: " << R
308  << "\t d_min: " << dmin_ratio << "\r";
309  }
310 
311  std::cout << "\n";
312 }
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
151  {
152  int num_samples = X.size(); // number of rows
153  // int num_features = X[0].size(); // number of columns
154  int num_out = W->size(); // number of rows
155  int R = num_out >> 2, iter = 0;
156  double alpha = 1.f;
157 
158  std::valarray<double> D(num_out);
159 
160  // Loop alpha from 1 to slpha_min
161  do {
162  // Loop for each sample pattern in the data set
163  for (int sample = 0; sample < num_samples; sample++) {
164  // update weights for the current input pattern sample
165  update_weights(X[sample], W, &D, alpha, R);
166  }
167 
168  // every 10th iteration, reduce the neighborhood range
169  if (iter % 10 == 0 && R > 1) {
170  R--;
171  }
172 
173  alpha -= 0.01;
174  iter++;
175  } while (alpha > alpha_min);
176 }
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
143  {
144  std::ofstream fp(fname);
145  if (!fp) { // error with fopen
146  std::cerr << "File error (" << fname << "): " << std::strerror(errno)
147  << std::endl;
148  return -1;
149  }
150 
151  // neighborhood range
152  unsigned int R = 1;
153 
154  for (int i = 0; i < W.size(); i++) { // for each x
155  for (int j = 0; j < W[0].size(); j++) { // for each y
156  double distance = 0.f;
157 
158  int from_x = std::max<int>(0, i - R);
159  int to_x = std::min<int>(W.size(), i + R + 1);
160  int from_y = std::max<int>(0, j - R);
161  int to_y = std::min<int>(W[0].size(), j + R + 1);
162  int l = 0, m = 0;
163 #ifdef _OPENMP
164 #pragma omp parallel for reduction(+ : distance)
165 #endif
166  for (l = from_x; l < to_x; l++) { // scan neighborhoor in x
167  for (m = from_y; m < to_y; m++) { // scan neighborhood in y
168  auto d = W[i][j] - W[l][m];
169  double d2 = std::pow(d, 2).sum();
170  distance += std::sqrt(d2);
171  // distance += d2;
172  }
173  }
174 
175  distance /= R * R; // mean distance from neighbors
176  fp << distance; // print the mean separation
177  if (j < W[0].size() - 1) { // if not the last column
178  fp << ','; // suffix comma
179  }
180  }
181  if (i < W.size() - 1) { // if not the last row
182  fp << '\n'; // start a new line
183  }
184  }
185 
186  fp.close();
187  return 0;
188 }
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
105  {
106  int j = 0, k = 0;
107  int num_out = W->size(); // number of SOM output nodes
108  // int num_features = x.size(); // number of data features
109 
110 #ifdef _OPENMP
111 #pragma omp for
112 #endif
113  // step 1: for each output point
114  for (j = 0; j < num_out; j++) {
115  // compute Euclidian distance of each output
116  // point from the current sample
117  (*D)[j] = (((*W)[j] - x) * ((*W)[j] - x)).sum();
118  }
119 
120  // step 2: get closest node i.e., node with snallest Euclidian distance to
121  // the current pattern
122  auto result = std::min_element(std::begin(*D), std::end(*D));
123  // double d_min = *result;
124  int d_min_idx = std::distance(std::begin(*D), result);
125 
126  // step 3a: get the neighborhood range
127  int from_node = std::max(0, d_min_idx - R);
128  int to_node = std::min(num_out, d_min_idx + R + 1);
129 
130  // step 3b: update the weights of nodes in the
131  // neighborhood
132 #ifdef _OPENMP
133 #pragma omp for
134 #endif
135  for (j = from_node; j < to_node; j++) {
136  // update weights of nodes in the neighborhood
137  (*W)[j] += alpha * (x - (*W)[j]);
138  }
139 }
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
203  {
204  int x = 0, y = 0;
205  int num_out_x = static_cast<int>(W->size()); // output nodes - in X
206  int num_out_y = static_cast<int>(W[0][0].size()); // output nodes - in Y
207  // int num_features = static_cast<int>(W[0][0][0].size()); // features =
208  // in Z
209  double d_min = 0.f;
210 
211 #ifdef _OPENMP
212 #pragma omp for
213 #endif
214  // step 1: for each output point
215  for (x = 0; x < num_out_x; x++) {
216  for (y = 0; y < num_out_y; y++) {
217  (*D)[x][y] = 0.f;
218  // compute Euclidian distance of each output
219  // point from the current sample
220  auto d = ((*W)[x][y] - X);
221  (*D)[x][y] = (d * d).sum();
222  (*D)[x][y] = std::sqrt((*D)[x][y]);
223  }
224  }
225 
226  // step 2: get closest node i.e., node with snallest Euclidian distance
227  // to the current pattern
228  int d_min_x = 0, d_min_y = 0;
229  get_min_2d(*D, &d_min, &d_min_x, &d_min_y);
230 
231  // step 3a: get the neighborhood range
232  int from_x = std::max(0, d_min_x - R);
233  int to_x = std::min(num_out_x, d_min_x + R + 1);
234  int from_y = std::max(0, d_min_y - R);
235  int to_y = std::min(num_out_y, d_min_y + R + 1);
236 
237  // step 3b: update the weights of nodes in the
238  // neighborhood
239 #ifdef _OPENMP
240 #pragma omp for
241 #endif
242  for (x = from_x; x < to_x; x++) {
243  for (y = from_y; y < to_y; y++) {
244  /* you can enable the following normalization if needed.
245  personally, I found it detrimental to convergence */
246  // const double s2pi = sqrt(2.f * M_PI);
247  // double normalize = 1.f / (alpha * s2pi);
248 
249  /* apply scaling inversely proportional to distance from the
250  current node */
251  double d2 =
252  (d_min_x - x) * (d_min_x - x) + (d_min_y - y) * (d_min_y - y);
253  double scale_factor = std::exp(-d2 / (2.f * alpha * alpha));
254 
255  (*W)[x][y] += (X - (*W)[x][y]) * alpha * scale_factor;
256  }
257  }
258  return d_min;
259 }
Here is the call graph for this function:

Variable Documentation

◆ MIN_DISTANCE

constexpr double machine_learning::MIN_DISTANCE = 1e-4
constexpr

Minimum average distance of image nodes

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:103
std::vector
STL class.
std::vector::size
T size(T... args)
std::distance
T distance(T... args)
std::strerror
T strerror(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:200
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:105
std::sqrt
T sqrt(T... args)
std::cout
std::ofstream
STL class.
std::min_element
T min_element(T... args)
std::valarray
STL class.
std::min
T min(T... args)
std::endl
T endl(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)