moo_fann 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,100 @@
1
+ /*
2
+ Fast Artificial Neural Network Library (fann)
3
+ Copyright (C) 2003-2012 Steffen Nissen (sn@leenissen.dk)
4
+
5
+ This library is free software; you can redistribute it and/or
6
+ modify it under the terms of the GNU Lesser General Public
7
+ License as published by the Free Software Foundation; either
8
+ version 2.1 of the License, or (at your option) any later version.
9
+
10
+ This library is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public
16
+ License along with this library; if not, write to the Free Software
17
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ */
19
+
20
+ #ifndef __fann_io_h__
21
+ #define __fann_io_h__
22
+
23
+ /* Section: FANN File Input/Output
24
+
25
+ It is possible to save an entire ann to a file with <fann_save> for future loading with <fann_create_from_file>.
26
+ */
27
+
28
+ /* Group: File Input and Output */
29
+
30
+ /* Function: fann_create_from_file
31
+
32
+ Constructs a backpropagation neural network from a configuration file, which have been saved by <fann_save>.
33
+
34
+ See also:
35
+ <fann_save>, <fann_save_to_fixed>
36
+
37
+ This function appears in FANN >= 1.0.0.
38
+ */
39
+ FANN_EXTERNAL struct fann *FANN_API fann_create_from_file(const char *configuration_file);
40
+
41
+
42
+ /* Function: fann_save
43
+
44
+ Save the entire network to a configuration file.
45
+
46
+ The configuration file contains all information about the neural network and enables
47
+ <fann_create_from_file> to create an exact copy of the neural network and all of the
48
+ parameters associated with the neural network.
49
+
50
+ These three parameters (<fann_set_callback>, <fann_set_error_log>,
51
+ <fann_set_user_data>) are *NOT* saved to the file because they cannot safely be
52
+ ported to a different location. Also temporary parameters generated during training
53
+ like <fann_get_MSE> is not saved.
54
+
55
+ Return:
56
+ The function returns 0 on success and -1 on failure.
57
+
58
+ See also:
59
+ <fann_create_from_file>, <fann_save_to_fixed>
60
+
61
+ This function appears in FANN >= 1.0.0.
62
+ */
63
+ FANN_EXTERNAL int FANN_API fann_save(struct fann *ann, const char *configuration_file);
64
+
65
+
66
+ /* Function: fann_save_to_fixed
67
+
68
+ Saves the entire network to a configuration file.
69
+ But it is saved in fixed point format no matter which
70
+ format it is currently in.
71
+
72
+ This is usefull for training a network in floating points,
73
+ and then later executing it in fixed point.
74
+
75
+ The function returns the bit position of the fix point, which
76
+ can be used to find out how accurate the fixed point network will be.
77
+ A high value indicates high precision, and a low value indicates low
78
+ precision.
79
+
80
+ A negative value indicates very low precision, and a very
81
+ strong possibility for overflow.
82
+ (the actual fix point will be set to 0, since a negative
83
+ fix point does not make sence).
84
+
85
+ Generally, a fix point lower than 6 is bad, and should be avoided.
86
+ The best way to avoid this, is to have less connections to each neuron,
87
+ or just less neurons in each layer.
88
+
89
+ The fixed point use of this network is only intended for use on machines that
90
+ have no floating point processor, like an iPAQ. On normal computers the floating
91
+ point version is actually faster.
92
+
93
+ See also:
94
+ <fann_create_from_file>, <fann_save>
95
+
96
+ This function appears in FANN >= 1.0.0.
97
+ */
98
+ FANN_EXTERNAL int FANN_API fann_save_to_fixed(struct fann *ann, const char *configuration_file);
99
+
100
+ #endif
@@ -0,0 +1,1047 @@
1
+ /*
2
+ Fast Artificial Neural Network Library (fann)
3
+ Copyright (C) 2003-2012 Steffen Nissen (sn@leenissen.dk)
4
+
5
+ This library is free software; you can redistribute it and/or
6
+ modify it under the terms of the GNU Lesser General Public
7
+ License as published by the Free Software Foundation; either
8
+ version 2.1 of the License, or (at your option) any later version.
9
+
10
+ This library is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public
16
+ License along with this library; if not, write to the Free Software
17
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ */
19
+
20
+ #include <stdio.h>
21
+ #include <stdlib.h>
22
+ #include <stdarg.h>
23
+ #include <string.h>
24
+ #include <math.h>
25
+
26
+ #include "config.h"
27
+ #include "fann.h"
28
+
29
+ /*#define DEBUGTRAIN*/
30
+
31
+ #ifndef FIXEDFANN
32
+ /* INTERNAL FUNCTION
33
+ Calculates the derived of a value, given an activation function
34
+ and a steepness
35
+ */
36
+ fann_type fann_activation_derived(unsigned int activation_function,
37
+ fann_type steepness, fann_type value, fann_type sum)
38
+ {
39
+ switch (activation_function)
40
+ {
41
+ case FANN_LINEAR:
42
+ case FANN_LINEAR_PIECE:
43
+ case FANN_LINEAR_PIECE_SYMMETRIC:
44
+ return (fann_type) fann_linear_derive(steepness, value);
45
+ case FANN_SIGMOID:
46
+ case FANN_SIGMOID_STEPWISE:
47
+ value = fann_clip(value, 0.01f, 0.99f);
48
+ return (fann_type) fann_sigmoid_derive(steepness, value);
49
+ case FANN_SIGMOID_SYMMETRIC:
50
+ case FANN_SIGMOID_SYMMETRIC_STEPWISE:
51
+ value = fann_clip(value, -0.98f, 0.98f);
52
+ return (fann_type) fann_sigmoid_symmetric_derive(steepness, value);
53
+ case FANN_GAUSSIAN:
54
+ /* value = fann_clip(value, 0.01f, 0.99f); */
55
+ return (fann_type) fann_gaussian_derive(steepness, value, sum);
56
+ case FANN_GAUSSIAN_SYMMETRIC:
57
+ /* value = fann_clip(value, -0.98f, 0.98f); */
58
+ return (fann_type) fann_gaussian_symmetric_derive(steepness, value, sum);
59
+ case FANN_ELLIOT:
60
+ value = fann_clip(value, 0.01f, 0.99f);
61
+ return (fann_type) fann_elliot_derive(steepness, value, sum);
62
+ case FANN_ELLIOT_SYMMETRIC:
63
+ value = fann_clip(value, -0.98f, 0.98f);
64
+ return (fann_type) fann_elliot_symmetric_derive(steepness, value, sum);
65
+ case FANN_SIN_SYMMETRIC:
66
+ return (fann_type) fann_sin_symmetric_derive(steepness, sum);
67
+ case FANN_COS_SYMMETRIC:
68
+ return (fann_type) fann_cos_symmetric_derive(steepness, sum);
69
+ case FANN_SIN:
70
+ return (fann_type) fann_sin_derive(steepness, sum);
71
+ case FANN_COS:
72
+ return (fann_type) fann_cos_derive(steepness, sum);
73
+ case FANN_THRESHOLD:
74
+ fann_error(NULL, FANN_E_CANT_TRAIN_ACTIVATION);
75
+ }
76
+ return 0;
77
+ }
78
+
79
+ /* INTERNAL FUNCTION
80
+ Calculates the activation of a value, given an activation function
81
+ and a steepness
82
+ */
83
+ fann_type fann_activation(struct fann * ann, unsigned int activation_function, fann_type steepness,
84
+ fann_type value)
85
+ {
86
+ value = fann_mult(steepness, value);
87
+ fann_activation_switch(activation_function, value, value);
88
+ return value;
89
+ }
90
+
91
+ /* Trains the network with the backpropagation algorithm.
92
+ */
93
+ FANN_EXTERNAL void FANN_API fann_train(struct fann *ann, fann_type * input,
94
+ fann_type * desired_output)
95
+ {
96
+ fann_run(ann, input);
97
+
98
+ fann_compute_MSE(ann, desired_output);
99
+
100
+ fann_backpropagate_MSE(ann);
101
+
102
+ fann_update_weights(ann);
103
+ }
104
+ #endif
105
+
106
+
107
+ /* INTERNAL FUNCTION
108
+ Helper function to update the MSE value and return a diff which takes symmetric functions into account
109
+ */
110
+ fann_type fann_update_MSE(struct fann *ann, struct fann_neuron* neuron, fann_type neuron_diff)
111
+ {
112
+ float neuron_diff2;
113
+
114
+ switch (neuron->activation_function)
115
+ {
116
+ case FANN_LINEAR_PIECE_SYMMETRIC:
117
+ case FANN_THRESHOLD_SYMMETRIC:
118
+ case FANN_SIGMOID_SYMMETRIC:
119
+ case FANN_SIGMOID_SYMMETRIC_STEPWISE:
120
+ case FANN_ELLIOT_SYMMETRIC:
121
+ case FANN_GAUSSIAN_SYMMETRIC:
122
+ case FANN_SIN_SYMMETRIC:
123
+ case FANN_COS_SYMMETRIC:
124
+ neuron_diff /= (fann_type)2.0;
125
+ break;
126
+ case FANN_THRESHOLD:
127
+ case FANN_LINEAR:
128
+ case FANN_SIGMOID:
129
+ case FANN_SIGMOID_STEPWISE:
130
+ case FANN_GAUSSIAN:
131
+ case FANN_GAUSSIAN_STEPWISE:
132
+ case FANN_ELLIOT:
133
+ case FANN_LINEAR_PIECE:
134
+ case FANN_SIN:
135
+ case FANN_COS:
136
+ break;
137
+ }
138
+
139
+ #ifdef FIXEDFANN
140
+ neuron_diff2 =
141
+ (neuron_diff / (float) ann->multiplier) * (neuron_diff / (float) ann->multiplier);
142
+ #else
143
+ neuron_diff2 = (float) (neuron_diff * neuron_diff);
144
+ #endif
145
+
146
+ ann->MSE_value += neuron_diff2;
147
+
148
+ /*printf("neuron_diff %f = (%f - %f)[/2], neuron_diff2=%f, sum=%f, MSE_value=%f, num_MSE=%d\n", neuron_diff, *desired_output, neuron_value, neuron_diff2, last_layer_begin->sum, ann->MSE_value, ann->num_MSE); */
149
+ if(fann_abs(neuron_diff) >= ann->bit_fail_limit)
150
+ {
151
+ ann->num_bit_fail++;
152
+ }
153
+
154
+ return neuron_diff;
155
+ }
156
+
157
+ /* Tests the network.
158
+ */
159
+ FANN_EXTERNAL fann_type *FANN_API fann_test(struct fann *ann, fann_type * input,
160
+ fann_type * desired_output)
161
+ {
162
+ fann_type neuron_value;
163
+ fann_type *output_begin = fann_run(ann, input);
164
+ fann_type *output_it;
165
+ const fann_type *output_end = output_begin + ann->num_output;
166
+ fann_type neuron_diff;
167
+ struct fann_neuron *output_neuron = (ann->last_layer - 1)->first_neuron;
168
+
169
+ /* calculate the error */
170
+ for(output_it = output_begin; output_it != output_end; output_it++)
171
+ {
172
+ neuron_value = *output_it;
173
+
174
+ neuron_diff = (*desired_output - neuron_value);
175
+
176
+ neuron_diff = fann_update_MSE(ann, output_neuron, neuron_diff);
177
+
178
+ desired_output++;
179
+ output_neuron++;
180
+
181
+ ann->num_MSE++;
182
+ }
183
+
184
+ return output_begin;
185
+ }
186
+
187
+ /* get the mean square error.
188
+ */
189
+ FANN_EXTERNAL float FANN_API fann_get_MSE(struct fann *ann)
190
+ {
191
+ if(ann->num_MSE)
192
+ {
193
+ return ann->MSE_value / (float) ann->num_MSE;
194
+ }
195
+ else
196
+ {
197
+ return 0;
198
+ }
199
+ }
200
+
201
+ FANN_EXTERNAL unsigned int FANN_API fann_get_bit_fail(struct fann *ann)
202
+ {
203
+ return ann->num_bit_fail;
204
+ }
205
+
206
+ /* reset the mean square error.
207
+ */
208
+ FANN_EXTERNAL void FANN_API fann_reset_MSE(struct fann *ann)
209
+ {
210
+ /*printf("resetMSE %d %f\n", ann->num_MSE, ann->MSE_value);*/
211
+ ann->num_MSE = 0;
212
+ ann->MSE_value = 0;
213
+ ann->num_bit_fail = 0;
214
+ }
215
+
216
+ #ifndef FIXEDFANN
217
+
218
+ /* INTERNAL FUNCTION
219
+ compute the error at the network output
220
+ (usually, after forward propagation of a certain input vector, fann_run)
221
+ the error is a sum of squares for all the output units
222
+ also increments a counter because MSE is an average of such errors
223
+
224
+ After this train_errors in the output layer will be set to:
225
+ neuron_value_derived * (desired_output - neuron_value)
226
+ */
227
+ void fann_compute_MSE(struct fann *ann, fann_type * desired_output)
228
+ {
229
+ fann_type neuron_value, neuron_diff, *error_it = 0, *error_begin = 0;
230
+ struct fann_neuron *last_layer_begin = (ann->last_layer - 1)->first_neuron;
231
+ const struct fann_neuron *last_layer_end = last_layer_begin + ann->num_output;
232
+ const struct fann_neuron *first_neuron = ann->first_layer->first_neuron;
233
+
234
+ /* if no room allocated for the error variabels, allocate it now */
235
+ if(ann->train_errors == NULL)
236
+ {
237
+ ann->train_errors = (fann_type *) calloc(ann->total_neurons, sizeof(fann_type));
238
+ if(ann->train_errors == NULL)
239
+ {
240
+ fann_error((struct fann_error *) ann, FANN_E_CANT_ALLOCATE_MEM);
241
+ return;
242
+ }
243
+ }
244
+ else
245
+ {
246
+ /* clear the error variabels */
247
+ memset(ann->train_errors, 0, (ann->total_neurons) * sizeof(fann_type));
248
+ }
249
+ error_begin = ann->train_errors;
250
+
251
+ #ifdef DEBUGTRAIN
252
+ printf("\ncalculate errors\n");
253
+ #endif
254
+ /* calculate the error and place it in the output layer */
255
+ error_it = error_begin + (last_layer_begin - first_neuron);
256
+
257
+ for(; last_layer_begin != last_layer_end; last_layer_begin++)
258
+ {
259
+ neuron_value = last_layer_begin->value;
260
+ neuron_diff = *desired_output - neuron_value;
261
+
262
+ neuron_diff = fann_update_MSE(ann, last_layer_begin, neuron_diff);
263
+
264
+ if(ann->train_error_function)
265
+ { /* TODO make switch when more functions */
266
+ if(neuron_diff < -.9999999)
267
+ neuron_diff = -17.0;
268
+ else if(neuron_diff > .9999999)
269
+ neuron_diff = 17.0;
270
+ else
271
+ neuron_diff = (fann_type) log((1.0 + neuron_diff) / (1.0 - neuron_diff));
272
+ }
273
+
274
+ *error_it = fann_activation_derived(last_layer_begin->activation_function,
275
+ last_layer_begin->activation_steepness, neuron_value,
276
+ last_layer_begin->sum) * neuron_diff;
277
+
278
+ desired_output++;
279
+ error_it++;
280
+
281
+ ann->num_MSE++;
282
+ }
283
+ }
284
+
285
+ /* INTERNAL FUNCTION
286
+ Propagate the error backwards from the output layer.
287
+
288
+ After this the train_errors in the hidden layers will be:
289
+ neuron_value_derived * sum(outgoing_weights * connected_neuron)
290
+ */
291
+ void fann_backpropagate_MSE(struct fann *ann)
292
+ {
293
+ fann_type tmp_error;
294
+ unsigned int i;
295
+ struct fann_layer *layer_it;
296
+ struct fann_neuron *neuron_it, *last_neuron;
297
+ struct fann_neuron **connections;
298
+
299
+ fann_type *error_begin = ann->train_errors;
300
+ fann_type *error_prev_layer;
301
+ fann_type *weights;
302
+ const struct fann_neuron *first_neuron = ann->first_layer->first_neuron;
303
+ const struct fann_layer *second_layer = ann->first_layer + 1;
304
+ struct fann_layer *last_layer = ann->last_layer;
305
+
306
+ /* go through all the layers, from last to first.
307
+ * And propagate the error backwards */
308
+ for(layer_it = last_layer - 1; layer_it > second_layer; --layer_it)
309
+ {
310
+ last_neuron = layer_it->last_neuron;
311
+
312
+ /* for each connection in this layer, propagate the error backwards */
313
+ if(ann->connection_rate >= 1)
314
+ {
315
+ if(ann->network_type == FANN_NETTYPE_LAYER)
316
+ {
317
+ error_prev_layer = error_begin + ((layer_it - 1)->first_neuron - first_neuron);
318
+ }
319
+ else
320
+ {
321
+ error_prev_layer = error_begin;
322
+ }
323
+
324
+ for(neuron_it = layer_it->first_neuron; neuron_it != last_neuron; neuron_it++)
325
+ {
326
+
327
+ tmp_error = error_begin[neuron_it - first_neuron];
328
+ weights = ann->weights + neuron_it->first_con;
329
+ for(i = neuron_it->last_con - neuron_it->first_con; i--;)
330
+ {
331
+ /*printf("i = %d\n", i);
332
+ * printf("error_prev_layer[%d] = %f\n", i, error_prev_layer[i]);
333
+ * printf("weights[%d] = %f\n", i, weights[i]); */
334
+ error_prev_layer[i] += tmp_error * weights[i];
335
+ }
336
+ }
337
+ }
338
+ else
339
+ {
340
+ for(neuron_it = layer_it->first_neuron; neuron_it != last_neuron; neuron_it++)
341
+ {
342
+
343
+ tmp_error = error_begin[neuron_it - first_neuron];
344
+ weights = ann->weights + neuron_it->first_con;
345
+ connections = ann->connections + neuron_it->first_con;
346
+ for(i = neuron_it->last_con - neuron_it->first_con; i--;)
347
+ {
348
+ error_begin[connections[i] - first_neuron] += tmp_error * weights[i];
349
+ }
350
+ }
351
+ }
352
+
353
+ /* then calculate the actual errors in the previous layer */
354
+ error_prev_layer = error_begin + ((layer_it - 1)->first_neuron - first_neuron);
355
+ last_neuron = (layer_it - 1)->last_neuron;
356
+
357
+ for(neuron_it = (layer_it - 1)->first_neuron; neuron_it != last_neuron; neuron_it++)
358
+ {
359
+ *error_prev_layer *= fann_activation_derived(neuron_it->activation_function,
360
+ neuron_it->activation_steepness, neuron_it->value, neuron_it->sum);
361
+ error_prev_layer++;
362
+ }
363
+
364
+ }
365
+ }
366
+
367
+ /* INTERNAL FUNCTION
368
+ Update weights for incremental training
369
+ */
370
+ void fann_update_weights(struct fann *ann)
371
+ {
372
+ struct fann_neuron *neuron_it, *last_neuron, *prev_neurons;
373
+ fann_type tmp_error, delta_w, *weights;
374
+ struct fann_layer *layer_it;
375
+ unsigned int i;
376
+ unsigned int num_connections;
377
+
378
+ /* store some variabels local for fast access */
379
+ const float learning_rate = ann->learning_rate;
380
+ const float learning_momentum = ann->learning_momentum;
381
+ struct fann_neuron *first_neuron = ann->first_layer->first_neuron;
382
+ struct fann_layer *first_layer = ann->first_layer;
383
+ const struct fann_layer *last_layer = ann->last_layer;
384
+ fann_type *error_begin = ann->train_errors;
385
+ fann_type *deltas_begin, *weights_deltas;
386
+
387
+ /* if no room allocated for the deltas, allocate it now */
388
+ if(ann->prev_weights_deltas == NULL)
389
+ {
390
+ ann->prev_weights_deltas =
391
+ (fann_type *) calloc(ann->total_connections_allocated, sizeof(fann_type));
392
+ if(ann->prev_weights_deltas == NULL)
393
+ {
394
+ fann_error((struct fann_error *) ann, FANN_E_CANT_ALLOCATE_MEM);
395
+ return;
396
+ }
397
+ }
398
+
399
+ #ifdef DEBUGTRAIN
400
+ printf("\nupdate weights\n");
401
+ #endif
402
+ deltas_begin = ann->prev_weights_deltas;
403
+ prev_neurons = first_neuron;
404
+ for(layer_it = (first_layer + 1); layer_it != last_layer; layer_it++)
405
+ {
406
+ #ifdef DEBUGTRAIN
407
+ printf("layer[%d]\n", layer_it - first_layer);
408
+ #endif
409
+ last_neuron = layer_it->last_neuron;
410
+ if(ann->connection_rate >= 1)
411
+ {
412
+ if(ann->network_type == FANN_NETTYPE_LAYER)
413
+ {
414
+ prev_neurons = (layer_it - 1)->first_neuron;
415
+ }
416
+ for(neuron_it = layer_it->first_neuron; neuron_it != last_neuron; neuron_it++)
417
+ {
418
+ tmp_error = error_begin[neuron_it - first_neuron] * learning_rate;
419
+ num_connections = neuron_it->last_con - neuron_it->first_con;
420
+ weights = ann->weights + neuron_it->first_con;
421
+ weights_deltas = deltas_begin + neuron_it->first_con;
422
+ for(i = 0; i != num_connections; i++)
423
+ {
424
+ delta_w = tmp_error * prev_neurons[i].value + learning_momentum * weights_deltas[i];
425
+ weights[i] += delta_w ;
426
+ weights_deltas[i] = delta_w;
427
+ }
428
+ }
429
+ }
430
+ else
431
+ {
432
+ for(neuron_it = layer_it->first_neuron; neuron_it != last_neuron; neuron_it++)
433
+ {
434
+ tmp_error = error_begin[neuron_it - first_neuron] * learning_rate;
435
+ num_connections = neuron_it->last_con - neuron_it->first_con;
436
+ weights = ann->weights + neuron_it->first_con;
437
+ weights_deltas = deltas_begin + neuron_it->first_con;
438
+ for(i = 0; i != num_connections; i++)
439
+ {
440
+ delta_w = tmp_error * prev_neurons[i].value + learning_momentum * weights_deltas[i];
441
+ weights[i] += delta_w;
442
+ weights_deltas[i] = delta_w;
443
+ }
444
+ }
445
+ }
446
+ }
447
+ }
448
+
449
+ /* INTERNAL FUNCTION
450
+ Update slopes for batch training
451
+ layer_begin = ann->first_layer+1 and layer_end = ann->last_layer-1
452
+ will update all slopes.
453
+
454
+ */
455
+ void fann_update_slopes_batch(struct fann *ann, struct fann_layer *layer_begin,
456
+ struct fann_layer *layer_end)
457
+ {
458
+ struct fann_neuron *neuron_it, *last_neuron, *prev_neurons, **connections;
459
+ fann_type tmp_error;
460
+ unsigned int i, num_connections;
461
+
462
+ /* store some variabels local for fast access */
463
+ struct fann_neuron *first_neuron = ann->first_layer->first_neuron;
464
+ fann_type *error_begin = ann->train_errors;
465
+ fann_type *slope_begin, *neuron_slope;
466
+
467
+ /* if no room allocated for the slope variabels, allocate it now */
468
+ if(ann->train_slopes == NULL)
469
+ {
470
+ ann->train_slopes =
471
+ (fann_type *) calloc(ann->total_connections_allocated, sizeof(fann_type));
472
+ if(ann->train_slopes == NULL)
473
+ {
474
+ fann_error((struct fann_error *) ann, FANN_E_CANT_ALLOCATE_MEM);
475
+ return;
476
+ }
477
+ }
478
+
479
+ if(layer_begin == NULL)
480
+ {
481
+ layer_begin = ann->first_layer + 1;
482
+ }
483
+
484
+ if(layer_end == NULL)
485
+ {
486
+ layer_end = ann->last_layer - 1;
487
+ }
488
+
489
+ slope_begin = ann->train_slopes;
490
+
491
+ #ifdef DEBUGTRAIN
492
+ printf("\nupdate slopes\n");
493
+ #endif
494
+
495
+ prev_neurons = first_neuron;
496
+
497
+ for(; layer_begin <= layer_end; layer_begin++)
498
+ {
499
+ #ifdef DEBUGTRAIN
500
+ printf("layer[%d]\n", layer_begin - ann->first_layer);
501
+ #endif
502
+ last_neuron = layer_begin->last_neuron;
503
+ if(ann->connection_rate >= 1)
504
+ {
505
+ if(ann->network_type == FANN_NETTYPE_LAYER)
506
+ {
507
+ prev_neurons = (layer_begin - 1)->first_neuron;
508
+ }
509
+
510
+ for(neuron_it = layer_begin->first_neuron; neuron_it != last_neuron; neuron_it++)
511
+ {
512
+ tmp_error = error_begin[neuron_it - first_neuron];
513
+ neuron_slope = slope_begin + neuron_it->first_con;
514
+ num_connections = neuron_it->last_con - neuron_it->first_con;
515
+ for(i = 0; i != num_connections; i++)
516
+ {
517
+ neuron_slope[i] += tmp_error * prev_neurons[i].value;
518
+ }
519
+ }
520
+ }
521
+ else
522
+ {
523
+ for(neuron_it = layer_begin->first_neuron; neuron_it != last_neuron; neuron_it++)
524
+ {
525
+ tmp_error = error_begin[neuron_it - first_neuron];
526
+ neuron_slope = slope_begin + neuron_it->first_con;
527
+ num_connections = neuron_it->last_con - neuron_it->first_con;
528
+ connections = ann->connections + neuron_it->first_con;
529
+ for(i = 0; i != num_connections; i++)
530
+ {
531
+ neuron_slope[i] += tmp_error * connections[i]->value;
532
+ }
533
+ }
534
+ }
535
+ }
536
+ }
537
+
538
+ /* INTERNAL FUNCTION
539
+ Clears arrays used for training before a new training session.
540
+ Also creates the arrays that do not exist yet.
541
+ */
542
+ void fann_clear_train_arrays(struct fann *ann)
543
+ {
544
+ unsigned int i;
545
+ fann_type delta_zero;
546
+
547
+ /* if no room allocated for the slope variabels, allocate it now
548
+ * (calloc clears mem) */
549
+ if(ann->train_slopes == NULL)
550
+ {
551
+ ann->train_slopes =
552
+ (fann_type *) calloc(ann->total_connections_allocated, sizeof(fann_type));
553
+ if(ann->train_slopes == NULL)
554
+ {
555
+ fann_error((struct fann_error *) ann, FANN_E_CANT_ALLOCATE_MEM);
556
+ return;
557
+ }
558
+ }
559
+ else
560
+ {
561
+ memset(ann->train_slopes, 0, (ann->total_connections_allocated) * sizeof(fann_type));
562
+ }
563
+
564
+ /* if no room allocated for the variabels, allocate it now */
565
+ if(ann->prev_steps == NULL)
566
+ {
567
+ ann->prev_steps = (fann_type *) malloc(ann->total_connections_allocated * sizeof(fann_type));
568
+ if(ann->prev_steps == NULL)
569
+ {
570
+ fann_error((struct fann_error *) ann, FANN_E_CANT_ALLOCATE_MEM);
571
+ return;
572
+ }
573
+ }
574
+
575
+ if(ann->training_algorithm == FANN_TRAIN_RPROP)
576
+ {
577
+ delta_zero = ann->rprop_delta_zero;
578
+
579
+ for(i = 0; i < ann->total_connections_allocated; i++)
580
+ ann->prev_steps[i] = delta_zero;
581
+ }
582
+ else
583
+ {
584
+ memset(ann->prev_steps, 0, (ann->total_connections_allocated) * sizeof(fann_type));
585
+ }
586
+
587
+ /* if no room allocated for the variabels, allocate it now */
588
+ if(ann->prev_train_slopes == NULL)
589
+ {
590
+ ann->prev_train_slopes =
591
+ (fann_type *) calloc(ann->total_connections_allocated, sizeof(fann_type));
592
+ if(ann->prev_train_slopes == NULL)
593
+ {
594
+ fann_error((struct fann_error *) ann, FANN_E_CANT_ALLOCATE_MEM);
595
+ return;
596
+ }
597
+ }
598
+ else
599
+ {
600
+ memset(ann->prev_train_slopes, 0, (ann->total_connections_allocated) * sizeof(fann_type));
601
+ }
602
+ }
603
+
604
+ /* INTERNAL FUNCTION
605
+ Update weights for batch training
606
+ */
607
+ void fann_update_weights_batch(struct fann *ann, unsigned int num_data, unsigned int first_weight,
608
+ unsigned int past_end)
609
+ {
610
+ fann_type *train_slopes = ann->train_slopes;
611
+ fann_type *weights = ann->weights;
612
+ const float epsilon = ann->learning_rate / num_data;
613
+ unsigned int i = first_weight;
614
+
615
+ for(; i != past_end; i++)
616
+ {
617
+ weights[i] += train_slopes[i] * epsilon;
618
+ train_slopes[i] = 0.0;
619
+ }
620
+ }
621
+
622
+ /* INTERNAL FUNCTION
623
+ The quickprop training algorithm
624
+ */
625
+ void fann_update_weights_quickprop(struct fann *ann, unsigned int num_data,
626
+ unsigned int first_weight, unsigned int past_end)
627
+ {
628
+ fann_type *train_slopes = ann->train_slopes;
629
+ fann_type *weights = ann->weights;
630
+ fann_type *prev_steps = ann->prev_steps;
631
+ fann_type *prev_train_slopes = ann->prev_train_slopes;
632
+
633
+ fann_type w, prev_step, slope, prev_slope, next_step;
634
+
635
+ float epsilon = ann->learning_rate / num_data;
636
+ float decay = ann->quickprop_decay; /*-0.0001;*/
637
+ float mu = ann->quickprop_mu; /*1.75; */
638
+ float shrink_factor = (float) (mu / (1.0 + mu));
639
+
640
+ unsigned int i = first_weight;
641
+
642
+ for(; i != past_end; i++)
643
+ {
644
+ w = weights[i];
645
+ prev_step = prev_steps[i];
646
+ slope = train_slopes[i] + decay * w;
647
+ prev_slope = prev_train_slopes[i];
648
+ next_step = 0.0;
649
+
650
+ /* The step must always be in direction opposite to the slope. */
651
+ if(prev_step > 0.001)
652
+ {
653
+ /* If last step was positive... */
654
+ if(slope > 0.0) /* Add in linear term if current slope is still positive. */
655
+ next_step += epsilon * slope;
656
+
657
+ /*If current slope is close to or larger than prev slope... */
658
+ if(slope > (shrink_factor * prev_slope))
659
+ next_step += mu * prev_step; /* Take maximum size negative step. */
660
+ else
661
+ next_step += prev_step * slope / (prev_slope - slope); /* Else, use quadratic estimate. */
662
+ }
663
+ else if(prev_step < -0.001)
664
+ {
665
+ /* If last step was negative... */
666
+ if(slope < 0.0) /* Add in linear term if current slope is still negative. */
667
+ next_step += epsilon * slope;
668
+
669
+ /* If current slope is close to or more neg than prev slope... */
670
+ if(slope < (shrink_factor * prev_slope))
671
+ next_step += mu * prev_step; /* Take maximum size negative step. */
672
+ else
673
+ next_step += prev_step * slope / (prev_slope - slope); /* Else, use quadratic estimate. */
674
+ }
675
+ else /* Last step was zero, so use only linear term. */
676
+ next_step += epsilon * slope;
677
+
678
+ /*
679
+ if(next_step > 1000 || next_step < -1000)
680
+ {
681
+ printf("quickprop[%d] weight=%f, slope=%f, prev_slope=%f, next_step=%f, prev_step=%f\n",
682
+ i, weights[i], slope, prev_slope, next_step, prev_step);
683
+
684
+ if(next_step > 1000)
685
+ next_step = 1000;
686
+ else
687
+ next_step = -1000;
688
+ }
689
+ */
690
+
691
+ /* update global data arrays */
692
+ prev_steps[i] = next_step;
693
+
694
+ w += next_step;
695
+
696
+ if(w > 1500)
697
+ weights[i] = 1500;
698
+ else if(w < -1500)
699
+ weights[i] = -1500;
700
+ else
701
+ weights[i] = w;
702
+
703
+ /*weights[i] = w;*/
704
+
705
+ prev_train_slopes[i] = slope;
706
+ train_slopes[i] = 0.0;
707
+ }
708
+ }
709
+
710
+ /* INTERNAL FUNCTION
711
+ The iRprop- algorithm
712
+ */
713
+ void fann_update_weights_irpropm(struct fann *ann, unsigned int first_weight, unsigned int past_end)
714
+ {
715
+ fann_type *train_slopes = ann->train_slopes;
716
+ fann_type *weights = ann->weights;
717
+ fann_type *prev_steps = ann->prev_steps;
718
+ fann_type *prev_train_slopes = ann->prev_train_slopes;
719
+
720
+ fann_type prev_step, slope, prev_slope, next_step, same_sign;
721
+
722
+ float increase_factor = ann->rprop_increase_factor; /*1.2; */
723
+ float decrease_factor = ann->rprop_decrease_factor; /*0.5; */
724
+ float delta_min = ann->rprop_delta_min; /*0.0; */
725
+ float delta_max = ann->rprop_delta_max; /*50.0; */
726
+
727
+ unsigned int i = first_weight;
728
+
729
+ for(; i != past_end; i++)
730
+ {
731
+ prev_step = fann_max(prev_steps[i], (fann_type) 0.0001); /* prev_step may not be zero because then the training will stop */
732
+ slope = train_slopes[i];
733
+ prev_slope = prev_train_slopes[i];
734
+
735
+ same_sign = prev_slope * slope;
736
+
737
+ if(same_sign >= 0.0)
738
+ next_step = fann_min(prev_step * increase_factor, delta_max);
739
+ else
740
+ {
741
+ next_step = fann_max(prev_step * decrease_factor, delta_min);
742
+ slope = 0;
743
+ }
744
+
745
+ if(slope < 0)
746
+ {
747
+ weights[i] -= next_step;
748
+ if(weights[i] < -1500)
749
+ weights[i] = -1500;
750
+ }
751
+ else
752
+ {
753
+ weights[i] += next_step;
754
+ if(weights[i] > 1500)
755
+ weights[i] = 1500;
756
+ }
757
+
758
+ /*if(i == 2){
759
+ * printf("weight=%f, slope=%f, next_step=%f, prev_step=%f\n", weights[i], slope, next_step, prev_step);
760
+ * } */
761
+
762
+ /* update global data arrays */
763
+ prev_steps[i] = next_step;
764
+ prev_train_slopes[i] = slope;
765
+ train_slopes[i] = 0.0;
766
+ }
767
+ }
768
+
769
+ /* INTERNAL FUNCTION
770
+ The SARprop- algorithm
771
+ */
772
+ void fann_update_weights_sarprop(struct fann *ann, unsigned int epoch, unsigned int first_weight, unsigned int past_end)
773
+ {
774
+ fann_type *train_slopes = ann->train_slopes;
775
+ fann_type *weights = ann->weights;
776
+ fann_type *prev_steps = ann->prev_steps;
777
+ fann_type *prev_train_slopes = ann->prev_train_slopes;
778
+
779
+ fann_type prev_step, slope, prev_slope, next_step = 0, same_sign;
780
+
781
+ /* These should be set from variables */
782
+ float increase_factor = ann->rprop_increase_factor; /*1.2; */
783
+ float decrease_factor = ann->rprop_decrease_factor; /*0.5; */
784
+ /* TODO: why is delta_min 0.0 in iRprop? SARPROP uses 1x10^-6 (Braun and Riedmiller, 1993) */
785
+ float delta_min = 0.000001f;
786
+ float delta_max = ann->rprop_delta_max; /*50.0; */
787
+ float weight_decay_shift = ann->sarprop_weight_decay_shift; /* ld 0.01 = -6.644 */
788
+ float step_error_threshold_factor = ann->sarprop_step_error_threshold_factor; /* 0.1 */
789
+ float step_error_shift = ann->sarprop_step_error_shift; /* ld 3 = 1.585 */
790
+ float T = ann->sarprop_temperature;
791
+ float MSE = fann_get_MSE(ann);
792
+ float RMSE = (float)sqrt(MSE);
793
+
794
+ unsigned int i = first_weight;
795
+
796
+
797
+ /* for all weights; TODO: are biases included? */
798
+ for(; i != past_end; i++)
799
+ {
800
+ /* TODO: confirm whether 1x10^-6 == delta_min is really better */
801
+ prev_step = fann_max(prev_steps[i], (fann_type) 0.000001); /* prev_step may not be zero because then the training will stop */
802
+ /* calculate SARPROP slope; TODO: better as new error function? (see SARPROP paper)*/
803
+ slope = -train_slopes[i] - weights[i] * (fann_type)fann_exp2(-T * epoch + weight_decay_shift);
804
+
805
+ /* TODO: is prev_train_slopes[i] 0.0 in the beginning? */
806
+ prev_slope = prev_train_slopes[i];
807
+
808
+ same_sign = prev_slope * slope;
809
+
810
+ if(same_sign > 0.0)
811
+ {
812
+ next_step = fann_min(prev_step * increase_factor, delta_max);
813
+ /* TODO: are the signs inverted? see differences between SARPROP paper and iRprop */
814
+ if (slope < 0.0)
815
+ weights[i] += next_step;
816
+ else
817
+ weights[i] -= next_step;
818
+ }
819
+ else if(same_sign < 0.0)
820
+ {
821
+ if(prev_step < step_error_threshold_factor * MSE)
822
+ next_step = prev_step * decrease_factor + (float)rand() / RAND_MAX * RMSE * (fann_type)fann_exp2(-T * epoch + step_error_shift);
823
+ else
824
+ next_step = fann_max(prev_step * decrease_factor, delta_min);
825
+
826
+ slope = 0.0;
827
+ }
828
+ else
829
+ {
830
+ if(slope < 0.0)
831
+ weights[i] += prev_step;
832
+ else
833
+ weights[i] -= prev_step;
834
+ }
835
+
836
+
837
+ /*if(i == 2){
838
+ * printf("weight=%f, slope=%f, next_step=%f, prev_step=%f\n", weights[i], slope, next_step, prev_step);
839
+ * } */
840
+
841
+ /* update global data arrays */
842
+ prev_steps[i] = next_step;
843
+ prev_train_slopes[i] = slope;
844
+ train_slopes[i] = 0.0;
845
+ }
846
+ }
847
+
848
+ #endif
849
+
850
+ FANN_GET_SET(enum fann_train_enum, training_algorithm)
851
+ FANN_GET_SET(float, learning_rate)
852
+
853
+ FANN_EXTERNAL void FANN_API fann_set_activation_function_hidden(struct fann *ann,
854
+ enum fann_activationfunc_enum activation_function)
855
+ {
856
+ struct fann_neuron *last_neuron, *neuron_it;
857
+ struct fann_layer *layer_it;
858
+ struct fann_layer *last_layer = ann->last_layer - 1; /* -1 to not update the output layer */
859
+
860
+ for(layer_it = ann->first_layer + 1; layer_it != last_layer; layer_it++)
861
+ {
862
+ last_neuron = layer_it->last_neuron;
863
+ for(neuron_it = layer_it->first_neuron; neuron_it != last_neuron; neuron_it++)
864
+ {
865
+ neuron_it->activation_function = activation_function;
866
+ }
867
+ }
868
+ }
869
+
870
+ FANN_EXTERNAL struct fann_layer* FANN_API fann_get_layer(struct fann *ann, int layer)
871
+ {
872
+ if(layer <= 0 || layer >= (ann->last_layer - ann->first_layer))
873
+ {
874
+ fann_error((struct fann_error *) ann, FANN_E_INDEX_OUT_OF_BOUND, layer);
875
+ return NULL;
876
+ }
877
+
878
+ return ann->first_layer + layer;
879
+ }
880
+
881
+ FANN_EXTERNAL struct fann_neuron* FANN_API fann_get_neuron_layer(struct fann *ann, struct fann_layer* layer, int neuron)
882
+ {
883
+ if(neuron >= (layer->last_neuron - layer->first_neuron))
884
+ {
885
+ fann_error((struct fann_error *) ann, FANN_E_INDEX_OUT_OF_BOUND, neuron);
886
+ return NULL;
887
+ }
888
+
889
+ return layer->first_neuron + neuron;
890
+ }
891
+
892
+ FANN_EXTERNAL struct fann_neuron* FANN_API fann_get_neuron(struct fann *ann, unsigned int layer, int neuron)
893
+ {
894
+ struct fann_layer *layer_it = fann_get_layer(ann, layer);
895
+ if(layer_it == NULL)
896
+ return NULL;
897
+ return fann_get_neuron_layer(ann, layer_it, neuron);
898
+ }
899
+
900
+ FANN_EXTERNAL enum fann_activationfunc_enum FANN_API
901
+ fann_get_activation_function(struct fann *ann, int layer, int neuron)
902
+ {
903
+ struct fann_neuron* neuron_it = fann_get_neuron(ann, layer, neuron);
904
+ if (neuron_it == NULL)
905
+ {
906
+ return (enum fann_activationfunc_enum)-1; /* layer or neuron out of bounds */
907
+ }
908
+ else
909
+ {
910
+ return neuron_it->activation_function;
911
+ }
912
+ }
913
+
914
+ FANN_EXTERNAL void FANN_API fann_set_activation_function(struct fann *ann,
915
+ enum fann_activationfunc_enum
916
+ activation_function,
917
+ int layer,
918
+ int neuron)
919
+ {
920
+ struct fann_neuron* neuron_it = fann_get_neuron(ann, layer, neuron);
921
+ if(neuron_it == NULL)
922
+ return;
923
+
924
+ neuron_it->activation_function = activation_function;
925
+ }
926
+
927
+ FANN_EXTERNAL void FANN_API fann_set_activation_function_layer(struct fann *ann,
928
+ enum fann_activationfunc_enum
929
+ activation_function,
930
+ int layer)
931
+ {
932
+ struct fann_neuron *last_neuron, *neuron_it;
933
+ struct fann_layer *layer_it = fann_get_layer(ann, layer);
934
+
935
+ if(layer_it == NULL)
936
+ return;
937
+
938
+ last_neuron = layer_it->last_neuron;
939
+ for(neuron_it = layer_it->first_neuron; neuron_it != last_neuron; neuron_it++)
940
+ {
941
+ neuron_it->activation_function = activation_function;
942
+ }
943
+ }
944
+
945
+
946
+ FANN_EXTERNAL void FANN_API fann_set_activation_function_output(struct fann *ann,
947
+ enum fann_activationfunc_enum activation_function)
948
+ {
949
+ struct fann_neuron *last_neuron, *neuron_it;
950
+ struct fann_layer *last_layer = ann->last_layer - 1;
951
+
952
+ last_neuron = last_layer->last_neuron;
953
+ for(neuron_it = last_layer->first_neuron; neuron_it != last_neuron; neuron_it++)
954
+ {
955
+ neuron_it->activation_function = activation_function;
956
+ }
957
+ }
958
+
959
+ FANN_EXTERNAL void FANN_API fann_set_activation_steepness_hidden(struct fann *ann,
960
+ fann_type steepness)
961
+ {
962
+ struct fann_neuron *last_neuron, *neuron_it;
963
+ struct fann_layer *layer_it;
964
+ struct fann_layer *last_layer = ann->last_layer - 1; /* -1 to not update the output layer */
965
+
966
+ for(layer_it = ann->first_layer + 1; layer_it != last_layer; layer_it++)
967
+ {
968
+ last_neuron = layer_it->last_neuron;
969
+ for(neuron_it = layer_it->first_neuron; neuron_it != last_neuron; neuron_it++)
970
+ {
971
+ neuron_it->activation_steepness = steepness;
972
+ }
973
+ }
974
+ }
975
+
976
+ FANN_EXTERNAL fann_type FANN_API
977
+ fann_get_activation_steepness(struct fann *ann, int layer, int neuron)
978
+ {
979
+ struct fann_neuron* neuron_it = fann_get_neuron(ann, layer, neuron);
980
+ if(neuron_it == NULL)
981
+ {
982
+ return -1; /* layer or neuron out of bounds */
983
+ }
984
+ else
985
+ {
986
+ return neuron_it->activation_steepness;
987
+ }
988
+ }
989
+
990
+ FANN_EXTERNAL void FANN_API fann_set_activation_steepness(struct fann *ann,
991
+ fann_type steepness,
992
+ int layer,
993
+ int neuron)
994
+ {
995
+ struct fann_neuron* neuron_it = fann_get_neuron(ann, layer, neuron);
996
+ if(neuron_it == NULL)
997
+ return;
998
+
999
+ neuron_it->activation_steepness = steepness;
1000
+ }
1001
+
1002
+ FANN_EXTERNAL void FANN_API fann_set_activation_steepness_layer(struct fann *ann,
1003
+ fann_type steepness,
1004
+ int layer)
1005
+ {
1006
+ struct fann_neuron *last_neuron, *neuron_it;
1007
+ struct fann_layer *layer_it = fann_get_layer(ann, layer);
1008
+
1009
+ if(layer_it == NULL)
1010
+ return;
1011
+
1012
+ last_neuron = layer_it->last_neuron;
1013
+ for(neuron_it = layer_it->first_neuron; neuron_it != last_neuron; neuron_it++)
1014
+ {
1015
+ neuron_it->activation_steepness = steepness;
1016
+ }
1017
+ }
1018
+
1019
+ FANN_EXTERNAL void FANN_API fann_set_activation_steepness_output(struct fann *ann,
1020
+ fann_type steepness)
1021
+ {
1022
+ struct fann_neuron *last_neuron, *neuron_it;
1023
+ struct fann_layer *last_layer = ann->last_layer - 1;
1024
+
1025
+ last_neuron = last_layer->last_neuron;
1026
+ for(neuron_it = last_layer->first_neuron; neuron_it != last_neuron; neuron_it++)
1027
+ {
1028
+ neuron_it->activation_steepness = steepness;
1029
+ }
1030
+ }
1031
+
1032
+ FANN_GET_SET(enum fann_errorfunc_enum, train_error_function)
1033
+ FANN_GET_SET(fann_callback_type, callback)
1034
+ FANN_GET_SET(float, quickprop_decay)
1035
+ FANN_GET_SET(float, quickprop_mu)
1036
+ FANN_GET_SET(float, rprop_increase_factor)
1037
+ FANN_GET_SET(float, rprop_decrease_factor)
1038
+ FANN_GET_SET(float, rprop_delta_min)
1039
+ FANN_GET_SET(float, rprop_delta_max)
1040
+ FANN_GET_SET(float, rprop_delta_zero)
1041
+ FANN_GET_SET(float, sarprop_weight_decay_shift)
1042
+ FANN_GET_SET(float, sarprop_step_error_threshold_factor)
1043
+ FANN_GET_SET(float, sarprop_step_error_shift)
1044
+ FANN_GET_SET(float, sarprop_temperature)
1045
+ FANN_GET_SET(enum fann_stopfunc_enum, train_stop_function)
1046
+ FANN_GET_SET(fann_type, bit_fail_limit)
1047
+ FANN_GET_SET(float, learning_momentum)