DaNNet
dnn_layer_pool.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 namespace dnn
17 {
21 
28 class layer_pool: public layer
29 {
30 protected:
31  arma::uword N_block;
32  arma::uword N_stride;
33 // arma::uword N_pad; ///< Padding
34 // arma::Mat<DNN_Dtype> C; ///< Input expanded by im2col
35  arma::Mat<DNN_Dtype> mask;
36 public:
37 // layer_pool(const arma::uword n_block, const arma::uword n_stride, const arma::uword n_pad):layer()
38 
43  layer_pool(const arma::uword n_block):layer()
44  {
45  N_block = n_block;
46  N_stride = N_block;//n_stride;
47 // N_pad = n_pad;
48  type = "Pool";
49  id = type;
50  }
51 
52  virtual void init(void)
53  {
54  layer::init();
55 
57  N_cols_right = (left->get_nrof_cols()-N_block)/N_stride + 1;
58  N_rows_right = (left->get_nrof_rows()-N_block)/N_stride + 1;
60 
61 // C. set_size(N_block*N_block*N_channels_right,N_rows_right*N_cols_right);
62  }
63 
64  virtual void upd_buf_size(arma::uword nmb)
65  {
67  mask.zeros(N_left,nmb);
68  }
69 
70  virtual void prop(void) =0;
71  virtual void prop_mb(void) =0;
72  virtual void backprop(void) =0;
73 
74  virtual void disp(void)
75  {
76  layer::disp();
77  std::cout << "Pool Rate: " << N_block << std::endl;
78  std::cout << "Stride: " << N_stride << std::endl;
79 // std::cout << "Padding: " << N_pad << std::endl;
80  std::cout << "Nr of outputs: " << get_nrof_outputs() << " ["<< N_rows_right << ","<<N_cols_right<<","<< N_channels_right<<"]"<< std::endl;
81  }
82 
90  void upsamp2(const arma::Mat<DNN_Dtype>& Src, arma::Mat<DNN_Dtype>& Dst,arma::uword N)
91  {
92  const arma::uword Rin = Src.n_rows;
93  const arma::uword Cin = Src.n_cols;
94 
95  DNN_Dtype * Dst_ptr=Dst.memptr();
96 
97  for (arma::uword c=0 ; c<Cin ; c++ )
98  {
99  for (arma::uword k=0 ; k<N ; k++ )
100  {
101  for (arma::uword r=0 ; r<Rin ; r++ )
102  {
103  const DNN_Dtype px = Src.at(r,c);
104  for (arma::uword n=0 ; n<N ; n++ )
105  {
106  *(Dst_ptr++)=px;
107  }
108  }
109  }
110  }
111  }
112 
120  void upsamp2(const arma::Cube<DNN_Dtype>& Src,arma::Cube<DNN_Dtype>& Dst, const arma::uword N)
121  {
122  for (arma::uword l=0 ; l<Src.n_slices ; l++ )
123  {
124  upsamp2(Src.slice(l),Dst.slice(l),N);
125  }
126  }
127 
128 }; // End class layer_pool
129 
136 class pool_max: public layer_pool
137 {
138 public:
139 // pool_max(const arma::uword n_block,const arma::uword n_stride,const arma::uword n_pad):layer_pool(n_block,n_stride,n_pad)
140 
145  pool_max(const arma::uword n_block):layer_pool(n_block)
146  {
147  N_block = n_block;
148  N_stride = N_block;//n_stride;
149 // N_pad = n_pad;
150  type = "MAXpool";
151  id = type+"("+std::to_string(N_block)+","+std::to_string(N_block)+")";
152  }
153 
159  void prop(void)
160  {
161  arma::Mat<DNN_Dtype> Dst(N_rows_right, N_cols_right, arma::fill::zeros);
162  DNN_Dtype* Y_ptr;
163  Y_ptr = Y1.memptr();
164  arma::Cube<DNN_Dtype> Src(left->get_Y1_memptr(), N_rows_left, N_cols_left, N_channels_left, false, true);
165  for (arma::uword l = 0; l < N_channels_left; l++)
166  {
167  for (arma::uword c = 0; c <= N_cols_left - N_block; c += N_block)
168  {
169  for (arma::uword r = 0; r <= N_rows_left - N_block; r += N_block)
170  {
171  DNN_Dtype mx = Src.at(r,c,l);
172  for (arma::uword ir = 0; ir < N_block; ir++)
173  {
174  for (arma::uword ic = 0; ic < N_block; ic++)
175  {
176  DNN_Dtype px = Src.at(r + ir, c + ic, l);
177  if (px >= mx)
178  {
179  mx = px;
180  }
181  }
182  }
183  *Y_ptr++ = mx;
184  }
185  }
186  }
187  }
188 
194  void prop_mb(void)
195  {
196  arma::Mat<DNN_Dtype> Dst(N_rows_right, N_cols_right, arma::fill::zeros);
197  arma::Mat<DNN_Dtype> mask_mat(N_rows_left,N_cols_left, arma::fill::zeros);
198  mask.zeros(); // Init mask
199  DNN_Dtype* Y_ptr;
200  for (arma::uword n = 0; n < N_batch; n++)
201  {
202  Y_ptr = Y.colptr(n);
203  arma::Cube<DNN_Dtype> Src(left->get_Y_colptr(n), N_rows_left,N_cols_left, N_channels_left,false,true);
204  for (arma::uword l = 0; l < N_channels_left; l++)
205  {
206  for (arma::uword c = 0; c <= N_cols_left - N_block; c += N_block)
207  {
208  for (arma::uword r = 0; r <= N_rows_left - N_block; r += N_block)
209  {
210  arma::uword r_offs=0, c_offs=0;
211  DNN_Dtype mx = Src.at(r,c,l);
212  for (arma::uword ir = 0; ir < N_block; ir++)
213  {
214  for (arma::uword ic = 0; ic < N_block; ic++)
215  {
216  DNN_Dtype px = Src.at(r+ir, c+ic, l);
217  if (px >= mx)
218  {
219  mx = px;
220  r_offs = ir;
221  c_offs = ic;
222  }
223  }
224  }
225  *Y_ptr++ = mx;
226  mask.at(l*N_rows_left*N_cols_left +(c+c_offs)*N_rows_left+r+r_offs, n) = 1;
227  }
228  }
229  }
230  }
231  }
232 
238  void backprop(void)
239  {
240  arma::Cube<DNN_Dtype> ttt(N_rows_right*N_block,N_cols_right*N_block,N_channels_right);
241  for (arma::uword n=0; n<N_batch; n++)
242  {
243  arma::Cube<DNN_Dtype> blob(right->get_Dleft_colptr(n),N_rows_right,N_cols_right,N_channels_right,false,true);
244  upsamp2(blob,ttt,N_block);
245  Dleft.col(n) = cube2mat(ttt,ttt.n_elem,1)%mask.col(n);
246  }
247  }
248 
249 }; // End class pool_max
250 
258 {
259 public:
260 // pool_average(const arma::uword n_block,const arma::uword n_stride,const arma::uword n_pad):layer_pool(n_block,n_stride,n_pad)
265  pool_average(const arma::uword n_block):layer_pool(n_block)
266  {
267  N_block = n_block;
268 // N_stride = n_stride;
269 // N_pad = n_pad;
270  type = "AVGpool";
271  id = type+"("+std::to_string(N_block)+","+std::to_string(N_block)+")";
272  }
273 
279  void prop(void)
280  {
281  arma::Mat<DNN_Dtype> Dst(N_rows_right,N_cols_right, arma::fill::zeros);
282  arma::Mat<DNN_Dtype> X_1 = left->get_Y1();
283  arma::Cube<DNN_Dtype> Src_cube(X_1.memptr(),N_rows_left,N_cols_left,N_channels_left);
284  for (arma::uword l=0 ; l<Src_cube.n_slices; l++ )
285  {
286  arma::Mat<DNN_Dtype> Src_mat=Src_cube.slice(l);
287  arma::Mat<DNN_Dtype> mask_mat(arma::size(Src_mat),arma::fill::zeros);
288  for (arma::uword c=0 ; c<N_cols_left-N_block ; c+=N_block )
289  {
290  for (arma::uword r=0 ; r<N_rows_left-N_block ; r+=N_block )
291  {
292  arma::Mat<DNN_Dtype> dd=Src_mat(r,c,arma::size(N_block,N_block));
293  Dst(r/N_block,c/N_block) = dd.max();
294  }
295  }
296  Y1.rows(l*Dst.n_elem,(l+1)*Dst.n_elem-1) = mat2mat(Dst,Dst.n_elem,1);
297  }
298  }
299 
305  void prop_mb(void)
306  {
307  arma::Mat<DNN_Dtype> Dst(N_rows_right, N_cols_right, arma::fill::zeros);
308  DNN_Dtype* Y_ptr;
309  const DNN_Dtype nn=(DNN_Dtype)1.0/(N_block*N_block);
310  for (arma::uword n = 0; n < N_batch; n++)
311  {
312  Y_ptr = Y.colptr(n);
313  arma::Cube<DNN_Dtype> Src(left->get_Y_colptr(n), N_rows_left,N_cols_left, N_channels_left,false,true);
314  for (arma::uword l = 0; l < N_channels_left; l++)
315  {
316  for (arma::uword c = 0; c <= N_cols_left - N_block; c += N_block)
317  {
318  for (arma::uword r = 0; r <= N_rows_left - N_block; r += N_block)
319  {
320  DNN_Dtype av=0;
321  for (arma::uword ir = 0; ir < N_block; ir++)
322  {
323  for (arma::uword ic = 0; ic < N_block; ic++)
324  {
325  av += Src.at(r+ir, c+ic, l);
326  }
327  }
328  *Y_ptr++ = av*nn;
329  }
330  }
331  }
332  }
333  }
334 
340  void backprop(void)
341  {
342  arma::Cube<DNN_Dtype> ttt(N_rows_right*N_block,N_cols_right*N_block,N_channels_right);
343  const DNN_Dtype nn = (DNN_Dtype)1.0/(N_block*N_block);
344  for (arma::uword n=0; n<N_batch; n++)
345  {
346  arma::Cube<DNN_Dtype> blob(right->get_Dleft_colptr(n),N_rows_right,N_cols_right,N_channels_right,false,true);
347  upsamp2(blob,ttt,N_block);
348  Dleft.col(n) = cube2mat(ttt,ttt.n_elem,1)*nn;
349  }
350  }
351 }; // End class pool_average
353 } // End namespace dnn
virtual void init(void)
Initialize layer.
Max pooling layer class.
std::string type
Layer type string.
void prop_mb(void)
Forward mini batch propagation though layer.
virtual void prop(void)=0
Forward propagation.
arma::Mat< DNN_Dtype > Y
Output buffer mini batch [N_right,N_batch].
arma::uword N_rows_left
Input rows.
layer * right
Pointer to next layer.
void prop(void)
Forward propagation though layer.
arma::uword N_channels_right
Output channels, number of filters.
arma_inline arma::Mat< DNN_Dtype > mat2mat(const arma::Mat< DNN_Dtype > &A, const arma::uword rows, const arma::uword cols)
Reshapes a matrix.
Definition: dnn_misc.h:125
arma::Mat< DNN_Dtype > Dleft
Error buffer [N_left,N_batch].
arma::Mat< DNN_Dtype > mask
Pooling mask.
void prop(void)
Forward propagation though layer.
Layer base class.
virtual void backprop(void)=0
Back propagation.
virtual void upd_buf_size(arma::uword nmb)
Update layer buffer sizes.
arma::uword N_cols_left
Input cols.
arma::Mat< DNN_Dtype > Y1
Output buffer [N_right,1].
virtual void prop_mb(void)=0
Forward propagation - mini batch.
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.
pool_average(const arma::uword n_block)
Average pooling layer constructor.
virtual arma::Mat< DNN_Dtype > get_Y1(void)
Get output buffer.
virtual void init(void)
Initialize layer.
arma_inline arma::Mat< DNN_Dtype > cube2mat(arma::Cube< DNN_Dtype > &A, const arma::uword rows, const arma::uword cols)
Converts a cube to a matrix.
Definition: dnn_misc.h:158
virtual arma::uword get_nrof_channels(void)
Get output buffer channel/layer size.
arma::uword N_stride
Stride.
virtual void disp(void)
Display info about layer.
float DNN_Dtype
Data type used in the network (float or double)
Definition: dnn.h:28
void backprop(void)
Backpropagation of mini batch propagation though layer.
arma::uword N_left
Total size left.
arma::uword N_rows_right
Output rows.
void upsamp2(const arma::Mat< DNN_Dtype > &Src, arma::Mat< DNN_Dtype > &Dst, arma::uword N)
2D upsampling
virtual void upd_buf_size(arma::uword nmb)
Update layer buffer sizes.
virtual void disp(void)
Display info about layer.
virtual arma::uword get_nrof_cols(void)
Get output buffer column size.
arma::uword N_batch
Mini batch size.
void upsamp2(const arma::Cube< DNN_Dtype > &Src, arma::Cube< DNN_Dtype > &Dst, const arma::uword N)
2D upsampling for Cube
Definition: dnn.h:22
arma::uword N_block
Pooling block size.
void prop_mb(void)
Forward mini batch propagation though layer.
Average pooling layer class.
arma::uword N_channels_left
Input channels, number of filters.
pool_max(const arma::uword n_block)
Max pooling layer constructor.
virtual arma::uword get_nrof_rows(void)
Get output buffer row size.
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.
Pooling layer base class.
layer_pool(const arma::uword n_block)
Pooling layer constructor.
void backprop(void)
Backpropagation of mini batch propagation though layer.
virtual DNN_Dtype * get_Dleft_colptr(const arma::uword n)
Get error buffer memory column pointer - mini batch.