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,
49  ENLAutoencoderPosition autoencoder_position) :
50  m_input_width(input_width), m_input_height(input_height),
51  m_radius_x(radius_x), m_radius_y(radius_y),
52  m_stride_x(stride_x), m_stride_y(stride_y),
53  m_index(index),
54  m_activation_function(function),
55  m_autoencoder_position(autoencoder_position)
56 {
58  {
61  }
62  else
63  {
66  }
67 
70 
72 
75 }
76 
78  SGVector< float64_t > parameters,
79  CDynamicObjectArray* layers,
80  SGVector< int32_t > input_indices,
81  SGMatrix<float64_t> activations)
82 {
83  int32_t batch_size = activations.num_cols;
84 
85  float64_t bias = parameters[0];
86  for (int32_t i=0; i<m_output_num_neurons; i++)
87  {
88  for (int32_t j=0; j<batch_size; j++)
89  {
90  activations(i+m_row_offset,j) = bias;
91  }
92  }
93 
94  int32_t weights_index_offset = 1;
95  for (int32_t l=0; l<input_indices.vlen; l++)
96  {
97  CNeuralLayer* layer =
98  (CNeuralLayer*)layers->element(input_indices[l]);
99 
100  int32_t num_maps = layer->get_num_neurons()/m_input_num_neurons;
101 
102  for (int32_t m=0; m<num_maps; m++)
103  {
104  SGMatrix<float64_t> weights_matrix(parameters.vector+weights_index_offset,
106  weights_index_offset += m_filter_height*m_filter_width;
107 
108  convolve(layer->get_activations(), weights_matrix, activations,
109  false, false, m*m_input_num_neurons, m_row_offset);
110  }
111 
112  SG_UNREF(layer);
113  }
114 
116  {
117  for (int32_t i=0; i<m_output_num_neurons; i++)
118  for (int32_t j=0; j<batch_size; j++)
119  activations(i+m_row_offset,j) =
120  1.0/(1.0+CMath::exp(-1.0*activations(i+m_row_offset,j)));
121  }
123  {
124  for (int32_t i=0; i<m_output_num_neurons; i++)
125  for (int32_t j=0; j<batch_size; j++)
126  activations(i+m_row_offset,j) =
127  CMath::max<float64_t>(0, activations(i+m_row_offset,j));
128  }
129 }
130 
132  SGVector< float64_t > parameters,
133  SGMatrix<float64_t> activations,
134  SGMatrix< float64_t > activation_gradients,
135  CDynamicObjectArray* layers,
136  SGVector< int32_t > input_indices,
137  SGVector< float64_t > parameter_gradients)
138 {
139  int32_t batch_size = activation_gradients.num_cols;
140 
142  {
143  for (int32_t i=0; i<m_output_num_neurons; i++)
144  {
145  for (int32_t j=0; j<batch_size; j++)
146  {
147  activation_gradients(i+m_row_offset,j) *=
148  activation_gradients(i+m_row_offset,j) *
149  (1.0-activation_gradients(i+m_row_offset,j));
150  }
151  }
152  }
154  {
155  for (int32_t i=0; i<m_output_num_neurons; i++)
156  for (int32_t j=0; j<batch_size; j++)
157  if (activations(i+m_row_offset,j)==0)
158  activation_gradients(i+m_row_offset,j) = 0;
159  }
160 
161  float64_t bias_gradient = 0;
162  for (int32_t i=0; i<m_output_num_neurons; i++)
163  for (int32_t j=0; j<batch_size; j++)
164  bias_gradient += activation_gradients(i+m_row_offset,j);
165 
166  parameter_gradients[0] = bias_gradient;
167 
168  int32_t weights_index_offset = 1;
169  for (int32_t l=0; l<input_indices.vlen; l++)
170  {
171  CNeuralLayer* layer =
172  (CNeuralLayer*)layers->element(input_indices[l]);
173 
174  int32_t num_maps = layer->get_num_neurons()/m_input_num_neurons;
175 
176  for (int32_t m=0; m<num_maps; m++)
177  {
178  SGMatrix<float64_t> W(parameters.vector+weights_index_offset,
180  SGMatrix<float64_t> WG(parameter_gradients.vector+weights_index_offset,
182  weights_index_offset += m_filter_height*m_filter_width;
183 
185  activation_gradients, WG, m*m_input_num_neurons, m_row_offset);
186 
187  if (!layer->is_input())
188  convolve(activation_gradients, W,
189  layer->get_activation_gradients(), true, false,
191  }
192 
193  SG_UNREF(layer);
194  }
195 }
196 
198  SGMatrix< float64_t > activations,
199  int32_t pooling_width, int32_t pooling_height,
200  SGMatrix< float64_t > pooled_activations,
201  SGMatrix< float64_t > max_indices)
202 {
203  int32_t result_row_offset = m_row_offset;
204  int32_t result_width = m_output_width;
205  int32_t result_height = m_output_height;
206 
208  {
209  result_row_offset /= (pooling_width*pooling_height);
210  result_width /= pooling_width;
211  result_height /= pooling_height;
212  }
213 
214  for (int32_t i=0; i<pooled_activations.num_cols; i++)
215  {
216  SGMatrix<float64_t> image(
217  activations.matrix+i*activations.num_rows + m_row_offset,
219 
220  SGMatrix<float64_t> result(
221  pooled_activations.matrix+i*pooled_activations.num_rows + result_row_offset,
222  result_height, result_width, false);
223 
224  SGMatrix<float64_t> indices(
225  max_indices.matrix+i*max_indices.num_rows + result_row_offset,
226  result_height, result_width, false);
227 
229  {
230  result.zero();
231  indices.set_const(-1.0);
232  }
233 
234  for (int32_t x=0; x<m_output_width; x+=pooling_width)
235  {
236  for (int32_t y=0; y<m_output_height; y+=pooling_height)
237  {
238  float64_t max = image(y,x);
239  int32_t max_index = m_row_offset+y+x*image.num_rows;
240 
241  for (int32_t x1=x; x1<x+pooling_width; x1++)
242  {
243  for (int32_t y1=y; y1<y+pooling_height; y1++)
244  {
245  if (image(y1,x1) > max)
246  {
247  max = image(y1,x1);
248  max_index = m_row_offset+y1+x1*image.num_rows;
249  }
250  }
251  }
253  {
254  result(y/pooling_height, x/pooling_width) = max;
255  indices(y/pooling_height, x/pooling_width) = max_index;
256  }
257  else
258  {
259  result(y, x) = max;
260  indices(y, x) = max_index;
261  }
262  }
263  }
264  }
265 }
266 
268  SGMatrix< float64_t > inputs,
269  SGMatrix< float64_t > weights,
270  SGMatrix< float64_t > outputs,
271  bool flip,
272  bool reset_output,
273  int32_t inputs_row_offset,
274  int32_t outputs_row_offset)
275 {
276  for (int32_t i=0; i<outputs.num_cols; i++)
277  {
278  SGMatrix<float64_t> image(
279  inputs.matrix+i*inputs.num_rows + inputs_row_offset,
280  m_input_height, m_input_width, false);
281 
282  SGMatrix<float64_t> result(
283  outputs.matrix+i*outputs.num_rows + outputs_row_offset,
285 
286  for (int32_t x=0; x<m_input_width; x+=m_stride_x)
287  {
288  for (int32_t y=0; y<m_input_height; y+=m_stride_y)
289  {
290  int32_t res_x = m_autoencoder_position == NLAP_NONE ? x/m_stride_x : x;
291  int32_t res_y = m_autoencoder_position == NLAP_NONE ? y/m_stride_y : y;
292 
293  float64_t sum = reset_output ? 0 : result(res_y,res_x);
294  for (int32_t x1=x-m_radius_x; x1<=x+m_radius_x; x1++)
295  {
296  for (int32_t y1=y-m_radius_y; y1<=y+m_radius_y; y1++)
297  {
298  if (x1>=0 && y1>=0 && x1<image.num_cols && y1<image.num_rows)
299  {
300  if (flip)
301  sum +=
302  weights(y1-y+m_radius_y,x1-x+m_radius_x)*image(y1,x1);
303  else
304  sum +=
305  weights(m_radius_y-y1+y,m_radius_x-x1+x)*image(y1,x1);
306  }
307  }
308  }
309  result(res_y,res_x) = sum;
310  }
311  }
312  }
313 }
314 
316  SGMatrix< float64_t > inputs,
317  SGMatrix< float64_t > local_gradients,
318  SGMatrix< float64_t > weight_gradients,
319  int32_t inputs_row_offset,
320  int32_t local_gradients_row_offset)
321 {
322  weight_gradients.zero();
323  for (int32_t i=0; i<local_gradients.num_cols; i++)
324  {
325  SGMatrix<float64_t> image(
326  inputs.matrix+i*inputs.num_rows + inputs_row_offset,
327  m_input_height, m_input_width, false);
328 
329  SGMatrix<float64_t> LG_image(
330  local_gradients.matrix+i*local_gradients.num_rows
331  + local_gradients_row_offset, m_output_height, m_output_width, false);
332 
333  for (int32_t x=0; x<m_input_width; x+=m_stride_x)
334  {
335  for (int32_t y=0; y<m_input_height; y+=m_stride_y)
336  {
337  for (int32_t x1=x-m_radius_x; x1<=x+m_radius_x; x1++)
338  {
339  for (int32_t y1=y-m_radius_y; y1<=y+m_radius_y; y1++)
340  {
341  if (x1>=0 && y1>=0 && x1<image.num_cols && y1<image.num_rows)
342  {
344  weight_gradients(m_radius_y-y1+y,m_radius_x-x1+x) +=
345  LG_image(y/m_stride_y,x/m_stride_x)*image(y1,x1);
346  else
347  weight_gradients(m_radius_y-y1+y,m_radius_x-x1+x) +=
348  LG_image(y,x)*image(y1,x1);
349  }
350  }
351  }
352  }
353  }
354  }
355 }

SHOGUN Machine Learning Toolbox - Documentation