XCSF  1.4.7
XCSF learning classifier system
neural_layer_maxpool.c
Go to the documentation of this file.
1 /*
2  * This program is free software: you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation, either version 3 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program. If not, see <http://www.gnu.org/licenses/>.
14  */
15 
24 #include "neural_layer_maxpool.h"
25 #include "neural_activations.h"
26 #include "utils.h"
27 #include <float.h>
28 
33 static void
35 {
37  l->indexes = calloc(l->n_outputs, sizeof(int));
38  l->output = calloc(l->n_outputs, sizeof(double));
39  l->delta = calloc(l->n_outputs, sizeof(double));
40 }
41 
46 static void
48 {
50  l->indexes = realloc(l->indexes, sizeof(int) * l->n_outputs);
51  l->output = realloc(l->output, sizeof(double) * l->n_outputs);
52  l->delta = realloc(l->delta, sizeof(double) * l->n_outputs);
53 }
54 
60 void
61 neural_layer_maxpool_init(struct Layer *l, const struct ArgsLayer *args)
62 {
63  l->height = args->height;
64  l->width = args->width;
65  l->channels = args->channels;
66  l->pad = args->pad;
67  l->size = args->size;
68  l->stride = args->stride;
69  l->out_w = (l->width + l->pad - l->size) / l->stride + 1;
70  l->out_h = (l->height + l->pad - l->size) / l->stride + 1;
71  l->out_c = l->channels;
72  l->n_outputs = l->out_h * l->out_w * l->out_c;
73  l->max_outputs = l->n_outputs;
74  l->n_inputs = l->height * l->width * l->channels;
76 }
77 
83 struct Layer *
84 neural_layer_maxpool_copy(const struct Layer *src)
85 {
86  if (src->type != MAXPOOL) {
87  printf("neural_layer_maxpool_copy(): incorrect source layer type\n");
88  exit(EXIT_FAILURE);
89  }
90  struct Layer *l = malloc(sizeof(struct Layer));
91  layer_defaults(l);
92  l->type = src->type;
93  l->layer_vptr = src->layer_vptr;
94  l->height = src->height;
95  l->width = src->width;
96  l->channels = src->channels;
97  l->pad = src->pad;
98  l->size = src->size;
99  l->stride = src->stride;
100  l->out_w = src->out_w;
101  l->out_h = src->out_h;
102  l->out_c = src->out_c;
103  l->n_outputs = src->n_outputs;
104  l->max_outputs = src->max_outputs;
105  l->n_inputs = src->n_inputs;
107  return l;
108 }
109 
114 void
116 {
117  free(l->indexes);
118  free(l->output);
119  free(l->delta);
120 }
121 
126 void
128 {
129  (void) l;
130 }
131 
142 static int
143 max_pool(const struct Layer *l, const double *input, const int i, const int j,
144  const int k)
145 {
146  const int w_offset = -l->pad / 2;
147  const int h_offset = w_offset;
148  double max = -DBL_MAX;
149  int max_index = -1;
150  for (int n = 0; n < l->size; ++n) {
151  for (int m = 0; m < l->size; ++m) {
152  const int cur_h = h_offset + i * l->stride + n;
153  const int cur_w = w_offset + j * l->stride + m;
154  const int index = cur_w + l->width * (cur_h + l->height * k);
155  if (cur_h >= 0 && cur_h < l->height && cur_w >= 0 &&
156  cur_w < l->width && index < l->n_inputs && input[index] > max) {
157  max_index = index;
158  max = input[index];
159  }
160  }
161  }
162  if (max_index < 0 || max_index >= l->n_inputs) {
163  printf("max_pool() error: invalid max_index: (%d)\n", max_index);
164  layer_print(l, false);
165  exit(EXIT_FAILURE);
166  }
167  return max_index;
168 }
169 
176 void
177 neural_layer_maxpool_forward(const struct Layer *l, const struct Net *net,
178  const double *input)
179 {
180  (void) net;
181  for (int k = 0; k < l->channels; ++k) {
182  for (int i = 0; i < l->out_h; ++i) {
183  for (int j = 0; j < l->out_w; ++j) {
184  const int out_index = j + l->out_w * (i + l->out_h * k);
185  if (out_index < l->n_outputs) {
186  const int max_index = max_pool(l, input, i, j, k);
187  l->indexes[out_index] = max_index;
188  l->output[out_index] = input[max_index];
189  }
190  }
191  }
192  }
193 }
194 
202 void
203 neural_layer_maxpool_backward(const struct Layer *l, const struct Net *net,
204  const double *input, double *delta)
205 {
206  (void) net;
207  (void) input;
208  if (delta) {
209  for (int i = 0; i < l->n_outputs; ++i) {
210  delta[l->indexes[i]] += l->delta[i];
211  }
212  }
213 }
214 
219 void
221 {
222  (void) l;
223 }
224 
230 bool
232 {
233  (void) l;
234  return false;
235 }
236 
242 void
243 neural_layer_maxpool_resize(struct Layer *l, const struct Layer *prev)
244 {
245  const int w = prev->out_w;
246  const int h = prev->out_h;
247  const int c = prev->out_c;
248  l->height = h;
249  l->width = w;
250  l->channels = c;
251  l->n_inputs = h * w * c;
252  l->out_w = (w + l->pad - l->size) / l->stride + 1;
253  l->out_h = (h + l->pad - l->size) / l->stride + 1;
254  l->out_c = c;
255  l->n_outputs = l->out_h * l->out_w * l->out_c;
256  l->max_outputs = l->n_outputs;
258 }
259 
265 double *
267 {
268  return l->output;
269 }
270 
276 void
277 neural_layer_maxpool_print(const struct Layer *l, const bool print_weights)
278 {
279  char *json_str = neural_layer_maxpool_json_export(l, print_weights);
280  printf("%s\n", json_str);
281  free(json_str);
282 }
283 
291 char *
293  const bool return_weights)
294 {
295  (void) return_weights;
296  cJSON *json = cJSON_CreateObject();
297  cJSON_AddStringToObject(json, "type", "maxpool");
298  cJSON_AddNumberToObject(json, "n_inputs", l->n_inputs);
299  cJSON_AddNumberToObject(json, "n_outputs", l->n_outputs);
300  cJSON_AddNumberToObject(json, "height", l->height);
301  cJSON_AddNumberToObject(json, "width", l->width);
302  cJSON_AddNumberToObject(json, "channels", l->channels);
303  cJSON_AddNumberToObject(json, "size", l->size);
304  cJSON_AddNumberToObject(json, "stride", l->stride);
305  cJSON_AddNumberToObject(json, "pad", l->pad);
306  cJSON_AddNumberToObject(json, "out_w", l->out_w);
307  cJSON_AddNumberToObject(json, "out_h", l->out_h);
308  cJSON_AddNumberToObject(json, "out_c", l->out_c);
309  char *string = cJSON_Print(json);
310  cJSON_Delete(json);
311  return string;
312 }
313 
320 size_t
321 neural_layer_maxpool_save(const struct Layer *l, FILE *fp)
322 {
323  size_t s = 0;
324  s += fwrite(&l->height, sizeof(int), 1, fp);
325  s += fwrite(&l->width, sizeof(int), 1, fp);
326  s += fwrite(&l->channels, sizeof(int), 1, fp);
327  s += fwrite(&l->pad, sizeof(int), 1, fp);
328  s += fwrite(&l->out_w, sizeof(int), 1, fp);
329  s += fwrite(&l->out_h, sizeof(int), 1, fp);
330  s += fwrite(&l->out_c, sizeof(int), 1, fp);
331  s += fwrite(&l->n_outputs, sizeof(int), 1, fp);
332  s += fwrite(&l->max_outputs, sizeof(int), 1, fp);
333  s += fwrite(&l->n_inputs, sizeof(int), 1, fp);
334  s += fwrite(&l->size, sizeof(int), 1, fp);
335  s += fwrite(&l->stride, sizeof(int), 1, fp);
336  return s;
337 }
338 
345 size_t
346 neural_layer_maxpool_load(struct Layer *l, FILE *fp)
347 {
348  size_t s = 0;
349  s += fread(&l->height, sizeof(int), 1, fp);
350  s += fread(&l->width, sizeof(int), 1, fp);
351  s += fread(&l->channels, sizeof(int), 1, fp);
352  s += fread(&l->pad, sizeof(int), 1, fp);
353  s += fread(&l->out_w, sizeof(int), 1, fp);
354  s += fread(&l->out_h, sizeof(int), 1, fp);
355  s += fread(&l->out_c, sizeof(int), 1, fp);
356  s += fread(&l->n_outputs, sizeof(int), 1, fp);
357  s += fread(&l->max_outputs, sizeof(int), 1, fp);
358  s += fread(&l->n_inputs, sizeof(int), 1, fp);
359  s += fread(&l->size, sizeof(int), 1, fp);
360  s += fread(&l->stride, sizeof(int), 1, fp);
362  return s;
363 }
Neural network activation functions.
void layer_defaults(struct Layer *l)
Initialises a layer to default values.
Definition: neural_layer.c:413
void layer_guard_outputs(const struct Layer *l)
Check number of outputs is within bounds.
Definition: neural_layer.c:595
#define MAXPOOL
Layer type maxpooling.
Definition: neural_layer.h:35
static void layer_print(const struct Layer *l, const bool print_weights)
Prints the layer.
Definition: neural_layer.h:270
static int max_pool(const struct Layer *l, const double *input, const int i, const int j, const int k)
Returns the index of the maximum input value corresponding to a specified output height,...
void neural_layer_maxpool_print(const struct Layer *l, const bool print_weights)
Prints a maxpooling layer.
void neural_layer_maxpool_init(struct Layer *l, const struct ArgsLayer *args)
Initialises a 2D maxpooling layer.
void neural_layer_maxpool_rand(struct Layer *l)
Dummy function since maxpooling layers have no weights.
void neural_layer_maxpool_resize(struct Layer *l, const struct Layer *prev)
Resizes a maxpooling layer if the previous layer has changed size.
void neural_layer_maxpool_update(const struct Layer *l)
Dummy function since a maxpooling layer has no weights.
void neural_layer_maxpool_free(const struct Layer *l)
Free memory used by a maxpooling layer.
struct Layer * neural_layer_maxpool_copy(const struct Layer *src)
Initialises and creates a copy of one maxpooling layer from another.
bool neural_layer_maxpool_mutate(struct Layer *l)
Dummy function since a maxpooling layer cannot be mutated.
double * neural_layer_maxpool_output(const struct Layer *l)
Returns the output from a maxpooling layer.
static void malloc_layer_arrays(struct Layer *l)
Allocate memory used by a maxpooling layer.
static void realloc_layer_arrays(struct Layer *l)
Resize memory used by a maxpooling layer.
char * neural_layer_maxpool_json_export(const struct Layer *l, const bool return_weights)
Returns a json formatted string representation of a maxpooling layer.
size_t neural_layer_maxpool_save(const struct Layer *l, FILE *fp)
Writes a maxpooling layer to a file.
void neural_layer_maxpool_forward(const struct Layer *l, const struct Net *net, const double *input)
Forward propagates a maxpooling layer.
size_t neural_layer_maxpool_load(struct Layer *l, FILE *fp)
Reads a maxpooling layer from a file.
void neural_layer_maxpool_backward(const struct Layer *l, const struct Net *net, const double *input, double *delta)
Backward propagates a maxpooling layer.
An implementation of a 2D maxpooling layer.
Parameters for initialising a neural network layer.
int pad
Pool and Conv.
int channels
Pool, Conv, and Upsample.
int size
Pool and Conv.
int width
Pool, Conv, and Upsample.
int height
Pool, Conv, and Upsample.
int stride
Pool, Conv, and Upsample.
Neural network layer data structure.
Definition: neural_layer.h:73
double * output
Current neuron outputs (after activation function)
Definition: neural_layer.h:76
int size
Pool and Conv.
Definition: neural_layer.h:133
int pad
Pool and Conv.
Definition: neural_layer.h:129
int stride
Pool, Conv, and Upsample.
Definition: neural_layer.h:134
int n_inputs
Number of layer inputs.
Definition: neural_layer.h:90
int channels
Pool, Conv, and Upsample.
Definition: neural_layer.h:128
double * c
LSTM.
Definition: neural_layer.h:120
int height
Pool, Conv, and Upsample.
Definition: neural_layer.h:126
struct LayerVtbl const * layer_vptr
Functions acting on layers.
Definition: neural_layer.h:100
int max_outputs
Maximum number of neurons in the layer.
Definition: neural_layer.h:92
double * h
LSTM.
Definition: neural_layer.h:121
int width
Pool, Conv, and Upsample.
Definition: neural_layer.h:127
double * i
LSTM.
Definition: neural_layer.h:117
int n_outputs
Number of layer outputs.
Definition: neural_layer.h:91
int out_w
Pool, Conv, and Upsample.
Definition: neural_layer.h:130
int type
Layer type: CONNECTED, DROPOUT, etc.
Definition: neural_layer.h:74
int out_c
Pool, Conv, and Upsample.
Definition: neural_layer.h:132
int * indexes
Pool.
Definition: neural_layer.h:135
double * delta
Delta for updating weights.
Definition: neural_layer.h:83
int out_h
Pool, Conv, and Upsample.
Definition: neural_layer.h:131
Neural network data structure.
Definition: neural.h:48
Utility functions for random number handling, etc.