SHOGUN  3.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ConvolutionalFeatureMap.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, Shogun Toolbox Foundation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7 
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its
16  * contributors may be used to endorse or promote products derived from this
17  * software without specific prior written permission.
18 
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  * Written (W) 2014 Khaled Nasr
32  */
33 
37 #include <shogun/lib/SGVector.h>
38 #include <shogun/lib/SGMatrix.h>
40 
41 using namespace shogun;
42 
44  int32_t input_width, int32_t input_height,
45  int32_t radius_x, int32_t radius_y,
46  int32_t stride_x, int32_t stride_y,
47  int32_t index,
48  EConvMapActivationFunction function) :
49  m_input_width(input_width), m_input_height(input_height),
50  m_radius_x(radius_x), m_radius_y(radius_y),
51  m_stride_x(stride_x), m_stride_y(stride_y),
52  m_index(index),
53  m_activation_function(function)
54 {
57 
60 
62 
65 }
66 
68  SGVector< float64_t > parameters,
69  CDynamicObjectArray* layers,
70  SGVector< int32_t > input_indices,
71  SGMatrix<float64_t> activations,
72  SGMatrix<float64_t> buffer)
73 {
74  int32_t batch_size = activations.num_cols;
75 
76  // sum up all the inputs into the buffer
77  buffer.zero();
78  for (int32_t l=0; l<input_indices.vlen; l++)
79  {
80  CNeuralLayer* layer =
81  (CNeuralLayer*)layers->element(input_indices[l]);
82 
83  SGMatrix<float64_t> input = layer->get_activations();
84 
85  int32_t num_maps = layer->get_num_neurons()/m_input_num_neurons;
86 
87  for (int32_t m=0; m<num_maps; m++)
88  {
89  for (int32_t i=0; i<m_input_num_neurons; i++)
90  {
91  for (int32_t j=0; j<batch_size; j++)
92  {
93  buffer(i,j) +=
94  input(i+m*m_input_num_neurons,j);
95  }
96  }
97  }
98 
99  SG_UNREF(layer);
100  }
101 
102  SGMatrix<float64_t> weights_matrix(
103  parameters.vector+m_output_num_neurons,
105 
106  convolve(buffer, weights_matrix, activations,
107  false, true, 0, m_row_offset);
108 
109  float64_t* biases = parameters.vector;
110  for (int32_t i=0; i<m_output_num_neurons; i++)
111  {
112  for (int32_t j=0; j<batch_size; j++)
113  {
114  activations(i+m_row_offset,j) += biases[i];
115  }
116  }
117 
119  {
120  for (int32_t i=0; i<m_output_num_neurons; i++)
121  for (int32_t j=0; j<batch_size; j++)
122  activations(i+m_row_offset,j) =
123  1.0/(1.0+CMath::exp(-1.0*activations(i+m_row_offset,j)));
124  }
126  {
127  for (int32_t i=0; i<m_output_num_neurons; i++)
128  for (int32_t j=0; j<batch_size; j++)
129  activations(i+m_row_offset,j) =
130  CMath::max<float64_t>(0, activations(i+m_row_offset,j));
131  }
132 }
133 
135  SGVector< float64_t > parameters,
136  SGMatrix<float64_t> activations,
137  SGMatrix< float64_t > activation_gradients,
138  CDynamicObjectArray* layers,
139  SGVector< int32_t > input_indices,
140  SGVector< float64_t > parameter_gradients)
141 {
142  int32_t batch_size = activation_gradients.num_cols;
143 
145  {
146  for (int32_t i=0; i<m_output_num_neurons; i++)
147  {
148  for (int32_t j=0; j<batch_size; j++)
149  {
150  activation_gradients(i+m_row_offset,j) *=
151  activation_gradients(i+m_row_offset,j) *
152  (1.0-activation_gradients(i+m_row_offset,j));
153  }
154  }
155  }
157  {
158  for (int32_t i=0; i<m_output_num_neurons; i++)
159  for (int32_t j=0; j<batch_size; j++)
160  if (activations(i+m_row_offset,j)==0)
161  activation_gradients(i+m_row_offset,j) = 0;
162  }
163 
164  float64_t* bias_gradients = parameter_gradients.vector;
165  for (int32_t i=0; i<m_output_num_neurons; i++)
166  {
167  bias_gradients[i] = 0;
168  for (int32_t j=0; j<batch_size; j++)
169  bias_gradients[i] += activation_gradients(i+m_row_offset,j);
170  }
171 
172  SGMatrix<float64_t> W(parameters.vector + m_output_num_neurons,
174 
175  SGMatrix<float64_t> WG(parameter_gradients.vector + m_output_num_neurons,
177 
178  WG.zero();
179  for (int32_t l=0; l<input_indices.vlen; l++)
180  {
181  CNeuralLayer* layer =
182  (CNeuralLayer*)layers->element(input_indices[l]);
183 
184  SGMatrix<float64_t> input = layer->get_activations();
185 
186  int32_t num_maps = layer->get_num_neurons()/m_input_num_neurons;
187 
188  for (int32_t m=0; m<num_maps; m++)
189  {
191  activation_gradients, WG, m*m_input_num_neurons, m_row_offset);
192 
193  if (!layer->is_input())
194  convolve(activation_gradients, W,
195  layer->get_activation_gradients(), true, false,
197  }
198 
199  SG_UNREF(layer);
200  }
201 }
202 
204  SGMatrix< float64_t > activations,
205  int32_t pooling_width, int32_t pooling_height,
206  SGMatrix< float64_t > pooled_activations,
207  SGMatrix< float64_t > max_indices)
208 {
209  int32_t pooled_row_offset = m_row_offset/(pooling_width*pooling_height);
210 
211  for (int32_t i=0; i<pooled_activations.num_cols; i++)
212  {
213  SGMatrix<float64_t> image(
214  activations.matrix+i*activations.num_rows + m_row_offset,
216 
217  SGMatrix<float64_t> result(
218  pooled_activations.matrix+i*pooled_activations.num_rows + pooled_row_offset,
219  m_output_height/pooling_height, m_output_width/pooling_width, false);
220 
221  SGMatrix<float64_t> indices(
222  max_indices.matrix+i*max_indices.num_rows + pooled_row_offset,
223  m_output_height/pooling_height, m_output_width/pooling_width, false);
224 
225  for (int32_t x=0; x<m_output_width; x+=pooling_width)
226  {
227  for (int32_t y=0; y<m_output_height; y+=pooling_height)
228  {
229  float64_t max = image(y,x);
230  int32_t max_index = m_row_offset+y+x*image.num_rows;
231 
232  for (int32_t x1=x; x1<x+pooling_width; x1++)
233  {
234  for (int32_t y1=y; y1<y+pooling_height; y1++)
235  {
236  if (image(y1,x1) > max)
237  {
238  max = image(y1,x1);
239  max_index = m_row_offset+y1+x1*image.num_rows;
240  }
241  }
242  }
243  result(y/pooling_height, x/pooling_width) = max;
244  indices(y/pooling_height, x/pooling_width) = max_index;
245  }
246  }
247  }
248 }
249 
251  SGMatrix< float64_t > inputs,
252  SGMatrix< float64_t > weights,
253  SGMatrix< float64_t > outputs,
254  bool flip,
255  bool reset_output,
256  int32_t inputs_row_offset,
257  int32_t outputs_row_offset)
258 {
259  for (int32_t i=0; i<outputs.num_cols; i++)
260  {
261  SGMatrix<float64_t> image(
262  inputs.matrix+i*inputs.num_rows + inputs_row_offset,
263  m_input_height, m_input_width, false);
264 
265  SGMatrix<float64_t> result(
266  outputs.matrix+i*outputs.num_rows + outputs_row_offset,
268 
269  for (int32_t x=0; x<m_input_width; x+=m_stride_x)
270  {
271  for (int32_t y=0; y<m_input_height; y+=m_stride_y)
272  {
273  float64_t sum = reset_output ? 0 : result(y/m_stride_y,x/m_stride_x);
274  for (int32_t x1=x-m_radius_x; x1<=x+m_radius_x; x1++)
275  {
276  for (int32_t y1=y-m_radius_y; y1<=y+m_radius_y; y1++)
277  {
278  if (x1>=0 && y1>=0 && x1<image.num_cols && y1<image.num_rows)
279  {
280  if (flip)
281  sum +=
282  weights(y1-y+m_radius_y,x1-x+m_radius_x)*image(y1,x1);
283  else
284  sum +=
285  weights(m_radius_y-y1+y,m_radius_x-x1+x)*image(y1,x1);
286  }
287  }
288  }
289  result(y/m_stride_y,x/m_stride_x) = sum;
290  }
291  }
292  }
293 }
294 
296  SGMatrix< float64_t > inputs,
297  SGMatrix< float64_t > local_gradients,
298  SGMatrix< float64_t > weight_gradients,
299  int32_t inputs_row_offset,
300  int32_t local_gradients_row_offset)
301 {
302  for (int32_t i=0; i<local_gradients.num_cols; i++)
303  {
304  SGMatrix<float64_t> image(
305  inputs.matrix+i*inputs.num_rows + inputs_row_offset,
306  m_input_height, m_input_width, false);
307 
308  SGMatrix<float64_t> LG_image(
309  local_gradients.matrix+i*local_gradients.num_rows
310  + local_gradients_row_offset, m_output_height, m_output_width, false);
311 
312  for (int32_t x=0; x<m_input_width; x+=m_stride_x)
313  {
314  for (int32_t y=0; y<m_input_height; y+=m_stride_y)
315  {
316  for (int32_t x1=x-m_radius_x; x1<=x+m_radius_x; x1++)
317  {
318  for (int32_t y1=y-m_radius_y; y1<=y+m_radius_y; y1++)
319  {
320  if (x1>=0 && y1>=0 && x1<image.num_cols && y1<image.num_rows)
321  weight_gradients(m_radius_y-y1+y,m_radius_x-x1+x) +=
322  LG_image(y/m_stride_y,x/m_stride_x)*image(y1,x1);
323  }
324  }
325  }
326  }
327  }
328 }
#define SG_UNREF(x)
Definition: SGRefObject.h:35
void convolve(SGMatrix< float64_t > inputs, SGMatrix< float64_t > weights, SGMatrix< float64_t > outputs, bool flip, bool reset_output, int32_t inputs_row_offset, int32_t outputs_row_offset)
virtual SGMatrix< float64_t > get_activation_gradients()
Definition: NeuralLayer.h:256
virtual int32_t get_num_neurons()
Definition: NeuralLayer.h:237
Base class for neural network layers.
Definition: NeuralLayer.h:73
virtual SGMatrix< float64_t > get_activations()
Definition: NeuralLayer.h:249
void compute_activations(SGVector< float64_t > parameters, CDynamicObjectArray *layers, SGVector< int32_t > input_indices, SGMatrix< float64_t > activations, SGMatrix< float64_t > buffer)
EConvMapActivationFunction m_activation_function
CSGObject * element(int32_t idx1, int32_t idx2=0, int32_t idx3=0)
double float64_t
Definition: common.h:50
CConvolutionalFeatureMap(int32_t input_width, int32_t input_height, int32_t radius_x, int32_t radius_y, int32_t stride_x=1, int32_t stride_y=1, int32_t index=0, EConvMapActivationFunction function=CMAF_IDENTITY)
index_t num_rows
Definition: SGMatrix.h:298
Dynamic array class for CSGObject pointers that creates an array that can be used like a list or an a...
index_t num_cols
Definition: SGMatrix.h:300
static float64_t exp(float64_t x)
Definition: Math.h:444
EConvMapActivationFunction
Determines the activation function for neurons in a convolutional feature map.
virtual bool is_input()
Definition: NeuralLayer.h:113
void compute_gradients(SGVector< float64_t > parameters, SGMatrix< float64_t > activations, SGMatrix< float64_t > activation_gradients, CDynamicObjectArray *layers, SGVector< int32_t > input_indices, SGVector< float64_t > parameter_gradients)
void compute_weight_gradients(SGMatrix< float64_t > inputs, SGMatrix< float64_t > local_gradients, SGMatrix< float64_t > weight_gradients, int32_t inputs_row_offset, int32_t local_gradients_row_offset)
void pool_activations(SGMatrix< float64_t > activations, int32_t pooling_width, int32_t pooling_height, SGMatrix< float64_t > pooled_activations, SGMatrix< float64_t > max_indices)
index_t vlen
Definition: SGVector.h:707

SHOGUN Machine Learning Toolbox - Documentation