SNABSuite  0.x
Spiking Neural Architecture Benchmark Suite
Public Member Functions | Static Public Member Functions | Protected Member Functions | Protected Attributes | List of all members
MNIST::MLP< Loss, ActivationFunction, Constraint > Class Template Reference

The standard densely connected multilayer Perceptron. Template arguments provide the loss function, the activation function of neurons (experimental) and a possible constraint for the weights. More...

#include <mnist_mlp.hpp>

Inheritance diagram for MNIST::MLP< Loss, ActivationFunction, Constraint >:
MNIST::MLPBase

Public Member Functions

 MLP (std::vector< size_t > layer_sizes, size_t epochs=20, size_t batchsize=100, Real learn_rate=0.01)
 Constructor for random init. More...
 
 MLP (Json &data, size_t epochs=20, size_t batchsize=100, Real learn_rate=0.01, bool random=false, Constraint constraint=Constraint())
 Constructs the network from json file. The repo provides python scripts to create those from a keras network. More...
 
Real max_weight () const override
 Return the largest weight in the network. More...
 
Real conv_max_weight (size_t layer_id) const override
 
Real min_weight () const override
 Return the smallest weight in the network. More...
 
Real max_weight_abs () const override
 Return the largest absolute weight in the network. More...
 
const size_t & epochs () const override
 
const size_t & batchsize () const override
 
const Real & learnrate () const override
 
const mnist_helper::MNIST_DATAmnist_train_set () override
 Returns reference to the train data. More...
 
const mnist_helper::MNIST_DATAmnist_test_set () override
 Returns reference to the test data. More...
 
const std::vector< cypress::Matrix< Real > > & get_weights () override
 Return all weights in the form of weights[layer](src,tar) More...
 
const std::vector< mnist_helper::CONVOLUTION_LAYER > & get_conv_layers () override
 Return all filter weights in the form of weights[x][y][depth][filter]. More...
 
const std::vector< mnist_helper::POOLING_LAYER > & get_pooling_layers () override
 
const std::vector< size_t > & get_layer_sizes () override
 Return the number of neurons per layer. More...
 
const std::vector< mnist_helper::LAYER_TYPE > & get_layer_types () override
 
void scale_down_images (size_t pooling_size=3) override
 Scale down the whole data set, reduces the image by a given factor in every dimension. More...
 
bool correct (const uint16_t label, const std::vector< Real > &output) const override
 Checks if the output of the network was correct. More...
 
virtual std::vector< std::vector< std::vector< Real > > > forward_path (const std::vector< size_t > &indices, const size_t start) const override
 Forward path of the network (–> inference) More...
 
virtual Real forward_path_test () const override
 Forward path of test data. More...
 
virtual void backward_path (const std::vector< size_t > &indices, const size_t start, const std::vector< std::vector< std::vector< Real >>> &activations, bool last_only=false) override
 implementation of backprop More...
 
virtual void backward_path_2 (const std::vector< uint16_t > &labels, const std::vector< std::vector< std::vector< Real >>> &activations, bool last_only=false) override
 Implementation of backprop, adapted for usage in SNNs. More...
 
size_t accuracy (const std::vector< std::vector< std::vector< Real >>> &activations, const std::vector< size_t > &indices, const size_t start) override
 Calculate the overall accuracy from the given neural network output. More...
 
void train (unsigned seed=0) override
 Starts the full training process. More...
 

Static Public Member Functions

static std::vector< Real > mat_X_vec (const Matrix< Real > &mat, const std::vector< Real > &vec)
 Implements matrix vector multiplication. More...
 
static std::vector< Real > mat_trans_X_vec (const Matrix< Real > &mat, const std::vector< Real > &vec)
 Implements transposed matrix vector multiplication. More...
 
static std::vector< Real > vec_X_vec_comp (const std::vector< Real > &vec1, const std::vector< Real > &vec2)
 Vector vector multiplication, component-wise. More...
 
static void update_mat (Matrix< Real > &mat, const std::vector< Real > &errors, const std::vector< Real > &pre_output, const size_t sample_num, const Real learn_rate)
 Updates the weight matrix based on the error in this layer and the output of the previous layer. More...
 

Protected Member Functions

void load_data (std::string path)
 

Protected Attributes

std::vector< cypress::Matrix< Real > > m_layers
 
std::vector< size_t > m_layer_sizes
 
std::vector< mnist_helper::CONVOLUTION_LAYERm_filters
 
std::vector< mnist_helper::POOLING_LAYERm_pools
 
std::vector< mnist_helper::LAYER_TYPEm_layer_types
 
size_t m_epochs = 20
 
size_t m_batchsize = 100
 
Real learn_rate = 0.01
 
mnist_helper::MNIST_DATA m_mnist
 
mnist_helper::MNIST_DATA m_mnist_test
 
Constraint m_constraint
 

Detailed Description

template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
class MNIST::MLP< Loss, ActivationFunction, Constraint >

The standard densely connected multilayer Perceptron. Template arguments provide the loss function, the activation function of neurons (experimental) and a possible constraint for the weights.

Definition at line 241 of file mnist_mlp.hpp.

Constructor & Destructor Documentation

template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
MNIST::MLP< Loss, ActivationFunction, Constraint >::MLP ( std::vector< size_t >  layer_sizes,
size_t  epochs = 20,
size_t  batchsize = 100,
Real  learn_rate = 0.01 
)
inline

Constructor for random init.

Parameters
layer_sizeslist of #neurons beginning with input and ending with output layer
epochsnumber of epochs to train
batchsizemini batchsize before updating the weights
learn_rategradients are multiplied with this rate
constrainconstrains the weights during training, defaults to no constraint

Definition at line 274 of file mnist_mlp.hpp.

276  : m_layer_sizes(layer_sizes),
277  m_epochs(epochs),
280  {
281  for (size_t i = 0; i < layer_sizes.size() - 1; i++) {
282  m_layers.emplace_back(
283  Matrix<Real>(layer_sizes[i], layer_sizes[i + 1]));
284  }
285 
286  int seed = std::chrono::system_clock::now().time_since_epoch().count();
287  auto rng = std::default_random_engine(seed);
288  std::normal_distribution<Real> distribution(0.0, 1.0);
289  for (auto &layer : m_layers) {
290  // Kaiming init, best suited for ReLU activation functions
291  auto scale = std::sqrt(2.0 / double(layer.rows()));
292  for (size_t i = 0; i < layer.size(); i++) {
293  layer[i] = distribution(rng) * scale;
294  }
295  }
296 
297  // Glorot uniform
298  /*for (auto &layer : m_layers) {
299  auto limit = std::sqrt(6.0 / Real(layer.rows()+ layer.cols()));
300  std::uniform_real_distribution<Real> distribution(0, limit);
301  for (size_t i = 0; i < layer.size(); i++) {
302  layer[i] = distribution(rng);
303  }
304  }*/
305  try {
306  load_data("");
307  }
308  catch (...) {
309  load_data("../");
310  }
311  m_constraint.setup(m_layers);
312  }
Real learn_rate
Definition: mnist_mlp.hpp:250
size_t m_epochs
Definition: mnist_mlp.hpp:248
size_t m_batchsize
Definition: mnist_mlp.hpp:249
std::vector< size_t > m_layer_sizes
Definition: mnist_mlp.hpp:244
const size_t & batchsize() const override
Definition: mnist_mlp.hpp:532
Constraint m_constraint
Definition: mnist_mlp.hpp:260
std::vector< cypress::Matrix< Real > > m_layers
Definition: mnist_mlp.hpp:243
const size_t & epochs() const override
Definition: mnist_mlp.hpp:531
void load_data(std::string path)
Definition: mnist_mlp.hpp:254
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
MNIST::MLP< Loss, ActivationFunction, Constraint >::MLP ( Json &  data,
size_t  epochs = 20,
size_t  batchsize = 100,
Real  learn_rate = 0.01,
bool  random = false,
Constraint  constraint = Constraint() 
)
inline

Constructs the network from json file. The repo provides python scripts to create those from a keras network.

Parameters
datajson object containing the network information
epochsnumber of epochs to train
batchsizemini batchsize before updating the weights
learn_rategradients are multiplied with this rate
randomUse structure from Json, initialize weights random if true
constrainconstrains the weights during training, defaults to no constraint

Definition at line 326 of file mnist_mlp.hpp.

329  : m_epochs(epochs),
332  m_constraint(constraint)
333  {
334  int seed = std::chrono::system_clock::now().time_since_epoch().count();
335  auto rng = std::default_random_engine(seed);
336  std::normal_distribution<Real> distribution(0.0, 1.0);
337  for (auto &layer : data["netw"]) {
338  if (layer["class_name"].get<std::string>() == "Dense") {
339  auto &json = layer["weights"];
340  m_layers.emplace_back(
341  Matrix<Real>(json.size(), json[0].size()));
342  auto &weights = m_layers.back();
343  auto scale = std::sqrt(2.0 / double(weights.rows()));
344  for (size_t i = 0; i < json.size(); i++) {
345  for (size_t j = 0; j < json[i].size(); j++) {
346  if (!random) {
347  weights(i, j) = json[i][j].get<Real>();
348  }
349  else {
350  weights(i, j) = distribution(rng) * scale;
351  }
352  }
353  }
354  m_layer_sizes.emplace_back(m_layers.back().rows());
356  cypress::global_logger().debug(
357  "MNIST", "Dense layer detected with size " +
358  std::to_string(weights.rows()) + " times " +
359  std::to_string(weights.cols()));
360  }
361  else if (layer["class_name"].get<std::string>() == "Conv2D") {
362  auto &json = layer["weights"];
363  size_t kernel_x = json.size();
364  size_t kernel_y = json[0].size();
365  size_t kernel_z = json[0][0].size();
366  size_t output = json[0][0][0].size();
367  size_t stride = layer["stride"];
368  size_t padding = layer["padding"] == "valid" ? 0 : 1;
369  std::vector<size_t> input_sizes;
370  std::vector<size_t> output_sizes;
371  if (!layer["input_shape_x"].empty()){
372  input_sizes.push_back(layer["input_shape_x"]);
373  input_sizes.push_back(layer["input_shape_y"]);
374  input_sizes.push_back(layer["input_shape_z"]);
375  } else {
377  input_sizes.push_back(m_filters.back().output_sizes[0]);
378  input_sizes.push_back(m_filters.back().output_sizes[1]);
379  input_sizes.push_back(m_filters.back().output_sizes[2]);
380  } else if (m_layer_types.back() == mnist_helper::LAYER_TYPE::Pooling) {
381  input_sizes.push_back(m_pools.back().output_sizes[0]);
382  input_sizes.push_back(m_pools.back().output_sizes[1]);
383  input_sizes.push_back(m_pools.back().output_sizes[2]);
384  } else if (m_layer_types.back() == mnist_helper::LAYER_TYPE::Dense) {
385  throw std::runtime_error("Conv after Dense layer not implemented!");
386  }
387  }
388  output_sizes.push_back((input_sizes[0] - kernel_x + 2*padding)/stride+1);
389  output_sizes.push_back((input_sizes[1] - kernel_x + 2*padding)/stride+1);
390  output_sizes.push_back(output);
392  kernel_x,
393  std::vector<std::vector<std::vector<Real>>>(kernel_y,
394  std::vector<std::vector<Real>>(kernel_z,
395  std::vector<Real>(output)))
396  );
398  conv_filter,
399  input_sizes,
400  output_sizes,
401  stride,
402  padding};
403  m_filters.emplace_back(conv);
404  auto &weights = m_filters.back().filter;
405  //auto scale = std::sqrt(2.0 / double(weights.rows()));
406  for (size_t i = 0; i < json.size(); i++){
407  for (size_t j = 0; j < json[i].size(); j++){
408  for (size_t k = 0; k < json[i][j].size(); k++){
409  for (size_t l = 0 ; l < json[i][j][k].size(); l++){
410  weights[i][j][k][l] = json[i][j][k][l].get<Real>();
411  }
412  }
413  }
414  }
415  m_layer_sizes.emplace_back(input_sizes[0] * input_sizes[1] * input_sizes[2]);
417  cypress::global_logger().debug(
418  "MNIST", "Conv layer detected with size ("+
419  std::to_string(json.size())+","+std::to_string(json[0].size())+
420  ","+std::to_string(json[0][0].size())+","+std::to_string(json[0][0][0].size())+")");
421  } else if(layer["class_name"].get<std::string>() == "MaxPooling2D"){
422  std::vector<size_t> size = layer["size"];
423  size_t stride = layer["stride"];
424  std::vector<size_t> input_sizes;
425  std::vector<size_t> output_sizes;
426  if (m_layer_types.empty()){
427  throw std::runtime_error("Pooling layer must not be the first layer!");
428  }
430  input_sizes.push_back(m_filters.back().output_sizes[0]);
431  input_sizes.push_back(m_filters.back().output_sizes[1]);
432  input_sizes.push_back(m_filters.back().output_sizes[2]);
433  } else if (m_layer_types.back() == mnist_helper::LAYER_TYPE::Pooling){
434  input_sizes.push_back(m_pools.back().output_sizes[0]);
435  input_sizes.push_back(m_pools.back().output_sizes[1]);
436  input_sizes.push_back(m_pools.back().output_sizes[2]);
437  } else if (m_layer_types.back() == mnist_helper::LAYER_TYPE::Dense){
438  throw std::runtime_error("Pooling after Dense not implemented!");
439  }
440  output_sizes.push_back((input_sizes[0] - size[0] + 2*0)/stride+1);
441  output_sizes.push_back((input_sizes[1] - size[1] + 2*0)/stride+1);
442  output_sizes.push_back(input_sizes[2]);
443  mnist_helper::POOLING_LAYER pool = {input_sizes, output_sizes, size, stride};
444  m_pools.emplace_back(pool);
445  m_layer_sizes.emplace_back(input_sizes[0] * input_sizes[1] * input_sizes[2]);
447  cypress::global_logger().debug(
448  "MNIST", "Pooling layer detected with size (" +
449  std::to_string(size[0]) + ", " + std::to_string(size[1]) +
450  ") and stride " + std::to_string(stride));
451  }
452  else {
453  throw std::runtime_error("Unknown layer type");
454  }
455  }
456  m_layer_sizes.push_back(m_layers.back().cols());
457 // for (auto &layer : m_layers) {
458 // m_layer_sizes.emplace_back(layer.cols());
459 // }
460 
461  m_mnist = mnist_helper::loadMnistData(60000, "train");
462  m_mnist_test = mnist_helper::loadMnistData(10000, "t10k");
463  m_constraint.setup(m_layers);
464  }
Real learn_rate
Definition: mnist_mlp.hpp:250
size_t m_epochs
Definition: mnist_mlp.hpp:248
std::vector< mnist_helper::POOLING_LAYER > m_pools
Definition: mnist_mlp.hpp:246
size_t m_batchsize
Definition: mnist_mlp.hpp:249
std::vector< size_t > m_layer_sizes
Definition: mnist_mlp.hpp:244
std::vector< mnist_helper::CONVOLUTION_LAYER > m_filters
Definition: mnist_mlp.hpp:245
const size_t & batchsize() const override
Definition: mnist_mlp.hpp:532
Constraint m_constraint
Definition: mnist_mlp.hpp:260
mnist_helper::MNIST_DATA m_mnist
Definition: mnist_mlp.hpp:251
std::vector< cypress::Matrix< Real > > m_layers
Definition: mnist_mlp.hpp:243
mnist_helper::MNIST_DATA m_mnist_test
Definition: mnist_mlp.hpp:252
const size_t & epochs() const override
Definition: mnist_mlp.hpp:531
std::vector< std::vector< std::vector< std::vector< Real > > > > CONVOLUTION_FILTER
MNIST_DATA loadMnistData(const size_t num_data, const std::string path)
Read in MNIST data from files.
std::vector< mnist_helper::LAYER_TYPE > m_layer_types
Definition: mnist_mlp.hpp:247

Member Function Documentation

template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
size_t MNIST::MLP< Loss, ActivationFunction, Constraint >::accuracy ( const std::vector< std::vector< std::vector< Real >>> &  activations,
const std::vector< size_t > &  indices,
const size_t  start 
)
inlineoverridevirtual

Calculate the overall accuracy from the given neural network output.

Parameters
activationsoutput of forward path
startthe start index, uses images indices[start] until indices[start +batchsize -1]
activationsresult of forward path
Returns
the number of correctly classified images

Implements MNIST::MLPBase.

Definition at line 900 of file mnist_mlp.hpp.

903  {
904 #ifndef NDEBUG
905  assert(activations.size() == m_batchsize);
906 #endif
907 
908  auto &labels = std::get<1>(m_mnist);
909  size_t sum = 0;
910 
911  for (size_t sample = 0; sample < m_batchsize; sample++) {
912  if (start + sample >= indices.size())
913  break;
914  if (correct(labels[indices[start + sample]],
915  activations[sample].back()))
916  sum++;
917  }
918  return sum;
919  }
size_t m_batchsize
Definition: mnist_mlp.hpp:249
mnist_helper::MNIST_DATA m_mnist
Definition: mnist_mlp.hpp:251
bool correct(const uint16_t label, const std::vector< Real > &output) const override
Checks if the output of the network was correct.
Definition: mnist_mlp.hpp:678
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
virtual void MNIST::MLP< Loss, ActivationFunction, Constraint >::backward_path ( const std::vector< size_t > &  indices,
const size_t  start,
const std::vector< std::vector< std::vector< Real >>> &  activations,
bool  last_only = false 
)
inlineoverridevirtual

implementation of backprop

Parameters
indiceslist of shuffled (?) indices
startthe start index, uses images indices[start] until indices[start +batchsize -1]
activationsresult of forward path
last_onlytrue for last layer only training (Perceptron learn rule)

Implements MNIST::MLPBase.

Definition at line 798 of file mnist_mlp.hpp.

802  {
803 #ifndef NDEBUG
804  assert(m_batchsize == activations.size());
805 #endif
806  if(!m_filters.empty()){
807  throw std::runtime_error("Conv layer not supported in forward_path function!");
808  }
809  if(!m_pools.empty()){
810  throw std::runtime_error("Pooling layer layer not supported in forward_path function!");
811  }
812  const auto &labels = std::get<1>(m_mnist);
813  const std::vector<cypress::Matrix<cypress::Real>> orig_weights =
814  m_layers;
815  for (size_t sample = 0; sample < m_batchsize; sample++) {
816  if (start + sample >= indices.size())
817  break;
818  const auto &activ = activations[sample];
819  auto error = vec_X_vec_comp(
820  Loss::calc_error(labels[indices[start + sample]], activ.back()),
821  ActivationFunction::derivative(activ.back()));
822  // TODO works for ReLU only
823  update_mat(m_layers.back(), error, activ[activ.size() - 2],
825  if (!last_only) {
826  for (size_t inv_layer = 1; inv_layer < m_layers.size();
827  inv_layer++) {
828  size_t layer_id = m_layers.size() - inv_layer - 1;
829 
830  error = vec_X_vec_comp(
831  mat_X_vec(orig_weights[layer_id + 1], error),
832  ActivationFunction::derivative(activ[layer_id + 1]));
833  update_mat(m_layers[layer_id], error, activ[layer_id],
834  m_batchsize, learn_rate);
835  }
836  }
837  }
838  m_constraint.constrain_weights(m_layers);
839  }
Real learn_rate
Definition: mnist_mlp.hpp:250
std::vector< mnist_helper::POOLING_LAYER > m_pools
Definition: mnist_mlp.hpp:246
size_t m_batchsize
Definition: mnist_mlp.hpp:249
std::vector< mnist_helper::CONVOLUTION_LAYER > m_filters
Definition: mnist_mlp.hpp:245
static std::vector< Real > mat_X_vec(const Matrix< Real > &mat, const std::vector< Real > &vec)
Implements matrix vector multiplication.
Definition: mnist_mlp.hpp:614
Constraint m_constraint
Definition: mnist_mlp.hpp:260
static std::vector< Real > vec_X_vec_comp(const std::vector< Real > &vec1, const std::vector< Real > &vec2)
Vector vector multiplication, component-wise.
Definition: mnist_mlp.hpp:658
mnist_helper::MNIST_DATA m_mnist
Definition: mnist_mlp.hpp:251
std::vector< cypress::Matrix< Real > > m_layers
Definition: mnist_mlp.hpp:243
static void update_mat(Matrix< Real > &mat, const std::vector< Real > &errors, const std::vector< Real > &pre_output, const size_t sample_num, const Real learn_rate)
Updates the weight matrix based on the error in this layer and the output of the previous layer...
Definition: mnist_mlp.hpp:696
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
virtual void MNIST::MLP< Loss, ActivationFunction, Constraint >::backward_path_2 ( const std::vector< uint16_t > &  labels,
const std::vector< std::vector< std::vector< Real >>> &  activations,
bool  last_only = false 
)
inlineoverridevirtual

Implementation of backprop, adapted for usage in SNNs.

Parameters
labelsvector containing labels of the given batch
activationsactivations in the form of [layer][sample][neuron]
last_onlytrue for last layer only training (Perceptron learn rule)

Implements MNIST::MLPBase.

Definition at line 848 of file mnist_mlp.hpp.

852  {
853 #ifndef NDEBUG
854  assert(m_batchsize == activations.back().size());
855 #endif
856  if(!m_filters.empty()){
857  throw std::runtime_error("Conv layer not supported in forward_path function!");
858  }
859  if(!m_pools.empty()){
860  throw std::runtime_error("Pooling layer layer not supported in forward_path function!");
861  }
862  const auto orig_weights = m_layers;
863  for (size_t sample = 0; sample < m_batchsize; sample++) {
864 
865  auto error = vec_X_vec_comp(
866  Loss::calc_error(labels[sample], activations.back()[sample]),
867  ActivationFunction::derivative(activations.back()[sample]));
868  // TODO works for ReLU only
869  update_mat(m_layers.back(), error,
870  activations[activations.size() - 2][sample], m_batchsize,
871  learn_rate);
872  if (!last_only) {
873  for (size_t inv_layer = 1; inv_layer < m_layers.size();
874  inv_layer++) {
875  size_t layer_id = m_layers.size() - inv_layer - 1;
876 
877  error = vec_X_vec_comp(
878  mat_X_vec(orig_weights[layer_id + 1], error),
879  ActivationFunction::derivative(
880  activations[layer_id + 1][sample]));
881  update_mat(m_layers[layer_id], error,
882  activations[layer_id][sample], m_batchsize,
883  learn_rate);
884  }
885  }
886  m_constraint.constrain_weights(m_layers);
887  }
888  }
Real learn_rate
Definition: mnist_mlp.hpp:250
std::vector< mnist_helper::POOLING_LAYER > m_pools
Definition: mnist_mlp.hpp:246
size_t m_batchsize
Definition: mnist_mlp.hpp:249
std::vector< mnist_helper::CONVOLUTION_LAYER > m_filters
Definition: mnist_mlp.hpp:245
static std::vector< Real > mat_X_vec(const Matrix< Real > &mat, const std::vector< Real > &vec)
Implements matrix vector multiplication.
Definition: mnist_mlp.hpp:614
Constraint m_constraint
Definition: mnist_mlp.hpp:260
static std::vector< Real > vec_X_vec_comp(const std::vector< Real > &vec1, const std::vector< Real > &vec2)
Vector vector multiplication, component-wise.
Definition: mnist_mlp.hpp:658
std::vector< cypress::Matrix< Real > > m_layers
Definition: mnist_mlp.hpp:243
static void update_mat(Matrix< Real > &mat, const std::vector< Real > &errors, const std::vector< Real > &pre_output, const size_t sample_num, const Real learn_rate)
Updates the weight matrix based on the error in this layer and the output of the previous layer...
Definition: mnist_mlp.hpp:696
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
const size_t& MNIST::MLP< Loss, ActivationFunction, Constraint >::batchsize ( ) const
inlineoverridevirtual

Implements MNIST::MLPBase.

Definition at line 532 of file mnist_mlp.hpp.

532 { return m_batchsize; }
size_t m_batchsize
Definition: mnist_mlp.hpp:249
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
Real MNIST::MLP< Loss, ActivationFunction, Constraint >::conv_max_weight ( size_t  layer_id) const
inlineoverridevirtual

Implements MNIST::MLPBase.

Definition at line 482 of file mnist_mlp.hpp.

483  {
484  Real max = 0.0;
485  auto layer = m_filters[layer_id];
486  auto filter = layer.filter;
487  for (size_t f = 0; f < layer.output_sizes[2]; f++) {
488  for (size_t x = 0; x < filter.size(); x++) {
489  for (size_t y = 0; y < filter[0].size(); y++) {
490  for (size_t z = 0; z < filter[0][0].size(); z++) {
491  max = filter[x][y][z][f] > max ? filter[x][y][z][f] : max;
492  }
493  }
494  }
495  }
496  return max;
497  }
std::vector< mnist_helper::CONVOLUTION_LAYER > m_filters
Definition: mnist_mlp.hpp:245
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
bool MNIST::MLP< Loss, ActivationFunction, Constraint >::correct ( const uint16_t  label,
const std::vector< Real > &  output 
) const
inlineoverridevirtual

Checks if the output of the network was correct.

Parameters
labelthe correct neuron
outputthe output of the layer
Returns
true for correct classification

Implements MNIST::MLPBase.

Definition at line 678 of file mnist_mlp.hpp.

680  {
681  auto it = std::max_element(output.begin(), output.end());
682  auto out = std::distance(output.begin(), it);
683  return out == label;
684  }
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
const size_t& MNIST::MLP< Loss, ActivationFunction, Constraint >::epochs ( ) const
inlineoverridevirtual

Implements MNIST::MLPBase.

Definition at line 531 of file mnist_mlp.hpp.

531 { return m_epochs; }
size_t m_epochs
Definition: mnist_mlp.hpp:248
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
virtual std::vector<std::vector<std::vector<Real> > > MNIST::MLP< Loss, ActivationFunction, Constraint >::forward_path ( const std::vector< size_t > &  indices,
const size_t  start 
) const
inlineoverridevirtual

Forward path of the network (–> inference)

Parameters
indiceslist of shuffled (?) indices
startthe start index, uses images indices[start] until indices[start +batchsize -1]
Returns
std::vector< std::vector< std::vector< cypress::Real > > > the outputs of all layers, given in output[sample][layer][neuron]

Implements MNIST::MLPBase.

Definition at line 724 of file mnist_mlp.hpp.

726  {
727  if(!m_filters.empty()){
728  throw std::runtime_error("Conv layer not supported in forward_path function!");
729  }
730  if(!m_pools.empty()){
731  throw std::runtime_error("Pooling layer layer not supported in forward_path function!");
732  }
733  auto &input = std::get<0>(m_mnist);
734  std::vector<std::vector<std::vector<Real>>> res;
735  std::vector<std::vector<Real>> activations;
736  for (auto size : m_layer_sizes) {
737  activations.emplace_back(std::vector<Real>(size, 0.0));
738  }
739  for (size_t sample = 0; sample < m_batchsize; sample++) {
740  res.emplace_back(activations);
741  }
742 
743  for (size_t sample = 0; sample < m_batchsize; sample++) {
744  if (start + sample >= indices.size())
745  break;
746  res[sample][0] = input[indices[start + sample]];
747  for (size_t layer = 0; layer < m_layers.size(); layer++) {
748  res[sample][layer + 1] = ActivationFunction::function(
749  mat_trans_X_vec(m_layers[layer], res[sample][layer]));
750  }
751  }
752  return res;
753  }
std::vector< mnist_helper::POOLING_LAYER > m_pools
Definition: mnist_mlp.hpp:246
size_t m_batchsize
Definition: mnist_mlp.hpp:249
std::vector< size_t > m_layer_sizes
Definition: mnist_mlp.hpp:244
std::vector< mnist_helper::CONVOLUTION_LAYER > m_filters
Definition: mnist_mlp.hpp:245
static std::vector< Real > mat_trans_X_vec(const Matrix< Real > &mat, const std::vector< Real > &vec)
Implements transposed matrix vector multiplication.
Definition: mnist_mlp.hpp:636
mnist_helper::MNIST_DATA m_mnist
Definition: mnist_mlp.hpp:251
std::vector< cypress::Matrix< Real > > m_layers
Definition: mnist_mlp.hpp:243
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
virtual Real MNIST::MLP< Loss, ActivationFunction, Constraint >::forward_path_test ( ) const
inlineoverridevirtual

Forward path of test data.

Returns
cypress::Real the accuracy on test data

Implements MNIST::MLPBase.

Definition at line 760 of file mnist_mlp.hpp.

761  {
762  if(!m_filters.empty()){
763  throw std::runtime_error("Conv layer not supported in forward_path function!");
764  }
765  if(!m_pools.empty()){
766  throw std::runtime_error("Pooling layer layer not supported in forward_path function!");
767  }
768  auto &input = std::get<0>(m_mnist_test);
769  auto &labels = std::get<1>(m_mnist_test);
770  std::vector<std::vector<Real>> activations;
771  for (auto size : m_layer_sizes) {
772  activations.emplace_back(std::vector<Real>(size, 0.0));
773  }
774  size_t sum = 0;
775  for (size_t sample = 0; sample < input.size(); sample++) {
776  activations[0] = input[sample];
777  for (size_t layer = 0; layer < m_layers.size(); layer++) {
778  activations[layer + 1] = ActivationFunction::function(
779  mat_trans_X_vec(m_layers[layer], activations[layer]));
780  }
781  if (correct(labels[sample], activations.back()))
782  sum++;
783  }
784 
785  return Real(sum) / Real(labels.size());
786  }
std::vector< mnist_helper::POOLING_LAYER > m_pools
Definition: mnist_mlp.hpp:246
std::vector< size_t > m_layer_sizes
Definition: mnist_mlp.hpp:244
std::vector< mnist_helper::CONVOLUTION_LAYER > m_filters
Definition: mnist_mlp.hpp:245
static std::vector< Real > mat_trans_X_vec(const Matrix< Real > &mat, const std::vector< Real > &vec)
Implements transposed matrix vector multiplication.
Definition: mnist_mlp.hpp:636
std::vector< cypress::Matrix< Real > > m_layers
Definition: mnist_mlp.hpp:243
mnist_helper::MNIST_DATA m_mnist_test
Definition: mnist_mlp.hpp:252
bool correct(const uint16_t label, const std::vector< Real > &output) const override
Checks if the output of the network was correct.
Definition: mnist_mlp.hpp:678
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
const std::vector<mnist_helper::CONVOLUTION_LAYER>& MNIST::MLP< Loss, ActivationFunction, Constraint >::get_conv_layers ( )
inlineoverridevirtual

Return all filter weights in the form of weights[x][y][depth][filter].

Returns
const mnist_helper::Conv_TYPE &

Implements MNIST::MLPBase.

Definition at line 570 of file mnist_mlp.hpp.

571  {
572  return m_filters;
573  }
std::vector< mnist_helper::CONVOLUTION_LAYER > m_filters
Definition: mnist_mlp.hpp:245
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
const std::vector<size_t>& MNIST::MLP< Loss, ActivationFunction, Constraint >::get_layer_sizes ( )
inlineoverridevirtual

Return the number of neurons per layer.

Returns
const std::vector< size_t >&

Implements MNIST::MLPBase.

Definition at line 585 of file mnist_mlp.hpp.

586  {
587  return m_layer_sizes;
588  }
std::vector< size_t > m_layer_sizes
Definition: mnist_mlp.hpp:244
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
const std::vector<mnist_helper::LAYER_TYPE>& MNIST::MLP< Loss, ActivationFunction, Constraint >::get_layer_types ( )
inlineoverridevirtual

Implements MNIST::MLPBase.

Definition at line 590 of file mnist_mlp.hpp.

591  {
592  return m_layer_types;
593  }
std::vector< mnist_helper::LAYER_TYPE > m_layer_types
Definition: mnist_mlp.hpp:247
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
const std::vector<mnist_helper::POOLING_LAYER>& MNIST::MLP< Loss, ActivationFunction, Constraint >::get_pooling_layers ( )
inlineoverridevirtual

Implements MNIST::MLPBase.

Definition at line 575 of file mnist_mlp.hpp.

576  {
577  return m_pools;
578  }
std::vector< mnist_helper::POOLING_LAYER > m_pools
Definition: mnist_mlp.hpp:246
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
const std::vector<cypress::Matrix<Real> >& MNIST::MLP< Loss, ActivationFunction, Constraint >::get_weights ( )
inlineoverridevirtual

Return all weights in the form of weights[layer](src,tar)

Returns
const std::vector< cypress::Matrix< cypress::Real > >&

Implements MNIST::MLPBase.

Definition at line 559 of file mnist_mlp.hpp.

560  {
561  return m_layers;
562  }
std::vector< cypress::Matrix< Real > > m_layers
Definition: mnist_mlp.hpp:243
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
const Real& MNIST::MLP< Loss, ActivationFunction, Constraint >::learnrate ( ) const
inlineoverridevirtual

Implements MNIST::MLPBase.

Definition at line 533 of file mnist_mlp.hpp.

533 { return learn_rate; }
Real learn_rate
Definition: mnist_mlp.hpp:250
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
void MNIST::MLP< Loss, ActivationFunction, Constraint >::load_data ( std::string  path)
inlineprotected

Definition at line 254 of file mnist_mlp.hpp.

255  {
256  m_mnist = mnist_helper::loadMnistData(60000, path + "train");
257  m_mnist_test = mnist_helper::loadMnistData(10000, path + "t10k");
258  }
mnist_helper::MNIST_DATA m_mnist
Definition: mnist_mlp.hpp:251
mnist_helper::MNIST_DATA m_mnist_test
Definition: mnist_mlp.hpp:252
MNIST_DATA loadMnistData(const size_t num_data, const std::string path)
Read in MNIST data from files.
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
static std::vector<Real> MNIST::MLP< Loss, ActivationFunction, Constraint >::mat_trans_X_vec ( const Matrix< Real > &  mat,
const std::vector< Real > &  vec 
)
inlinestatic

Implements transposed matrix vector multiplication.

Parameters
matthe matrix to transpose: mat.rows() ==! vec.size()
vecthe vector
Returns
std::vector< cypress::Real > resulting vector

Definition at line 636 of file mnist_mlp.hpp.

638  {
639 #ifndef NDEBUG
640  assert(mat.rows() == vec.size());
641 #endif
642  std::vector<Real> res(mat.cols(), 0.0);
643  for (size_t i = 0; i < mat.cols(); i++) {
644  for (size_t j = 0; j < mat.rows(); j++) {
645  res[i] += mat(j, i) * vec[j];
646  }
647  }
648  return res;
649  }
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
static std::vector<Real> MNIST::MLP< Loss, ActivationFunction, Constraint >::mat_X_vec ( const Matrix< Real > &  mat,
const std::vector< Real > &  vec 
)
inlinestatic

Implements matrix vector multiplication.

Parameters
matthe matrix: mat.cols() ==! vec.size()
vecthe vector
Returns
std::vector< cypress::Real >

Definition at line 614 of file mnist_mlp.hpp.

616  {
617 #ifndef NDEBUG
618  assert(mat.cols() == vec.size());
619 #endif
620  std::vector<Real> res(mat.rows(), 0.0);
621  for (size_t i = 0; i < mat.rows(); i++) {
622  for (size_t j = 0; j < mat.cols(); j++) {
623  res[i] += mat(i, j) * vec[j];
624  }
625  }
626  return res;
627  }
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
Real MNIST::MLP< Loss, ActivationFunction, Constraint >::max_weight ( ) const
inlineoverridevirtual

Return the largest weight in the network.

Returns
value of the weight

Implements MNIST::MLPBase.

Definition at line 471 of file mnist_mlp.hpp.

472  {
473  Real max = 0.0;
474  for (auto &layer : m_layers) {
475  auto w = mnist_helper::max_weight(layer);
476  if (w > max)
477  max = w;
478  }
479  return max;
480  }
std::vector< cypress::Matrix< Real > > m_layers
Definition: mnist_mlp.hpp:243
Real max_weight(const T &json)
Calculate the max weight, ignore negative values.
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
Real MNIST::MLP< Loss, ActivationFunction, Constraint >::max_weight_abs ( ) const
inlineoverridevirtual

Return the largest absolute weight in the network.

Returns
value of the weight

Implements MNIST::MLPBase.

Definition at line 520 of file mnist_mlp.hpp.

521  {
522  Real max = 0.0;
523  for (auto &layer : m_layers) {
524  auto w = mnist_helper::max_weight_abs(layer);
525  if (w > max)
526  max = w;
527  }
528  return max;
529  }
Real max_weight_abs(const T &json)
Calculate the max absolute weight.
std::vector< cypress::Matrix< Real > > m_layers
Definition: mnist_mlp.hpp:243
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
Real MNIST::MLP< Loss, ActivationFunction, Constraint >::min_weight ( ) const
inlineoverridevirtual

Return the smallest weight in the network.

Returns
value of the weight

Implements MNIST::MLPBase.

Definition at line 504 of file mnist_mlp.hpp.

505  {
506  Real min = 0.0;
507  for (auto &layer : m_layers) {
508  auto w = mnist_helper::min_weight(layer);
509  if (w < min)
510  min = w;
511  }
512  return min;
513  }
Real min_weight(const T &json)
Calculate the min weight.
std::vector< cypress::Matrix< Real > > m_layers
Definition: mnist_mlp.hpp:243
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
const mnist_helper::MNIST_DATA& MNIST::MLP< Loss, ActivationFunction, Constraint >::mnist_test_set ( )
inlineoverridevirtual

Returns reference to the test data.

Returns
const mnist_helper::MNIST_DATA&

Implements MNIST::MLPBase.

Definition at line 549 of file mnist_mlp.hpp.

550  {
551  return m_mnist_test;
552  }
mnist_helper::MNIST_DATA m_mnist_test
Definition: mnist_mlp.hpp:252
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
const mnist_helper::MNIST_DATA& MNIST::MLP< Loss, ActivationFunction, Constraint >::mnist_train_set ( )
inlineoverridevirtual

Returns reference to the train data.

Returns
const mnist_helper::MNIST_DATA&

Implements MNIST::MLPBase.

Definition at line 540 of file mnist_mlp.hpp.

541  {
542  return m_mnist;
543  }
mnist_helper::MNIST_DATA m_mnist
Definition: mnist_mlp.hpp:251
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
void MNIST::MLP< Loss, ActivationFunction, Constraint >::scale_down_images ( size_t  pooling_size = 3)
inlineoverridevirtual

Scale down the whole data set, reduces the image by a given factor in every dimension.

Parameters
pooling_sizethe factor reducing the image

Implements MNIST::MLPBase.

Definition at line 601 of file mnist_mlp.hpp.

602  {
603  m_mnist = mnist_helper::scale_mnist(m_mnist, pooling_size);
605  }
MNIST_DATA scale_mnist(MNIST_DATA &data, size_t pooling_size=3)
downscale the complete MNIST dataset
mnist_helper::MNIST_DATA m_mnist
Definition: mnist_mlp.hpp:251
mnist_helper::MNIST_DATA m_mnist_test
Definition: mnist_mlp.hpp:252
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
void MNIST::MLP< Loss, ActivationFunction, Constraint >::train ( unsigned  seed = 0)
inlineoverridevirtual

Starts the full training process.

Parameters
seedsets up the random numbers for image shuffling

Implements MNIST::MLPBase.

Definition at line 926 of file mnist_mlp.hpp.

927  {
928  std::vector<size_t> indices(std::get<0>(m_mnist).size());
929  m_constraint.constrain_weights(m_layers);
930  for (size_t i = 0; i < indices.size(); i++) {
931  indices[i] = i;
932  }
933  if (seed == 0) {
934  seed = std::chrono::system_clock::now().time_since_epoch().count();
935  }
936  auto rng = std::default_random_engine{seed};
937 
938  for (size_t epoch = 0; epoch < m_epochs; epoch++) {
939  size_t correct = 0;
940  std::shuffle(indices.begin(), indices.end(), rng);
941  for (size_t current_idx = 0;
942  current_idx < std::get<1>(m_mnist).size();
943  current_idx += m_batchsize) {
944  auto activations = forward_path(indices, current_idx);
945  correct += accuracy(activations, indices, current_idx);
946  backward_path(indices, current_idx, activations);
947  m_constraint.constrain_weights(m_layers);
948  }
949  cypress::global_logger().info(
950  "MLP", "Accuracy of epoch " + std::to_string(epoch) + ": " +
951  std::to_string(Real(correct) /
952  Real(std::get<1>(m_mnist).size())));
953  }
954  }
size_t m_epochs
Definition: mnist_mlp.hpp:248
size_t m_batchsize
Definition: mnist_mlp.hpp:249
Constraint m_constraint
Definition: mnist_mlp.hpp:260
size_t accuracy(const std::vector< std::vector< std::vector< Real >>> &activations, const std::vector< size_t > &indices, const size_t start) override
Calculate the overall accuracy from the given neural network output.
Definition: mnist_mlp.hpp:900
mnist_helper::MNIST_DATA m_mnist
Definition: mnist_mlp.hpp:251
virtual std::vector< std::vector< std::vector< Real > > > forward_path(const std::vector< size_t > &indices, const size_t start) const override
Forward path of the network (–> inference)
Definition: mnist_mlp.hpp:724
std::vector< cypress::Matrix< Real > > m_layers
Definition: mnist_mlp.hpp:243
bool correct(const uint16_t label, const std::vector< Real > &output) const override
Checks if the output of the network was correct.
Definition: mnist_mlp.hpp:678
virtual void backward_path(const std::vector< size_t > &indices, const size_t start, const std::vector< std::vector< std::vector< Real >>> &activations, bool last_only=false) override
implementation of backprop
Definition: mnist_mlp.hpp:798
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
static void MNIST::MLP< Loss, ActivationFunction, Constraint >::update_mat ( Matrix< Real > &  mat,
const std::vector< Real > &  errors,
const std::vector< Real > &  pre_output,
const size_t  sample_num,
const Real  learn_rate 
)
inlinestatic

Updates the weight matrix based on the error in this layer and the output of the previous layer.

Parameters
matweight matrix.
errorserror vector in this layer
pre_outputoutput rates of previous layer
sample_numnumber of samples in this batch == mini batchsize
learn_ratethe learn rate multiplied with the gradient

Definition at line 696 of file mnist_mlp.hpp.

701  {
702 #ifndef NDEBUG
703  assert(mat.rows() == pre_output.size());
704  assert(mat.cols() == errors.size());
705 #endif
706  Real sample_num_r(sample_num);
707  for (size_t i = 0; i < mat.rows(); i++) {
708  for (size_t j = 0; j < mat.cols(); j++) {
709  mat(i, j) = mat(i, j) - learn_rate * pre_output[i] * errors[j] /
710  sample_num_r;
711  }
712  }
713  }
Real learn_rate
Definition: mnist_mlp.hpp:250
template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
static std::vector<Real> MNIST::MLP< Loss, ActivationFunction, Constraint >::vec_X_vec_comp ( const std::vector< Real > &  vec1,
const std::vector< Real > &  vec2 
)
inlinestatic

Vector vector multiplication, component-wise.

Parameters
vec1first vector
vec2second vector of size vec1.size()
Returns
std::vector< cypress::Real > resulting vector

Definition at line 658 of file mnist_mlp.hpp.

660  {
661 #ifndef NDEBUG
662  assert(vec1.size() == vec2.size());
663 #endif
664  std::vector<Real> res(vec1.size());
665  for (size_t i = 0; i < vec1.size(); i++) {
666  res[i] = vec1[i] * vec2[i];
667  }
668  return res;
669  }

Member Data Documentation

template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
Real MNIST::MLP< Loss, ActivationFunction, Constraint >::learn_rate = 0.01
protected

Definition at line 250 of file mnist_mlp.hpp.

template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
size_t MNIST::MLP< Loss, ActivationFunction, Constraint >::m_batchsize = 100
protected

Definition at line 249 of file mnist_mlp.hpp.

template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
Constraint MNIST::MLP< Loss, ActivationFunction, Constraint >::m_constraint
protected

Definition at line 260 of file mnist_mlp.hpp.

template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
size_t MNIST::MLP< Loss, ActivationFunction, Constraint >::m_epochs = 20
protected

Definition at line 248 of file mnist_mlp.hpp.

template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
std::vector<mnist_helper::CONVOLUTION_LAYER> MNIST::MLP< Loss, ActivationFunction, Constraint >::m_filters
protected

Definition at line 245 of file mnist_mlp.hpp.

template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
std::vector<size_t> MNIST::MLP< Loss, ActivationFunction, Constraint >::m_layer_sizes
protected

Definition at line 244 of file mnist_mlp.hpp.

template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
std::vector<mnist_helper::LAYER_TYPE> MNIST::MLP< Loss, ActivationFunction, Constraint >::m_layer_types
protected

Definition at line 247 of file mnist_mlp.hpp.

template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
std::vector<cypress::Matrix<Real> > MNIST::MLP< Loss, ActivationFunction, Constraint >::m_layers
protected

Definition at line 243 of file mnist_mlp.hpp.

template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
mnist_helper::MNIST_DATA MNIST::MLP< Loss, ActivationFunction, Constraint >::m_mnist
protected

Definition at line 251 of file mnist_mlp.hpp.

template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
mnist_helper::MNIST_DATA MNIST::MLP< Loss, ActivationFunction, Constraint >::m_mnist_test
protected

Definition at line 252 of file mnist_mlp.hpp.

template<typename Loss = MSE, typename ActivationFunction = ReLU, typename Constraint = NoConstraint>
std::vector<mnist_helper::POOLING_LAYER> MNIST::MLP< Loss, ActivationFunction, Constraint >::m_pools
protected

Definition at line 246 of file mnist_mlp.hpp.


The documentation for this class was generated from the following file: