DaNNet
dnn_layer_base.h
Go to the documentation of this file.
1 // Copyright 2019 Claes Rolen (www.rolensystems.com)
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 #include <ios>
17 #include <iomanip>
18 
19 namespace dnn
20 {
24 
31 class layer
32 {
33 protected:
34  // Network pointers
37  // Misc parameters
38  std::string id;
39  std::string type;
40  arma::uword layer_ix;
41  bool train_par;
42  bool add_bias;
45  // Buffer dimensions
46  arma::uword N_batch;
47  arma::uword N_rows_left;
48  arma::uword N_cols_left;
49  arma::uword N_channels_left;
50  arma::uword N_rows_right;
51  arma::uword N_cols_right;
52  arma::uword N_channels_right;
53  arma::uword N_left;
54  arma::uword N_right;
55  // Buffers - 'blob'
56  arma::Mat<DNN_Dtype> Y;
57  arma::Mat<DNN_Dtype> Y1;
58  arma::Mat<DNN_Dtype> Dleft;
59  arma::Cube<DNN_Dtype> W;
60  arma::Mat<DNN_Dtype> B;
61 
62 public:
68  layer(void)
69  {
70  left = nullptr;
71  right = nullptr;
72  id = "ID";
73  type = "TYPE";
74  layer_ix = 0;
75  N_batch = 0;
76  N_rows_left = 0;
77  N_cols_left = 0;
78  N_channels_left = 0;
79  N_rows_right = 0;
80  N_cols_right = 0;
81  N_channels_right = 0;
82  N_left = 0;
83  N_right = 0;
84  train_par = false;
85  add_bias = true;
86  opt_alg = nullptr;
87  phase = PHASE::TRAIN;
88  };
89 
90  ~layer() {};
91 
97  virtual void init(void)
98  {
99  N_left = left->get_nrof_outputs();
100  N_cols_left = left->get_nrof_cols();
101  N_rows_left = left->get_nrof_rows();
102  N_channels_left = left->get_nrof_channels();
103  }
104 
110  virtual void upd_buf_size(arma::uword nmb)
111  {
112  N_batch = nmb;
113  Y. zeros(N_right, N_batch);
114  Y1. zeros(N_right, 1);
115  Dleft.zeros(N_left, N_batch);
116  }
117 
123  friend std::ostream& operator<<(std::ostream& os, layer& lay)
124  {
125  // Dimension string
126  std::string n_out_s="["+std::to_string(lay.N_rows_right)+","+
127  std::to_string(lay.N_cols_right)+","+
128  std::to_string(lay.N_channels_right)+"]";
129  // Optimizer string
130  std::string opt_s="";
131  if(lay.opt_alg)
132  opt_s = lay.opt_alg->get_algorithm();
133  // Number of parameter string
134  std::string param_s="";
135  arma::uword p=(&lay)->get_nrof_params();
136  if(p)
137  param_s = std::to_string(p);
138 
139  // Put info to stream
140  std::ios init(NULL);
141  init.copyfmt(std::cout); // Save stream format
142 
143  os << std::left << " "
144  << std::setw(6) << lay.layer_ix
145  << std::setw(23) << lay.id
146  << std::setw(30) << opt_s
147  << std::setw(12) << n_out_s
148  << std::setw(10) << param_s;
149 
150  std::cout.copyfmt(init); // Restore stream format
151 
152  return os;
153  }
154 
157  virtual void prop(void)
158  {
159  Y1 = left->get_Y1();
160  }
161 
164  virtual void prop_mb(void)
165  {
166  Y = *(left->get_Y_ptr());
167  }
168 
171  virtual void backprop(void)
172  {
173  Dleft = *(right->get_Dleft_ptr()); // Back prop
174  }
175 
178  virtual void update(void)
179  {
180  }
181 
184  virtual void disp(void)
185  {
186  std::cout << "====================== " << std::endl;
187  std::cout << "Type: " << type << std::endl;
188  }
189 
192  virtual void enable_training(void)
193  {
194  train_par = true;
195  }
196 
199  virtual void disable_training(void)
200  {
201  train_par = false;
202  }
203 
206  virtual void enable_bias(void)
207  {
208  add_bias = true;
209  }
210 
213  virtual void disable_bias(void)
214  {
215  add_bias = false;
216  }
217 
220  virtual arma::Mat<DNN_Dtype> get_B(void)
221  {
222  return B;
223  }
224 
227  virtual arma::Cube<DNN_Dtype> get_W(void)
228  {
229  return W;
230  }
231 
234  virtual void set_B(arma::Mat<DNN_Dtype>& b)
235  {
236  B = b;
237  }
238 
241  virtual void set_W(arma::Cube<DNN_Dtype>& w)
242  {
243  W = w;
244  }
245 
248  virtual arma::uword get_nrof_params(void)
249  {
250  return 0;
251  }
252 
255  virtual void set_phase(PHASE p)
256  {
257  phase = p;
258  }
259 
262  virtual void set_left(layer* lptr)
263  {
264  left = lptr;
265  }
266 
269  virtual void set_right(layer* rptr)
270  {
271  right = rptr;
272  }
273 
276  virtual void set_id(const std::string str)
277  {
278  id = str;
279  }
280 
283  virtual std::string get_id(void)
284  {
285  return id;
286  }
287 
290  virtual void set_type(const std::string str)
291  {
292  type = str;
293  }
294 
297  virtual std::string get_type(void)
298  {
299  return type;
300  }
301 
304  virtual void set_ix(const arma::uword n)
305  {
306  layer_ix = n;
307  }
308 
311  virtual arma::uword get_ix(void)
312  {
313  return layer_ix;
314  }
315 
318  virtual void set_batch_size(const arma::uword n)
319  {
320  N_batch = n;
321  init();
322  }
323 
326  virtual arma::uword get_batch_size(void)
327  {
328  return N_batch;
329  }
330 
333  virtual void set_Y1(arma::Mat<DNN_Dtype>& y)
334  {
335  Y1 = y;
336  }
337 
340  virtual void set_Y(arma::Mat<DNN_Dtype>& y)
341  {
342  Y = y;
343  }
344 
347  virtual void set_Dleft(arma::Mat<DNN_Dtype>& d)
348  {
349  Dleft = d;
350  }
351 
354  virtual void set_rows_in(arma::uword r)
355  {
356  N_rows_left = r;
357  }
358 
361  virtual arma::uword get_nrof_rows(void)
362  {
363  return N_rows_right;
364  }
365 
368  virtual void set_cols_in(arma::uword c)
369  {
370  N_cols_left = c;
371  }
372 
375  virtual arma::uword get_nrof_cols(void)
376  {
377  return N_cols_right;
378  }
379 
382  virtual void set_channels_in(arma::uword l)
383  {
384  N_channels_left = l;
385  }
386 
389  virtual arma::uword get_nrof_channels(void)
390  {
391  return N_channels_right;
392  }
393 
396  virtual void set_opt_alg( opt& alg_class)
397  {
398  opt_alg = &alg_class;
399  }
400 
403  virtual opt* get_opt_alg( void)
404  {
405  return opt_alg;
406  }
407 
410  virtual arma::uword get_nrof_inputs(void)
411  {
412  if(left!=NULL)
413  return (left->get_nrof_rows())*(left->get_nrof_cols())*(left->get_nrof_channels());
414  else
415  return 0;
416  }
417 
420  virtual arma::uword get_nrof_outputs(void)
421  {
422  return N_rows_right*N_cols_right*N_channels_right;
423  }
424 
427  virtual arma::Mat<DNN_Dtype> get_Y1(void)
428  {
429  return Y1;
430  }
431 
434  virtual arma::Mat<DNN_Dtype>* get_Y1_ptr(void)
435  {
436  return &Y1;
437  }
438 
441  virtual DNN_Dtype* get_Y1_memptr(void)
442  {
443  return Y1.memptr();
444  }
445 
448  virtual arma::Mat<DNN_Dtype> get_Y(void)
449  {
450  return Y;
451  }
452 
455  virtual arma::Mat<DNN_Dtype>* get_Y_ptr(void)
456  {
457  return &Y;
458  }
459 
462  virtual DNN_Dtype* get_Y_memptr(void)
463  {
464  return Y.memptr();
465  }
466 
470  virtual DNN_Dtype* get_Y_colptr(const arma::uword n)
471  {
472  return Y.colptr(n);
473  }
474 
477  virtual arma::Mat<DNN_Dtype> get_Dleft()
478  {
479  return Dleft;
480  }
481 
484  virtual arma::Mat<DNN_Dtype>* get_Dleft_ptr(void)
485  {
486  return &Dleft;
487  }
488 
492  {
493  return Dleft.memptr();
494  }
495 
499  virtual DNN_Dtype* get_Dleft_colptr(const arma::uword n)
500  {
501  return Dleft.colptr(n);
502  }
503 
511  virtual void save_layer_param( std::string name, PARAM_FORMAT f=PARAM_FORMAT::ASCII)
512  {
513  switch (f)
514  {
515  case PARAM_FORMAT::ASCII:
516  W.save("dnn_w_" + name, arma::arma_ascii);
517  B.save("dnn_b_" + name, arma::arma_ascii);
518  break;
519  case PARAM_FORMAT::BIN:
520  W.save("dnn_w_" + name, arma::arma_binary);
521  B.save("dnn_b_" + name, arma::arma_binary);
522  break;
523  default:
524  std::cout << "Parameter format not implemented yet!" << std::endl;
525  }
526  }
527 
535  virtual void load_layer_param(std::string name, PARAM_FORMAT f = PARAM_FORMAT::AUTO)
536  {
537  bool ret = false;
538  switch (f)
539  {
540  case PARAM_FORMAT::AUTO:
541  ret = W.load("dnn_w_" + name, arma::auto_detect) &&
542  B.load("dnn_b_" + name, arma::auto_detect);
543  break;
544  case PARAM_FORMAT::ASCII:
545  ret = W.load("dnn_w_" + name, arma::arma_ascii) &&
546  B.load("dnn_b_" + name, arma::arma_ascii);
547  break;
548  case PARAM_FORMAT::BIN:
549  ret = W.load("dnn_w_" + name, arma::arma_binary) &&
550  B.load("dnn_b_" + name, arma::arma_binary);
551  break;
552  default:
553  std::cout << "Parameter format not implemented yet!" << std::endl;
554  }
555  if (ret != true)
556  {
557  exit(EXIT_FAILURE);
558  }
559  }
560 
571  template <typename T>
572  void init_weights(T& w, arma::uword fan_in, arma::uword fan_out, INIT_W_ALG alg, INIT_W_DIST dist)
573  {
574  if(dist == INIT_W_DIST::NORMAL) w = (T) w.randn();
575  if(dist == INIT_W_DIST::UNIFORM) w = (T) w.randu()*((DNN_Dtype)std::sqrt(3.0));
576 
577  switch(alg)
578  {
579  case INIT_W_ALG::LECUN:
580  w*=(DNN_Dtype)std::sqrt(1.0/fan_in);
581  break;
582  case INIT_W_ALG::XAVIER:
583  w*= (DNN_Dtype)std::sqrt(2.0/(fan_in+fan_out));
584  break;
585  case INIT_W_ALG::HE:
586  w*= (DNN_Dtype)std::sqrt(2.0/fan_in);
587  break;
588  case INIT_W_ALG::SIN:
589  for(arma::uword k=0; k<w.n_elem; k++ )
590  {
591  w(k) = (DNN_Dtype)(sin(k*45191.0)/std::sqrt(fan_in+fan_out));
592  }
593  break;
594  }
595  }
596 
601  {
602  return 1/(1+std::exp(-x));
603  }
604 
608  arma::Mat<DNN_Dtype> sigmoid(const arma::Mat<DNN_Dtype>& x)
609  {
610  return 1/(1+arma::trunc_exp(-x));
611  }
612 
616  arma::Mat<DNN_Dtype> softmax(const arma::Mat<DNN_Dtype>& x)
617  {
618  // Numerical stability improvement by subtracting max before exp.
619  arma::Mat<DNN_Dtype> y = arma::trunc_exp(x.each_row()-arma::max(x,0));
620  return y.each_row()/arma::sum(y,0);
621  }
622 }; // End class layer
624 } // End namespace dnn
virtual void enable_bias(void)
Enable bias term in layer.
virtual void set_ix(const arma::uword n)
Set layer index.
layer(void)
Layer constructor.
opt * opt_alg
Pointer to optimizer.
std::string type
Layer type string.
PHASE
Definition: dnn.h:34
arma::Mat< DNN_Dtype > Y
Output buffer mini batch [N_right,N_batch].
virtual void set_B(arma::Mat< DNN_Dtype > &b)
Set bias.
virtual std::string get_id(void)
Get layer id string.
virtual arma::Mat< DNN_Dtype > get_B(void)
Get bias.
virtual void set_Y1(arma::Mat< DNN_Dtype > &y)
Set output buffer.
arma::uword N_rows_left
Input rows.
std::string id
Layer id string.
layer * right
Pointer to next layer.
virtual arma::Mat< DNN_Dtype > get_Dleft()
Get error buffer - mini batch.
virtual arma::uword get_nrof_params(void)
Get number of trainable parameters.
virtual arma::Mat< DNN_Dtype > * get_Y1_ptr(void)
Get output buffer pointer.
PARAM_FORMAT
Definition: dnn.h:31
arma::uword N_channels_right
Output channels, number of filters.
arma::Mat< DNN_Dtype > Dleft
Error buffer [N_left,N_batch].
virtual void set_id(const std::string str)
Set layer id string.
virtual arma::Cube< DNN_Dtype > get_W(void)
Get weights.
friend std::ostream & operator<<(std::ostream &os, layer &lay)
operator <<
arma::Mat< DNN_Dtype > sigmoid(const arma::Mat< DNN_Dtype > &x)
Sigmoid function - matrix.
Layer base class.
arma::uword N_cols_left
Input cols.
arma::Mat< DNN_Dtype > Y1
Output buffer [N_right,1].
virtual void set_Y(arma::Mat< DNN_Dtype > &y)
Set output buffer - mini batch.
virtual void set_right(layer *rptr)
Set pointer to right layer.
virtual arma::uword get_nrof_inputs(void)
Get total number of layer inputs.
void init_weights(T &w, arma::uword fan_in, arma::uword fan_out, INIT_W_ALG alg, INIT_W_DIST dist)
Initiate weights.
virtual DNN_Dtype * get_Y_colptr(const arma::uword n)
Get output buffer memory column pointer - mini batch.
virtual arma::uword get_nrof_outputs(void)
Get total number of layer outputs.
PHASE phase
Active state/phase.
virtual arma::Mat< DNN_Dtype > get_Y1(void)
Get output buffer.
virtual void init(void)
Initialize layer.
arma::Mat< DNN_Dtype > B
Bias.
virtual arma::Mat< DNN_Dtype > get_Y(void)
Get output buffer - mini batch.
virtual arma::Mat< DNN_Dtype > * get_Dleft_ptr(void)
Get error buffer pointer - mini batch.
virtual arma::uword get_batch_size(void)
Get mini batch size.
virtual arma::uword get_nrof_channels(void)
Get output buffer channel/layer size.
virtual void update(void)
Parameter update.
INIT_W_DIST
Definition: dnn.h:33
DNN_Dtype sigmoid(const DNN_Dtype x)
Sigmoid function - scalar.
virtual void backprop(void)
Back propagation.
virtual void disp(void)
Display info about layer.
float DNN_Dtype
Data type used in the network (float or double)
Definition: dnn.h:28
arma::uword N_left
Total size left.
arma::uword N_rows_right
Output rows.
virtual void upd_buf_size(arma::uword nmb)
Update layer buffer sizes.
virtual void set_channels_in(arma::uword l)
Set input buffer channel/layer size.
virtual arma::uword get_ix(void)
Get layer index.
virtual opt * get_opt_alg(void)
Get pointer to optimizer class.
virtual arma::uword get_nrof_cols(void)
Get output buffer column size.
virtual void disable_training(void)
Disable training of layer.
virtual void load_layer_param(std::string name, PARAM_FORMAT f=PARAM_FORMAT::AUTO)
Load layer weight and bias.
arma::Cube< DNN_Dtype > W
Weights.
virtual void set_W(arma::Cube< DNN_Dtype > &w)
Set weights.
arma::uword N_batch
Mini batch size.
bool train_par
Enable training.
Definition: dnn.h:22
arma::uword layer_ix
Layer index [0..].
INIT_W_ALG
Definition: dnn.h:32
arma::uword N_channels_left
Input channels, number of filters.
virtual std::string get_algorithm(void)
Get the optimizer algorithm information.
Definition: dnn_opt.h:67
virtual void set_rows_in(arma::uword r)
Set input buffer row size.
virtual DNN_Dtype * get_Dleft_memptr(void)
Get error buffer memory pointer - mini batch.
virtual void disable_bias(void)
Disable bias term in layer.
virtual void set_Dleft(arma::Mat< DNN_Dtype > &d)
Set error output buffer - mini batch.
virtual arma::uword get_nrof_rows(void)
Get output buffer row size.
virtual void set_cols_in(arma::uword c)
Set input buffer column size.
virtual void set_batch_size(const arma::uword n)
Set mini batch size.
virtual std::string get_type(void)
Get layer type string.
virtual void set_opt_alg(opt &alg_class)
Set pointer to optimizer class.
arma::uword N_right
Total size right.
virtual DNN_Dtype * get_Y1_memptr(void)
Get output buffer memory pointer.
layer * left
Pointer to previous layer.
arma::uword N_cols_right
Output cols.
virtual void save_layer_param(std::string name, PARAM_FORMAT f=PARAM_FORMAT::ASCII)
Save layer weight and bias.
virtual DNN_Dtype * get_Y_memptr(void)
Get output buffer memory pointer - mini batch.
virtual void set_left(layer *lptr)
Set pointer to left layer.
virtual void set_type(const std::string str)
Set layer type string.
virtual void enable_training(void)
Enable training of layer.
virtual void prop_mb(void)
Forward propagation - mini batch.
virtual arma::Mat< DNN_Dtype > * get_Y_ptr(void)
Get output buffer pointer - mini batch.
virtual void set_phase(PHASE p)
Set phase/state.
arma::Mat< DNN_Dtype > softmax(const arma::Mat< DNN_Dtype > &x)
Softmax function - matrix.
virtual DNN_Dtype * get_Dleft_colptr(const arma::uword n)
Get error buffer memory column pointer - mini batch.
virtual void prop(void)
Forward propagation.
Optimizer base class.
Definition: dnn_opt.h:31
bool add_bias
Enable bias.