openGPMP
Open Source Mathematics Package
mlp_net.hpp
Go to the documentation of this file.
1 /*************************************************************************
2  *
3  * Project
4  * _____ _____ __ __ _____
5  * / ____| __ \| \/ | __ \
6  * ___ _ __ ___ _ __ | | __| |__) | \ / | |__) |
7  * / _ \| '_ \ / _ \ '_ \| | |_ | ___/| |\/| | ___/
8  *| (_) | |_) | __/ | | | |__| | | | | | | |
9  * \___/| .__/ \___|_| |_|\_____|_| |_| |_|_|
10  * | |
11  * |_|
12  *
13  * Copyright (C) Akiel Aries, <akiel@akiel.org>, et al.
14  *
15  * This software is licensed as described in the file LICENSE, which
16  * you should have received as part of this distribution. The terms
17  * among other details are referenced in the official documentation
18  * seen here : https://akielaries.github.io/openGPMP/ along with
19  * important files seen in this project.
20  *
21  * You may opt to use, copy, modify, merge, publish, distribute
22  * and/or sell copies of the Software, and permit persons to whom
23  * the Software is furnished to do so, under the terms of the
24  * LICENSE file. As this is an Open Source effort, all implementations
25  * must be of the same methodology.
26  *
27  *
28  *
29  * This software is distributed on an AS IS basis, WITHOUT
30  * WARRANTY OF ANY KIND, either express or implied.
31  *
32  ************************************************************************/
33 
40 #ifndef MLP_NETWORK_HPP
41 #define MLP_NETWORK_HPP
42 #include "../linalg.hpp"
43 #include "../linalg/mtx_tmpl.hpp"
44 
45 #include <cassert>
46 #include <fstream>
47 #include <random>
48 #include <stdio.h>
49 #include <utility>
50 #include <vector>
51 
52 namespace gpmp {
53 
57 namespace ml {
58 
59 /*
60  * TODO
61  * Think of using extended or derived classes
62  *
63  * Weights : MLP
64  *
65  */
66 struct neuron {
67  // exit
68  long double sortir;
69  // error
70  long double err;
71  // weight
72  long double *wt;
73  // last weight
74  long double *wt_last;
75  // saved weight
76  long double *wt_saved;
77 };
78 
79 struct layer {
80  int64_t num_neurons;
82 };
83 
87 class PrimaryMLP {
88  /* initialize random values for the network */
89  void rand_init();
90  /* check that random is an integer */
91  int64_t rand_int(int64_t low, int64_t hi);
92  /*check random is a real number */
93  long double rand_real(long double low, long double hi);
94  /*return the number of layers in the network */
95  int64_t num_layers;
100  long double _MSE;
104  long double _MAE;
105 
106  void set_signal_in(long double *input);
107  void get_signal_out(long double *output);
108 
109  void weights_save();
110  void weights_rand();
112  /*adjust weights */
114 
115  /* propogate given the signal */
116  void prop_signal();
117  /* returns the computed output error */
118  void output_err(long double *target);
119  /* returns the computed error from backwards propogation */
121  /* simulate the Multi-Layer Perceptron Neual Network */
122  void simulate(long double *input,
123  long double *output,
124  long double *target,
125  bool training);
126 
127  public:
128  long double _Eta;
129  long double _Alpha;
130  long double _Gain;
131  long double _AvgTestError;
132 
133  /* CONSTRUCT */
134  PrimaryMLP(int64_t nl, int64_t npl[]);
135  /* DECONSTRUCT */
136  ~PrimaryMLP();
137 
138  /* method to train the network given data*/
139  int64_t train(const char *fnames);
140  /* method to test given data*/
141  int64_t test(const char *fname);
142  int64_t evaluate();
143 
144  void run(const char *fname, const int64_t &max_iters);
145 };
146 
151 template <typename T> class SecondaryMLP {
152  public:
156  void log(auto &file, const auto &x, const auto &y, const auto &y_hat) {
157  // mean squared error
158  auto mse = (y.data[0] - y_hat.data[0]);
159  mse = mse * mse;
160  file << mse << " " << x.data[0] << " " << y.data[0] << " "
161  << y_hat.data[0] << " \n";
162  }
163 
169  inline long double sigmoid_activ(long double x) {
170  return 1.0f / (1 + exp(-x));
171  }
172 
178  inline long double sigmoid_deriv(long double x) {
179  return (x * (1 - x));
180  }
181 
182  std::vector<size_t> layer_units;
183  std::vector<gpmp::linalg::Matrix<T>> bias_vectors;
184  std::vector<gpmp::linalg::Matrix<T>> wt_mtx;
185  std::vector<gpmp::linalg::Matrix<T>> activations;
186 
187  long double lr;
188 
194  explicit SecondaryMLP(std::vector<size_t> _layer_units,
195  long double _lr = .001)
196  : layer_units(_layer_units), wt_mtx(), bias_vectors(), lr(_lr) {
197  // traverse the elements
198  for (size_t i = 0; i < layer_units.size() - 1; ++i) {
199  // size of inputs
200  size_t inputs{layer_units[i]};
201  // size of outputs
202  size_t outputs{layer_units[i + 1]};
203 
204  // set to random Guassian Noise related values
205  // weights
206  auto gauss_wt = gpmp::linalg::mtx<T>::randn(outputs, inputs);
207  wt_mtx.push_back(gauss_wt);
208  // biases
209  auto bias_wt = gpmp::linalg::mtx<T>::randn(outputs, 1);
210  bias_vectors.push_back(bias_wt);
211  // activation function
212  activations.resize(layer_units.size());
213  }
214  }
222  assert(std::get<0>(x.shape) == layer_units[0] && std::get<1>(x.shape));
223  // input = to previously declared acitvations method
224  activations[0] = x;
225  gpmp::linalg::Matrix prev(x);
226 
227  // traverse layer units
228  for (uint64_t i = 0; i < layer_units.size() - 1; ++i) {
229  gpmp::linalg::Matrix y = wt_mtx[i].mult(prev);
230  y = y + bias_vectors[i];
231  y = y.apply_function(&SecondaryMLP::sigmoid_activ);
232  activations[i + 1] = y;
233  prev = y;
234  }
235  return prev;
236  }
246  assert(std::get<0>(target.shape) == layer_units.back());
247  // calculate the error, target - ouput
248  auto y = target;
249  auto y_hat = activations.back();
250  auto err = target - y_hat;
251  // back propagate the error calculated from output to input
252  // and step the weights
253  for (int64_t i = wt_mtx.size() - 1; i >= 0; --i) {
254  // calculate errors for previous layer
255  auto wt = wt_mtx[i].T();
256  auto prior_errs = wt.mult(err);
257  auto outputs_d =
258  activations[i + 1].apply_function(&SecondaryMLP::sigmoid_deriv);
259  auto gradients = err.hadamard(outputs_d);
260  gradients = gradients.scalar_mult(lr);
261  auto trans_a = activations[i].T();
262  auto gradients_wt = gradients.mult(trans_a);
263 
264  // adjust the networks weights based on propagation
265  // technique
266  bias_vectors[i] = bias_vectors[i].add(gradients);
267  wt_mtx[i] = wt_mtx[i].add(gradients_wt);
268  err = prior_errs;
269  }
270  }
271 };
272 
273 } // namespace ml
274 
275 } // namespace gpmp
276 
277 #endif
Matrix and Scalar operations.
Definition: mtx_tmpl.hpp:61
Primary Multi-Layer Perceptron Class.
Definition: mlp_net.hpp:87
PrimaryMLP(int64_t nl, int64_t npl[])
Definition: mlp_network.cpp:64
long double _MSE
Mean Squared Error.
Definition: mlp_net.hpp:100
void output_err(long double *target)
void run(const char *fname, const int64_t &max_iters)
long double _Gain
Definition: mlp_net.hpp:130
long double _AvgTestError
Definition: mlp_net.hpp:131
long double rand_real(long double low, long double hi)
Definition: mlp_network.cpp:59
int64_t rand_int(int64_t low, int64_t hi)
Definition: mlp_network.cpp:54
long double _Eta
Definition: mlp_net.hpp:128
void get_signal_out(long double *output)
long double _Alpha
Definition: mlp_net.hpp:129
int64_t test(const char *fname)
void simulate(long double *input, long double *output, long double *target, bool training)
void set_signal_in(long double *input)
int64_t train(const char *fnames)
long double _MAE
Mean Absolute Error.
Definition: mlp_net.hpp:104
Secondary Multi-Layer Perceptron Class making use of the Linear Algebra module.
Definition: mlp_net.hpp:151
void prop_backwards(gpmp::linalg::Matrix< T > target)
Definition: mlp_net.hpp:245
std::vector< gpmp::linalg::Matrix< T > > bias_vectors
Definition: mlp_net.hpp:183
std::vector< gpmp::linalg::Matrix< T > > wt_mtx
Definition: mlp_net.hpp:184
void log(auto &file, const auto &x, const auto &y, const auto &y_hat)
Definition: mlp_net.hpp:156
std::vector< gpmp::linalg::Matrix< T > > activations
Definition: mlp_net.hpp:185
SecondaryMLP(std::vector< size_t > _layer_units, long double _lr=.001)
Definition: mlp_net.hpp:194
long double sigmoid_activ(long double x)
Sigmoid activation function.
Definition: mlp_net.hpp:169
long double sigmoid_deriv(long double x)
Sigmoid Derivative for backwards propogation.
Definition: mlp_net.hpp:178
auto prop_forwards(gpmp::linalg::Matrix< T > x)
Definition: mlp_net.hpp:221
std::vector< size_t > layer_units
Definition: mlp_net.hpp:182
The source C++ openGPMP namespace.
static Matrix< T > randn(size_t rows, size_t cols)
Definition: mtx_tmpl.hpp:425
int64_t num_neurons
Definition: mlp_net.hpp:80
neuron * neuron_ptr
Definition: mlp_net.hpp:81
long double err
Definition: mlp_net.hpp:70
long double * wt_saved
Definition: mlp_net.hpp:76
long double * wt
Definition: mlp_net.hpp:72
long double sortir
Definition: mlp_net.hpp:68
long double * wt_last
Definition: mlp_net.hpp:74