SHOGUN  3.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NeuralConvolutionalLayer.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 
36 #include <shogun/lib/SGVector.h>
37 
38 using namespace shogun;
39 
41 {
42  init();
43 }
44 
47  int32_t num_maps,
48  int32_t radius_x, int32_t radius_y,
49  int32_t pooling_width, int32_t pooling_height,
50  int32_t stride_x, int32_t stride_y) : CNeuralLayer()
51 {
52  init();
53  m_num_maps = num_maps;
54  m_radius_x = radius_x;
55  m_radius_y = radius_y;
56  m_pooling_width = pooling_width;
57  m_pooling_height = pooling_height;
58  m_stride_x = stride_x;
59  m_stride_y = stride_y;
60 }
61 
63 {
64  CNeuralLayer::set_batch_size(batch_size);
65 
69  else
72 
74 
76  m_convolution_output.num_rows, m_convolution_output.num_cols);
77 }
78 
79 
81  SGVector< int32_t > input_indices)
82 {
83  CNeuralLayer* first_input_layer =
84  (CNeuralLayer*)layers->element(input_indices[0]);
85 
86  m_input_width = first_input_layer->get_width();
87  m_input_height = first_input_layer->get_height();
88 
89  SG_UNREF(first_input_layer);
90 
92  {
95  }
96  else
97  {
100  }
101 
103 
104  CNeuralLayer::initialize(layers, input_indices);
105 
107  for (int32_t l=0; l<input_indices.vlen; l++)
108  {
109  CNeuralLayer* layer =
110  (CNeuralLayer*)layers->element(input_indices[l]);
111 
113 
114  SG_UNREF(layer);
115  }
116 
117  // one bias for each map and one weight matrix between each map in this
118  // layer and each channel in the input layers
120  m_num_maps*(1 + m_input_num_channels*(2*m_radius_x+1)*(2*m_radius_y+1));
121 }
122 
124  SGVector<bool> parameter_regularizable,
125  float64_t sigma)
126 {
127  int32_t num_parameters_per_map =
129 
130  for (int32_t m=0; m<m_num_maps; m++)
131  {
132  float64_t* map_params = parameters.vector+m*num_parameters_per_map;
133  bool* map_param_regularizable =
134  parameter_regularizable.vector+m*num_parameters_per_map;
135 
136  for (int32_t i=0; i<num_parameters_per_map; i++)
137  {
138  map_params[i] = CMath::normal_random(0.0, sigma);
139 
140  // turn off regularization for the bias, on for the rest of the parameters
141  map_param_regularizable[i] = (i != 0);
142  }
143  }
144 }
145 
147  SGVector<float64_t> parameters,
148  CDynamicObjectArray* layers)
149 {
150  int32_t num_parameters_per_map =
152 
153  for (int32_t m=0; m<m_num_maps; m++)
154  {
155  SGVector<float64_t> map_params(
156  parameters.vector+m*num_parameters_per_map,
157  num_parameters_per_map, false);
158 
162 
163  map.compute_activations(map_params, layers, m_input_indices,
165 
168  }
169 }
170 
172  SGVector<float64_t> parameters,
173  SGMatrix<float64_t> targets,
174  CDynamicObjectArray* layers,
175  SGVector<float64_t> parameter_gradients)
176 {
177  if (targets.num_rows != 0)
178  {
179  // sqaured error measure
180  // local_gradients = activations-targets
181  int32_t length = m_num_neurons*m_batch_size;
182  for (int32_t i=0; i<length; i++)
184  }
185 
186  if (dropout_prop>0.0)
187  {
188  int32_t len = m_num_neurons*m_batch_size;
189  for (int32_t i=0; i<len; i++)
191  }
192 
193  // compute the pre-pooling activation gradients
195  for (int32_t i=0; i<m_num_neurons; i++)
196  for (int32_t j=0; j<m_batch_size; j++)
197  if (m_max_indices(i,j)!=-1.0)
200 
201  int32_t num_parameters_per_map =
203 
204  for (int32_t m=0; m<m_num_maps; m++)
205  {
206  SGVector<float64_t> map_params(
207  parameters.vector+m*num_parameters_per_map,
208  num_parameters_per_map, false);
209 
210  SGVector<float64_t> map_gradients(
211  parameter_gradients.vector+m*num_parameters_per_map,
212  num_parameters_per_map, false);
213 
217 
218  map.compute_gradients(map_params, m_convolution_output,
220  m_input_indices, map_gradients);
221  }
222 }
223 
225 {
226  // error = 0.5*(sum(targets-activations)^2)/batch_size
227  float64_t sum = 0;
228  int32_t length = m_num_neurons*m_batch_size;
229  for (int32_t i=0; i<length; i++)
230  sum += (targets[i]-m_activations[i])*(targets[i]-m_activations[i]);
231  sum *= (0.5/m_batch_size);
232  return sum;
233 }
234 
236  float64_t max_norm)
237 {
238  int32_t num_weights = (2*m_radius_x+1)*(2*m_radius_y+1);
239 
240  int32_t num_parameters_per_map = 1 + m_input_num_channels*num_weights;
241 
242  for (int32_t offset=1; offset<parameters.vlen; offset+=num_parameters_per_map)
243  {
244  float64_t* weights = parameters.vector+offset;
245 
246  float64_t norm =
247  SGVector<float64_t>::twonorm(weights, num_weights);
248 
249  if (norm > max_norm)
250  {
251  float64_t multiplier = max_norm/norm;
252  for (int32_t i=0; i<num_weights; i++)
253  weights[i] *= multiplier;
254  }
255  }
256 }
257 
258 void CNeuralConvolutionalLayer::init()
259 {
260  m_num_maps = 1;
261  m_input_width = 0;
262  m_input_height = 0;
264  m_radius_x = 0;
265  m_radius_y = 0;
266  m_pooling_width = 1;
267  m_pooling_height = 1;
268  m_stride_x = 1;
269  m_stride_y = 1;
271 
272  SG_ADD(&m_num_maps, "num_maps", "Number of maps", MS_NOT_AVAILABLE);
273  SG_ADD(&m_input_width, "input_width", "Input Width", MS_NOT_AVAILABLE);
274  SG_ADD(&m_input_height, "input_height", "Input Height", MS_NOT_AVAILABLE);
275  SG_ADD(&m_input_num_channels, "input_num_channels", "Input's number of channels",
277  SG_ADD(&m_radius_x, "radius_x", "X Radius", MS_NOT_AVAILABLE);
278  SG_ADD(&m_radius_y, "radius_y", "Y Radius", MS_NOT_AVAILABLE);
279  SG_ADD(&m_pooling_width, "pooling_width", "Pooling Width", MS_NOT_AVAILABLE);
280  SG_ADD(&m_pooling_height, "pooling_height", "Pooling Height", MS_NOT_AVAILABLE);
281  SG_ADD(&m_stride_x, "stride_x", "X Stride", MS_NOT_AVAILABLE);
282  SG_ADD(&m_stride_y, "stride_y", "Y Stride", MS_NOT_AVAILABLE);
283  SG_ADD((machine_int_t*) &m_activation_function, "activation_function",
284  "Activation Function", MS_NOT_AVAILABLE);
285 
286  SG_ADD(&m_convolution_output, "convolution_output",
287  "Convolution Output", MS_NOT_AVAILABLE);
288 
289  SG_ADD(&m_convolution_output_gradients, "convolution_output_gradients",
290  "Convolution Output Gradients", MS_NOT_AVAILABLE);
291 }

SHOGUN Machine Learning Toolbox - Documentation