ruby-fann 0.7.10 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -1
- data/License.txt +1 -1
- data/Manifest.txt +22 -1
- data/README.txt +0 -1
- data/Rakefile +0 -0
- data/config/hoe.rb +0 -0
- data/config/requirements.rb +0 -0
- data/ext/ruby_fann/MANIFEST +0 -0
- data/ext/ruby_fann/Makefile +36 -28
- data/ext/ruby_fann/doublefann.c +30 -0
- data/ext/ruby_fann/doublefann.h +33 -0
- data/ext/ruby_fann/extconf.rb +9 -5
- data/ext/ruby_fann/fann.c +1552 -0
- data/ext/ruby_fann/fann_activation.h +144 -0
- data/ext/ruby_fann/fann_augment.h +0 -0
- data/ext/ruby_fann/fann_cascade.c +1031 -0
- data/ext/ruby_fann/fann_cascade.h +503 -0
- data/ext/ruby_fann/fann_data.h +799 -0
- data/ext/ruby_fann/fann_error.c +204 -0
- data/ext/ruby_fann/fann_error.h +161 -0
- data/ext/ruby_fann/fann_internal.h +148 -0
- data/ext/ruby_fann/fann_io.c +762 -0
- data/ext/ruby_fann/fann_io.h +100 -0
- data/ext/ruby_fann/fann_train.c +962 -0
- data/ext/ruby_fann/fann_train.h +1203 -0
- data/ext/ruby_fann/fann_train_data.c +1231 -0
- data/ext/ruby_fann/neural_network.c +0 -0
- data/lib/ruby_fann/neurotica.rb +0 -0
- data/lib/ruby_fann/version.rb +3 -3
- data/lib/ruby_fann.rb +0 -0
- data/neurotica1.png +0 -0
- data/neurotica2.vrml +18 -18
- data/setup.rb +0 -0
- data/tasks/deployment.rake +0 -0
- data/tasks/environment.rake +0 -0
- data/tasks/website.rake +0 -0
- data/test/test.train +0 -0
- data/test/test_helper.rb +0 -0
- data/test/test_neurotica.rb +0 -0
- data/test/test_ruby_fann.rb +0 -0
- data/test/test_ruby_fann_functional.rb +0 -0
- data/verify.train +0 -0
- data/website/index.html +42 -92
- data/website/index.txt +0 -0
- data/website/javascripts/rounded_corners_lite.inc.js +0 -0
- data/website/stylesheets/screen.css +0 -0
- data/website/template.rhtml +0 -0
- data/xor.train +0 -0
- data/xor_cascade.net +2 -2
- data/xor_float.net +1 -1
- metadata +22 -6
- data/log/debug.log +0 -0
@@ -0,0 +1,1031 @@
|
|
1
|
+
/*
|
2
|
+
Fast Artificial Neural Network Library (fann)
|
3
|
+
Copyright (C) 2003 Steffen Nissen (lukesky@diku.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 "config.h"
|
21
|
+
#include "fann.h"
|
22
|
+
#include "string.h"
|
23
|
+
|
24
|
+
#ifndef FIXEDFANN
|
25
|
+
|
26
|
+
/* #define CASCADE_DEBUG */
|
27
|
+
/* #define CASCADE_DEBUG_FULL */
|
28
|
+
|
29
|
+
void fann_print_connections_raw(struct fann *ann)
|
30
|
+
{
|
31
|
+
unsigned int i;
|
32
|
+
|
33
|
+
for(i = 0; i < ann->total_connections_allocated; i++)
|
34
|
+
{
|
35
|
+
if(i == ann->total_connections)
|
36
|
+
{
|
37
|
+
printf("* ");
|
38
|
+
}
|
39
|
+
printf("%f ", ann->weights[i]);
|
40
|
+
}
|
41
|
+
printf("\n\n");
|
42
|
+
}
|
43
|
+
|
44
|
+
/* Cascade training directly on the training data.
|
45
|
+
The connected_neurons pointers are not valid during training,
|
46
|
+
but they will be again after training.
|
47
|
+
*/
|
48
|
+
FANN_EXTERNAL void FANN_API fann_cascadetrain_on_data(struct fann *ann, struct fann_train_data *data,
|
49
|
+
unsigned int max_neurons,
|
50
|
+
unsigned int neurons_between_reports,
|
51
|
+
float desired_error)
|
52
|
+
{
|
53
|
+
float error;
|
54
|
+
unsigned int i;
|
55
|
+
unsigned int total_epochs = 0;
|
56
|
+
int desired_error_reached;
|
57
|
+
|
58
|
+
if(neurons_between_reports && ann->callback == NULL)
|
59
|
+
{
|
60
|
+
printf("Max neurons %3d. Desired error: %.6f\n", max_neurons, desired_error);
|
61
|
+
}
|
62
|
+
|
63
|
+
for(i = 1; i <= max_neurons; i++)
|
64
|
+
{
|
65
|
+
/* train output neurons */
|
66
|
+
total_epochs += fann_train_outputs(ann, data, desired_error);
|
67
|
+
error = fann_get_MSE(ann);
|
68
|
+
desired_error_reached = fann_desired_error_reached(ann, desired_error);
|
69
|
+
|
70
|
+
/* print current error */
|
71
|
+
if(neurons_between_reports &&
|
72
|
+
(i % neurons_between_reports == 0
|
73
|
+
|| i == max_neurons || i == 1 || desired_error_reached == 0))
|
74
|
+
{
|
75
|
+
if(ann->callback == NULL)
|
76
|
+
{
|
77
|
+
printf
|
78
|
+
("Neurons %3d. Current error: %.6f. Total error:%8.4f. Epochs %5d. Bit fail %3d",
|
79
|
+
i, error, ann->MSE_value, total_epochs, ann->num_bit_fail);
|
80
|
+
if((ann->last_layer-2) != ann->first_layer)
|
81
|
+
{
|
82
|
+
printf(". candidate steepness %.2f. function %s",
|
83
|
+
(ann->last_layer-2)->first_neuron->activation_steepness,
|
84
|
+
FANN_ACTIVATIONFUNC_NAMES[(ann->last_layer-2)->first_neuron->activation_function]);
|
85
|
+
}
|
86
|
+
printf("\n");
|
87
|
+
}
|
88
|
+
else if((*ann->callback) (ann, data, max_neurons,
|
89
|
+
neurons_between_reports, desired_error, total_epochs) == -1)
|
90
|
+
{
|
91
|
+
/* you can break the training by returning -1 */
|
92
|
+
break;
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
if(desired_error_reached == 0)
|
97
|
+
break;
|
98
|
+
|
99
|
+
if(fann_initialize_candidates(ann) == -1)
|
100
|
+
{
|
101
|
+
/* Unable to initialize room for candidates */
|
102
|
+
break;
|
103
|
+
}
|
104
|
+
|
105
|
+
/* train new candidates */
|
106
|
+
total_epochs += fann_train_candidates(ann, data);
|
107
|
+
|
108
|
+
/* this installs the best candidate */
|
109
|
+
fann_install_candidate(ann);
|
110
|
+
}
|
111
|
+
|
112
|
+
/* Train outputs one last time but without any desired error */
|
113
|
+
total_epochs += fann_train_outputs(ann, data, 0.0);
|
114
|
+
|
115
|
+
if(neurons_between_reports && ann->callback == NULL)
|
116
|
+
{
|
117
|
+
printf("Train outputs Current error: %.6f. Epochs %6d\n", fann_get_MSE(ann),
|
118
|
+
total_epochs);
|
119
|
+
}
|
120
|
+
|
121
|
+
/* Set pointers in connected_neurons
|
122
|
+
* This is ONLY done in the end of cascade training,
|
123
|
+
* since there is no need for them during training.
|
124
|
+
*/
|
125
|
+
fann_set_shortcut_connections(ann);
|
126
|
+
}
|
127
|
+
|
128
|
+
FANN_EXTERNAL void FANN_API fann_cascadetrain_on_file(struct fann *ann, const char *filename,
|
129
|
+
unsigned int max_neurons,
|
130
|
+
unsigned int neurons_between_reports,
|
131
|
+
float desired_error)
|
132
|
+
{
|
133
|
+
struct fann_train_data *data = fann_read_train_from_file(filename);
|
134
|
+
|
135
|
+
if(data == NULL)
|
136
|
+
{
|
137
|
+
return;
|
138
|
+
}
|
139
|
+
fann_cascadetrain_on_data(ann, data, max_neurons, neurons_between_reports, desired_error);
|
140
|
+
fann_destroy_train(data);
|
141
|
+
}
|
142
|
+
|
143
|
+
int fann_train_outputs(struct fann *ann, struct fann_train_data *data, float desired_error)
|
144
|
+
{
|
145
|
+
float error, initial_error, error_improvement;
|
146
|
+
float target_improvement = 0.0;
|
147
|
+
float backslide_improvement = -1.0e20f;
|
148
|
+
unsigned int i;
|
149
|
+
unsigned int max_epochs = ann->cascade_max_out_epochs;
|
150
|
+
unsigned int stagnation = max_epochs;
|
151
|
+
|
152
|
+
/* TODO should perhaps not clear all arrays */
|
153
|
+
fann_clear_train_arrays(ann);
|
154
|
+
|
155
|
+
/* run an initial epoch to set the initital error */
|
156
|
+
initial_error = fann_train_outputs_epoch(ann, data);
|
157
|
+
|
158
|
+
if(fann_desired_error_reached(ann, desired_error) == 0)
|
159
|
+
return 1;
|
160
|
+
|
161
|
+
for(i = 1; i < max_epochs; i++)
|
162
|
+
{
|
163
|
+
error = fann_train_outputs_epoch(ann, data);
|
164
|
+
|
165
|
+
/*printf("Epoch %6d. Current error: %.6f. Bit fail %d.\n", i, error, ann->num_bit_fail); */
|
166
|
+
|
167
|
+
if(fann_desired_error_reached(ann, desired_error) == 0)
|
168
|
+
{
|
169
|
+
#ifdef CASCADE_DEBUG
|
170
|
+
printf("Error %f < %f\n", error, desired_error);
|
171
|
+
#endif
|
172
|
+
return i + 1;
|
173
|
+
}
|
174
|
+
|
175
|
+
/* Improvement since start of train */
|
176
|
+
error_improvement = initial_error - error;
|
177
|
+
|
178
|
+
/* After any significant change, set a new goal and
|
179
|
+
* allow a new quota of epochs to reach it */
|
180
|
+
if((error_improvement > target_improvement) || (error_improvement < backslide_improvement))
|
181
|
+
{
|
182
|
+
/*printf("error_improvement=%f, target_improvement=%f, backslide_improvement=%f, stagnation=%d\n", error_improvement, target_improvement, backslide_improvement, stagnation); */
|
183
|
+
|
184
|
+
target_improvement = error_improvement * (1.0f + ann->cascade_output_change_fraction);
|
185
|
+
backslide_improvement = error_improvement * (1.0f - ann->cascade_output_change_fraction);
|
186
|
+
stagnation = i + ann->cascade_output_stagnation_epochs;
|
187
|
+
}
|
188
|
+
|
189
|
+
/* No improvement in allotted period, so quit */
|
190
|
+
if(i >= stagnation)
|
191
|
+
{
|
192
|
+
return i + 1;
|
193
|
+
}
|
194
|
+
}
|
195
|
+
|
196
|
+
return max_epochs;
|
197
|
+
}
|
198
|
+
|
199
|
+
float fann_train_outputs_epoch(struct fann *ann, struct fann_train_data *data)
|
200
|
+
{
|
201
|
+
unsigned int i;
|
202
|
+
|
203
|
+
fann_reset_MSE(ann);
|
204
|
+
|
205
|
+
for(i = 0; i < data->num_data; i++)
|
206
|
+
{
|
207
|
+
fann_run(ann, data->input[i]);
|
208
|
+
fann_compute_MSE(ann, data->output[i]);
|
209
|
+
fann_update_slopes_batch(ann, ann->last_layer - 1, ann->last_layer - 1);
|
210
|
+
}
|
211
|
+
|
212
|
+
switch (ann->training_algorithm)
|
213
|
+
{
|
214
|
+
case FANN_TRAIN_RPROP:
|
215
|
+
fann_update_weights_irpropm(ann, (ann->last_layer - 1)->first_neuron->first_con,
|
216
|
+
ann->total_connections);
|
217
|
+
break;
|
218
|
+
case FANN_TRAIN_QUICKPROP:
|
219
|
+
fann_update_weights_quickprop(ann, data->num_data,
|
220
|
+
(ann->last_layer - 1)->first_neuron->first_con,
|
221
|
+
ann->total_connections);
|
222
|
+
break;
|
223
|
+
case FANN_TRAIN_BATCH:
|
224
|
+
case FANN_TRAIN_INCREMENTAL:
|
225
|
+
fann_error((struct fann_error *) ann, FANN_E_CANT_USE_TRAIN_ALG);
|
226
|
+
}
|
227
|
+
|
228
|
+
return fann_get_MSE(ann);
|
229
|
+
}
|
230
|
+
|
231
|
+
int fann_reallocate_connections(struct fann *ann, unsigned int total_connections)
|
232
|
+
{
|
233
|
+
/* The connections are allocated, but the pointers inside are
|
234
|
+
* first moved in the end of the cascade training session.
|
235
|
+
*/
|
236
|
+
|
237
|
+
#ifdef CASCADE_DEBUG
|
238
|
+
printf("realloc from %d to %d\n", ann->total_connections_allocated, total_connections);
|
239
|
+
#endif
|
240
|
+
ann->connections =
|
241
|
+
(struct fann_neuron **) realloc(ann->connections,
|
242
|
+
total_connections * sizeof(struct fann_neuron *));
|
243
|
+
if(ann->connections == NULL)
|
244
|
+
{
|
245
|
+
fann_error((struct fann_error *) ann, FANN_E_CANT_ALLOCATE_MEM);
|
246
|
+
return -1;
|
247
|
+
}
|
248
|
+
|
249
|
+
ann->weights = (fann_type *) realloc(ann->weights, total_connections * sizeof(fann_type));
|
250
|
+
if(ann->weights == NULL)
|
251
|
+
{
|
252
|
+
fann_error((struct fann_error *) ann, FANN_E_CANT_ALLOCATE_MEM);
|
253
|
+
return -1;
|
254
|
+
}
|
255
|
+
|
256
|
+
ann->train_slopes =
|
257
|
+
(fann_type *) realloc(ann->train_slopes, total_connections * sizeof(fann_type));
|
258
|
+
if(ann->train_slopes == NULL)
|
259
|
+
{
|
260
|
+
fann_error((struct fann_error *) ann, FANN_E_CANT_ALLOCATE_MEM);
|
261
|
+
return -1;
|
262
|
+
}
|
263
|
+
|
264
|
+
ann->prev_steps = (fann_type *) realloc(ann->prev_steps, total_connections * sizeof(fann_type));
|
265
|
+
if(ann->prev_steps == NULL)
|
266
|
+
{
|
267
|
+
fann_error((struct fann_error *) ann, FANN_E_CANT_ALLOCATE_MEM);
|
268
|
+
return -1;
|
269
|
+
}
|
270
|
+
|
271
|
+
ann->prev_train_slopes =
|
272
|
+
(fann_type *) realloc(ann->prev_train_slopes, total_connections * sizeof(fann_type));
|
273
|
+
if(ann->prev_train_slopes == NULL)
|
274
|
+
{
|
275
|
+
fann_error((struct fann_error *) ann, FANN_E_CANT_ALLOCATE_MEM);
|
276
|
+
return -1;
|
277
|
+
}
|
278
|
+
|
279
|
+
ann->total_connections_allocated = total_connections;
|
280
|
+
|
281
|
+
return 0;
|
282
|
+
}
|
283
|
+
|
284
|
+
int fann_reallocate_neurons(struct fann *ann, unsigned int total_neurons)
|
285
|
+
{
|
286
|
+
struct fann_layer *layer_it;
|
287
|
+
struct fann_neuron *neurons;
|
288
|
+
unsigned int num_neurons = 0;
|
289
|
+
unsigned int num_neurons_so_far = 0;
|
290
|
+
|
291
|
+
neurons =
|
292
|
+
(struct fann_neuron *) realloc(ann->first_layer->first_neuron,
|
293
|
+
total_neurons * sizeof(struct fann_neuron));
|
294
|
+
ann->total_neurons_allocated = total_neurons;
|
295
|
+
|
296
|
+
if(neurons == NULL)
|
297
|
+
{
|
298
|
+
fann_error((struct fann_error *) ann, FANN_E_CANT_ALLOCATE_MEM);
|
299
|
+
return -1;
|
300
|
+
}
|
301
|
+
|
302
|
+
/* Also allocate room for more train_errors */
|
303
|
+
ann->train_errors = (fann_type *) realloc(ann->train_errors, total_neurons * sizeof(fann_type));
|
304
|
+
if(ann->train_errors == NULL)
|
305
|
+
{
|
306
|
+
fann_error((struct fann_error *) ann, FANN_E_CANT_ALLOCATE_MEM);
|
307
|
+
return -1;
|
308
|
+
}
|
309
|
+
|
310
|
+
if(neurons != ann->first_layer->first_neuron)
|
311
|
+
{
|
312
|
+
/* Then the memory has moved, also move the pointers */
|
313
|
+
|
314
|
+
#ifdef CASCADE_DEBUG_FULL
|
315
|
+
printf("Moving neuron pointers\n");
|
316
|
+
#endif
|
317
|
+
|
318
|
+
/* Move pointers from layers to neurons */
|
319
|
+
for(layer_it = ann->first_layer; layer_it != ann->last_layer; layer_it++)
|
320
|
+
{
|
321
|
+
num_neurons = layer_it->last_neuron - layer_it->first_neuron;
|
322
|
+
layer_it->first_neuron = neurons + num_neurons_so_far;
|
323
|
+
layer_it->last_neuron = layer_it->first_neuron + num_neurons;
|
324
|
+
num_neurons_so_far += num_neurons;
|
325
|
+
}
|
326
|
+
}
|
327
|
+
|
328
|
+
return 0;
|
329
|
+
}
|
330
|
+
|
331
|
+
void initialize_candidate_weights(struct fann *ann, unsigned int first_con, unsigned int last_con, float scale_factor)
|
332
|
+
{
|
333
|
+
fann_type prev_step;
|
334
|
+
unsigned int i = 0;
|
335
|
+
unsigned int bias_weight = first_con + (ann->first_layer->last_neuron - ann->first_layer->first_neuron) - 1;
|
336
|
+
|
337
|
+
if(ann->training_algorithm == FANN_TRAIN_RPROP)
|
338
|
+
prev_step = ann->rprop_delta_zero;
|
339
|
+
else
|
340
|
+
prev_step = 0;
|
341
|
+
|
342
|
+
for(i = first_con; i < last_con; i++)
|
343
|
+
{
|
344
|
+
if(i == bias_weight)
|
345
|
+
ann->weights[i] = fann_rand(-scale_factor, scale_factor);
|
346
|
+
else
|
347
|
+
ann->weights[i] = fann_rand(0,scale_factor);
|
348
|
+
|
349
|
+
ann->train_slopes[i] = 0;
|
350
|
+
ann->prev_steps[i] = prev_step;
|
351
|
+
ann->prev_train_slopes[i] = 0;
|
352
|
+
}
|
353
|
+
}
|
354
|
+
|
355
|
+
int fann_initialize_candidates(struct fann *ann)
|
356
|
+
{
|
357
|
+
/* The candidates are allocated after the normal neurons and connections,
|
358
|
+
* but there is an empty place between the real neurons and the candidate neurons,
|
359
|
+
* so that it will be possible to make room when the chosen candidate are copied in
|
360
|
+
* on the desired place.
|
361
|
+
*/
|
362
|
+
unsigned int neurons_to_allocate, connections_to_allocate;
|
363
|
+
unsigned int num_candidates = fann_get_cascade_num_candidates(ann);
|
364
|
+
unsigned int num_neurons = ann->total_neurons + num_candidates + 1;
|
365
|
+
unsigned int num_hidden_neurons = ann->total_neurons - ann->num_input - ann->num_output;
|
366
|
+
unsigned int candidate_connections_in = ann->total_neurons - ann->num_output;
|
367
|
+
unsigned int candidate_connections_out = ann->num_output;
|
368
|
+
|
369
|
+
/* the number of connections going into a and out of a candidate is
|
370
|
+
* ann->total_neurons */
|
371
|
+
unsigned int num_connections =
|
372
|
+
ann->total_connections + (ann->total_neurons * (num_candidates + 1));
|
373
|
+
unsigned int first_candidate_connection = ann->total_connections + ann->total_neurons;
|
374
|
+
unsigned int first_candidate_neuron = ann->total_neurons + 1;
|
375
|
+
unsigned int connection_it, i, j, k, candidate_index;
|
376
|
+
struct fann_neuron *neurons;
|
377
|
+
float scale_factor;
|
378
|
+
|
379
|
+
/* First make sure that there is enough room, and if not then allocate a
|
380
|
+
* bit more so that we do not need to allocate more room each time.
|
381
|
+
*/
|
382
|
+
if(num_neurons > ann->total_neurons_allocated)
|
383
|
+
{
|
384
|
+
/* Then we need to allocate more neurons
|
385
|
+
* Allocate half as many neurons as already exist (at least ten)
|
386
|
+
*/
|
387
|
+
neurons_to_allocate = num_neurons + num_neurons / 2;
|
388
|
+
if(neurons_to_allocate < num_neurons + 10)
|
389
|
+
{
|
390
|
+
neurons_to_allocate = num_neurons + 10;
|
391
|
+
}
|
392
|
+
|
393
|
+
if(fann_reallocate_neurons(ann, neurons_to_allocate) == -1)
|
394
|
+
{
|
395
|
+
return -1;
|
396
|
+
}
|
397
|
+
}
|
398
|
+
|
399
|
+
if(num_connections > ann->total_connections_allocated)
|
400
|
+
{
|
401
|
+
/* Then we need to allocate more connections
|
402
|
+
* Allocate half as many connections as already exist
|
403
|
+
* (at least enough for ten neurons)
|
404
|
+
*/
|
405
|
+
connections_to_allocate = num_connections + num_connections / 2;
|
406
|
+
if(connections_to_allocate < num_connections + ann->total_neurons * 10)
|
407
|
+
{
|
408
|
+
connections_to_allocate = num_connections + ann->total_neurons * 10;
|
409
|
+
}
|
410
|
+
|
411
|
+
if(fann_reallocate_connections(ann, connections_to_allocate) == -1)
|
412
|
+
{
|
413
|
+
return -1;
|
414
|
+
}
|
415
|
+
}
|
416
|
+
|
417
|
+
/* Some test code to do semi Widrow + Nguyen initialization */
|
418
|
+
scale_factor = (float) 2.0f*(pow((double) (0.7f * (double) num_hidden_neurons),
|
419
|
+
(double) (1.0f / (double) ann->num_input)));
|
420
|
+
if(scale_factor > 8)
|
421
|
+
scale_factor = 8;
|
422
|
+
else if(scale_factor < 0.5)
|
423
|
+
scale_factor = 0.5;
|
424
|
+
|
425
|
+
/* Set the neurons.
|
426
|
+
*/
|
427
|
+
connection_it = first_candidate_connection;
|
428
|
+
neurons = ann->first_layer->first_neuron;
|
429
|
+
candidate_index = first_candidate_neuron;
|
430
|
+
|
431
|
+
for(i = 0; i < ann->cascade_activation_functions_count; i++)
|
432
|
+
{
|
433
|
+
for(j = 0; j < ann->cascade_activation_steepnesses_count; j++)
|
434
|
+
{
|
435
|
+
for(k = 0; k < ann->cascade_num_candidate_groups; k++)
|
436
|
+
{
|
437
|
+
/* TODO candidates should actually be created both in
|
438
|
+
* the last layer before the output layer, and in a new layer.
|
439
|
+
*/
|
440
|
+
neurons[candidate_index].value = 0;
|
441
|
+
neurons[candidate_index].sum = 0;
|
442
|
+
|
443
|
+
neurons[candidate_index].activation_function =
|
444
|
+
ann->cascade_activation_functions[i];
|
445
|
+
neurons[candidate_index].activation_steepness =
|
446
|
+
ann->cascade_activation_steepnesses[j];
|
447
|
+
|
448
|
+
neurons[candidate_index].first_con = connection_it;
|
449
|
+
connection_it += candidate_connections_in;
|
450
|
+
neurons[candidate_index].last_con = connection_it;
|
451
|
+
/* We have no specific pointers to the output weights, but they are
|
452
|
+
* available after last_con */
|
453
|
+
connection_it += candidate_connections_out;
|
454
|
+
ann->train_errors[candidate_index] = 0;
|
455
|
+
initialize_candidate_weights(ann, neurons[candidate_index].first_con, neurons[candidate_index].last_con+candidate_connections_out, scale_factor);
|
456
|
+
candidate_index++;
|
457
|
+
}
|
458
|
+
}
|
459
|
+
}
|
460
|
+
|
461
|
+
|
462
|
+
/* Now randomize the weights and zero out the arrays that needs zeroing out.
|
463
|
+
*/
|
464
|
+
/*
|
465
|
+
#ifdef CASCADE_DEBUG_FULL
|
466
|
+
printf("random cand weight [%d ... %d]\n", first_candidate_connection, num_connections - 1);
|
467
|
+
#endif
|
468
|
+
|
469
|
+
for(i = first_candidate_connection; i < num_connections; i++)
|
470
|
+
{
|
471
|
+
|
472
|
+
//ann->weights[i] = fann_random_weight();
|
473
|
+
ann->weights[i] = fann_rand(-2.0,2.0);
|
474
|
+
ann->train_slopes[i] = 0;
|
475
|
+
ann->prev_steps[i] = 0;
|
476
|
+
ann->prev_train_slopes[i] = initial_slope;
|
477
|
+
}
|
478
|
+
*/
|
479
|
+
|
480
|
+
return 0;
|
481
|
+
}
|
482
|
+
|
483
|
+
int fann_train_candidates(struct fann *ann, struct fann_train_data *data)
|
484
|
+
{
|
485
|
+
fann_type best_cand_score = 0.0;
|
486
|
+
fann_type target_cand_score = 0.0;
|
487
|
+
fann_type backslide_cand_score = -1.0e20f;
|
488
|
+
unsigned int i;
|
489
|
+
unsigned int max_epochs = ann->cascade_max_cand_epochs;
|
490
|
+
unsigned int stagnation = max_epochs;
|
491
|
+
|
492
|
+
if(ann->cascade_candidate_scores == NULL)
|
493
|
+
{
|
494
|
+
ann->cascade_candidate_scores =
|
495
|
+
(fann_type *) malloc(fann_get_cascade_num_candidates(ann) * sizeof(fann_type));
|
496
|
+
if(ann->cascade_candidate_scores == NULL)
|
497
|
+
{
|
498
|
+
fann_error((struct fann_error *) ann, FANN_E_CANT_ALLOCATE_MEM);
|
499
|
+
return 0;
|
500
|
+
}
|
501
|
+
}
|
502
|
+
|
503
|
+
for(i = 0; i < max_epochs; i++)
|
504
|
+
{
|
505
|
+
best_cand_score = fann_train_candidates_epoch(ann, data);
|
506
|
+
|
507
|
+
if(best_cand_score / ann->MSE_value > ann->cascade_candidate_limit)
|
508
|
+
{
|
509
|
+
#ifdef CASCADE_DEBUG
|
510
|
+
printf("above candidate limit %f/%f > %f", best_cand_score, ann->MSE_value,
|
511
|
+
ann->cascade_candidate_limit);
|
512
|
+
#endif
|
513
|
+
return i + 1;
|
514
|
+
}
|
515
|
+
|
516
|
+
if((best_cand_score > target_cand_score) || (best_cand_score < backslide_cand_score))
|
517
|
+
{
|
518
|
+
#ifdef CASCADE_DEBUG_FULL
|
519
|
+
printf("Best candidate score %f, real score: %f\n", ann->MSE_value - best_cand_score,
|
520
|
+
best_cand_score);
|
521
|
+
/* printf("best_cand_score=%f, target_cand_score=%f, backslide_cand_score=%f, stagnation=%d\n", best_cand_score, target_cand_score, backslide_cand_score, stagnation); */
|
522
|
+
#endif
|
523
|
+
|
524
|
+
target_cand_score = best_cand_score * (1.0f + ann->cascade_candidate_change_fraction);
|
525
|
+
backslide_cand_score = best_cand_score * (1.0f - ann->cascade_candidate_change_fraction);
|
526
|
+
stagnation = i + ann->cascade_candidate_stagnation_epochs;
|
527
|
+
}
|
528
|
+
|
529
|
+
/* No improvement in allotted period, so quit */
|
530
|
+
if(i >= stagnation)
|
531
|
+
{
|
532
|
+
#ifdef CASCADE_DEBUG
|
533
|
+
printf("Stagnation with %d epochs, best candidate score %f, real score: %f\n", i + 1,
|
534
|
+
ann->MSE_value - best_cand_score, best_cand_score);
|
535
|
+
#endif
|
536
|
+
return i + 1;
|
537
|
+
}
|
538
|
+
}
|
539
|
+
|
540
|
+
#ifdef CASCADE_DEBUG
|
541
|
+
printf("Max epochs %d reached, best candidate score %f, real score: %f\n", max_epochs,
|
542
|
+
ann->MSE_value - best_cand_score, best_cand_score);
|
543
|
+
#endif
|
544
|
+
return max_epochs;
|
545
|
+
}
|
546
|
+
|
547
|
+
void fann_update_candidate_slopes(struct fann *ann)
|
548
|
+
{
|
549
|
+
struct fann_neuron *neurons = ann->first_layer->first_neuron;
|
550
|
+
struct fann_neuron *first_cand = neurons + ann->total_neurons + 1;
|
551
|
+
struct fann_neuron *last_cand = first_cand + fann_get_cascade_num_candidates(ann);
|
552
|
+
struct fann_neuron *cand_it;
|
553
|
+
unsigned int i, j, num_connections;
|
554
|
+
unsigned int num_output = ann->num_output;
|
555
|
+
fann_type max_sum, cand_sum, activation, derived, error_value, diff, cand_score;
|
556
|
+
fann_type *weights, *cand_out_weights, *cand_slopes, *cand_out_slopes;
|
557
|
+
fann_type *output_train_errors = ann->train_errors + (ann->total_neurons - ann->num_output);
|
558
|
+
|
559
|
+
for(cand_it = first_cand; cand_it < last_cand; cand_it++)
|
560
|
+
{
|
561
|
+
cand_score = ann->cascade_candidate_scores[cand_it - first_cand];
|
562
|
+
error_value = 0.0;
|
563
|
+
|
564
|
+
/* code more or less stolen from fann_run to fast forward pass
|
565
|
+
*/
|
566
|
+
cand_sum = 0.0;
|
567
|
+
num_connections = cand_it->last_con - cand_it->first_con;
|
568
|
+
weights = ann->weights + cand_it->first_con;
|
569
|
+
|
570
|
+
/* unrolled loop start */
|
571
|
+
i = num_connections & 3; /* same as modulo 4 */
|
572
|
+
switch (i)
|
573
|
+
{
|
574
|
+
case 3:
|
575
|
+
cand_sum += weights[2] * neurons[2].value;
|
576
|
+
case 2:
|
577
|
+
cand_sum += weights[1] * neurons[1].value;
|
578
|
+
case 1:
|
579
|
+
cand_sum += weights[0] * neurons[0].value;
|
580
|
+
case 0:
|
581
|
+
break;
|
582
|
+
}
|
583
|
+
|
584
|
+
for(; i != num_connections; i += 4)
|
585
|
+
{
|
586
|
+
cand_sum +=
|
587
|
+
weights[i] * neurons[i].value +
|
588
|
+
weights[i + 1] * neurons[i + 1].value +
|
589
|
+
weights[i + 2] * neurons[i + 2].value + weights[i + 3] * neurons[i + 3].value;
|
590
|
+
}
|
591
|
+
/*
|
592
|
+
* for(i = 0; i < num_connections; i++){
|
593
|
+
* cand_sum += weights[i] * neurons[i].value;
|
594
|
+
* }
|
595
|
+
*/
|
596
|
+
/* unrolled loop end */
|
597
|
+
|
598
|
+
max_sum = 150/cand_it->activation_steepness;
|
599
|
+
if(cand_sum > max_sum)
|
600
|
+
cand_sum = max_sum;
|
601
|
+
else if(cand_sum < -max_sum)
|
602
|
+
cand_sum = -max_sum;
|
603
|
+
|
604
|
+
activation =
|
605
|
+
fann_activation(ann, cand_it->activation_function, cand_it->activation_steepness,
|
606
|
+
cand_sum);
|
607
|
+
/* printf("%f = sigmoid(%f);\n", activation, cand_sum); */
|
608
|
+
|
609
|
+
cand_it->sum = cand_sum;
|
610
|
+
cand_it->value = activation;
|
611
|
+
|
612
|
+
derived = fann_activation_derived(cand_it->activation_function,
|
613
|
+
cand_it->activation_steepness, activation, cand_sum);
|
614
|
+
|
615
|
+
/* The output weights is located right after the input weights in
|
616
|
+
* the weight array.
|
617
|
+
*/
|
618
|
+
cand_out_weights = weights + num_connections;
|
619
|
+
|
620
|
+
cand_out_slopes = ann->train_slopes + cand_it->first_con + num_connections;
|
621
|
+
for(j = 0; j < num_output; j++)
|
622
|
+
{
|
623
|
+
diff = (activation * cand_out_weights[j]) - output_train_errors[j];
|
624
|
+
#ifdef CASCADE_DEBUG_FULL
|
625
|
+
/* printf("diff = %f = (%f * %f) - %f;\n", diff, activation, cand_out_weights[j], output_train_errors[j]); */
|
626
|
+
#endif
|
627
|
+
cand_out_slopes[j] -= 2.0f * diff * activation;
|
628
|
+
#ifdef CASCADE_DEBUG_FULL
|
629
|
+
/* printf("cand_out_slopes[%d] <= %f += %f * %f;\n", j, cand_out_slopes[j], diff, activation); */
|
630
|
+
#endif
|
631
|
+
error_value += diff * cand_out_weights[j];
|
632
|
+
cand_score -= (diff * diff);
|
633
|
+
#ifdef CASCADE_DEBUG_FULL
|
634
|
+
/* printf("cand_score[%d][%d] = %f -= (%f * %f)\n", cand_it - first_cand, j, cand_score, diff, diff); */
|
635
|
+
|
636
|
+
printf("cand[%d]: error=%f, activation=%f, diff=%f, slope=%f\n", cand_it - first_cand,
|
637
|
+
output_train_errors[j], (activation * cand_out_weights[j]), diff,
|
638
|
+
-2.0 * diff * activation);
|
639
|
+
#endif
|
640
|
+
}
|
641
|
+
|
642
|
+
ann->cascade_candidate_scores[cand_it - first_cand] = cand_score;
|
643
|
+
error_value *= derived;
|
644
|
+
|
645
|
+
cand_slopes = ann->train_slopes + cand_it->first_con;
|
646
|
+
for(i = 0; i < num_connections; i++)
|
647
|
+
{
|
648
|
+
cand_slopes[i] -= error_value * neurons[i].value;
|
649
|
+
}
|
650
|
+
}
|
651
|
+
}
|
652
|
+
|
653
|
+
void fann_update_candidate_weights(struct fann *ann, unsigned int num_data)
|
654
|
+
{
|
655
|
+
struct fann_neuron *first_cand = (ann->last_layer - 1)->last_neuron + 1; /* there is an empty neuron between the actual neurons and the candidate neuron */
|
656
|
+
struct fann_neuron *last_cand = first_cand + fann_get_cascade_num_candidates(ann) - 1;
|
657
|
+
|
658
|
+
switch (ann->training_algorithm)
|
659
|
+
{
|
660
|
+
case FANN_TRAIN_RPROP:
|
661
|
+
fann_update_weights_irpropm(ann, first_cand->first_con,
|
662
|
+
last_cand->last_con + ann->num_output);
|
663
|
+
break;
|
664
|
+
case FANN_TRAIN_QUICKPROP:
|
665
|
+
fann_update_weights_quickprop(ann, num_data, first_cand->first_con,
|
666
|
+
last_cand->last_con + ann->num_output);
|
667
|
+
break;
|
668
|
+
case FANN_TRAIN_BATCH:
|
669
|
+
case FANN_TRAIN_INCREMENTAL:
|
670
|
+
fann_error((struct fann_error *) ann, FANN_E_CANT_USE_TRAIN_ALG);
|
671
|
+
break;
|
672
|
+
}
|
673
|
+
}
|
674
|
+
|
675
|
+
fann_type fann_train_candidates_epoch(struct fann *ann, struct fann_train_data *data)
|
676
|
+
{
|
677
|
+
unsigned int i, j;
|
678
|
+
unsigned int best_candidate;
|
679
|
+
fann_type best_score;
|
680
|
+
unsigned int num_cand = fann_get_cascade_num_candidates(ann);
|
681
|
+
fann_type *output_train_errors = ann->train_errors + (ann->total_neurons - ann->num_output);
|
682
|
+
struct fann_neuron *output_neurons = (ann->last_layer - 1)->first_neuron;
|
683
|
+
|
684
|
+
for(i = 0; i < num_cand; i++)
|
685
|
+
{
|
686
|
+
/* The ann->MSE_value is actually the sum squared error */
|
687
|
+
ann->cascade_candidate_scores[i] = ann->MSE_value;
|
688
|
+
}
|
689
|
+
/*printf("start score: %f\n", ann->MSE_value); */
|
690
|
+
|
691
|
+
for(i = 0; i < data->num_data; i++)
|
692
|
+
{
|
693
|
+
fann_run(ann, data->input[i]);
|
694
|
+
|
695
|
+
for(j = 0; j < ann->num_output; j++)
|
696
|
+
{
|
697
|
+
/* TODO only debug, but the error is in opposite direction, this might be usefull info */
|
698
|
+
/* if(output_train_errors[j] != (ann->output[j] - data->output[i][j])){
|
699
|
+
* printf("difference in calculated error at %f != %f; %f = %f - %f;\n", output_train_errors[j], (ann->output[j] - data->output[i][j]), output_train_errors[j], ann->output[j], data->output[i][j]);
|
700
|
+
* } */
|
701
|
+
|
702
|
+
/*
|
703
|
+
* output_train_errors[j] = (data->output[i][j] - ann->output[j])/2;
|
704
|
+
* output_train_errors[j] = ann->output[j] - data->output[i][j];
|
705
|
+
*/
|
706
|
+
|
707
|
+
output_train_errors[j] = (data->output[i][j] - ann->output[j]);
|
708
|
+
|
709
|
+
switch (output_neurons[j].activation_function)
|
710
|
+
{
|
711
|
+
case FANN_LINEAR_PIECE_SYMMETRIC:
|
712
|
+
case FANN_SIGMOID_SYMMETRIC:
|
713
|
+
case FANN_SIGMOID_SYMMETRIC_STEPWISE:
|
714
|
+
case FANN_THRESHOLD_SYMMETRIC:
|
715
|
+
case FANN_ELLIOT_SYMMETRIC:
|
716
|
+
case FANN_GAUSSIAN_SYMMETRIC:
|
717
|
+
case FANN_SIN_SYMMETRIC:
|
718
|
+
case FANN_COS_SYMMETRIC:
|
719
|
+
output_train_errors[j] /= 2.0;
|
720
|
+
break;
|
721
|
+
case FANN_LINEAR:
|
722
|
+
case FANN_THRESHOLD:
|
723
|
+
case FANN_SIGMOID:
|
724
|
+
case FANN_SIGMOID_STEPWISE:
|
725
|
+
case FANN_GAUSSIAN:
|
726
|
+
case FANN_GAUSSIAN_STEPWISE:
|
727
|
+
case FANN_ELLIOT:
|
728
|
+
case FANN_LINEAR_PIECE:
|
729
|
+
case FANN_SIN:
|
730
|
+
case FANN_COS:
|
731
|
+
break;
|
732
|
+
}
|
733
|
+
}
|
734
|
+
|
735
|
+
fann_update_candidate_slopes(ann);
|
736
|
+
}
|
737
|
+
|
738
|
+
fann_update_candidate_weights(ann, data->num_data);
|
739
|
+
|
740
|
+
/* find the best candidate score */
|
741
|
+
best_candidate = 0;
|
742
|
+
best_score = ann->cascade_candidate_scores[best_candidate];
|
743
|
+
for(i = 1; i < num_cand; i++)
|
744
|
+
{
|
745
|
+
/*struct fann_neuron *cand = ann->first_layer->first_neuron + ann->total_neurons + 1 + i;
|
746
|
+
* printf("candidate[%d] = activation: %s, steepness: %f, score: %f\n",
|
747
|
+
* i, FANN_ACTIVATIONFUNC_NAMES[cand->activation_function],
|
748
|
+
* cand->activation_steepness, ann->cascade_candidate_scores[i]); */
|
749
|
+
|
750
|
+
if(ann->cascade_candidate_scores[i] > best_score)
|
751
|
+
{
|
752
|
+
best_candidate = i;
|
753
|
+
best_score = ann->cascade_candidate_scores[best_candidate];
|
754
|
+
}
|
755
|
+
}
|
756
|
+
|
757
|
+
ann->cascade_best_candidate = ann->total_neurons + best_candidate + 1;
|
758
|
+
#ifdef CASCADE_DEBUG_FULL
|
759
|
+
printf("Best candidate[%d]: with score %f, real score: %f\n", best_candidate,
|
760
|
+
ann->MSE_value - best_score, best_score);
|
761
|
+
#endif
|
762
|
+
|
763
|
+
return best_score;
|
764
|
+
}
|
765
|
+
|
766
|
+
/* add a layer ad the position pointed to by *layer */
|
767
|
+
struct fann_layer *fann_add_layer(struct fann *ann, struct fann_layer *layer)
|
768
|
+
{
|
769
|
+
int layer_pos = layer - ann->first_layer;
|
770
|
+
int num_layers = ann->last_layer - ann->first_layer + 1;
|
771
|
+
int i;
|
772
|
+
|
773
|
+
/* allocate the layer */
|
774
|
+
struct fann_layer *layers =
|
775
|
+
(struct fann_layer *) realloc(ann->first_layer, num_layers * sizeof(struct fann_layer));
|
776
|
+
if(layers == NULL)
|
777
|
+
{
|
778
|
+
fann_error((struct fann_error *) ann, FANN_E_CANT_ALLOCATE_MEM);
|
779
|
+
return NULL;
|
780
|
+
}
|
781
|
+
|
782
|
+
/* copy layers so that the free space is at the right location */
|
783
|
+
for(i = num_layers - 1; i >= layer_pos; i--)
|
784
|
+
{
|
785
|
+
layers[i] = layers[i - 1];
|
786
|
+
}
|
787
|
+
|
788
|
+
/* the newly allocated layer is empty */
|
789
|
+
layers[layer_pos].first_neuron = layers[layer_pos + 1].first_neuron;
|
790
|
+
layers[layer_pos].last_neuron = layers[layer_pos + 1].first_neuron;
|
791
|
+
|
792
|
+
/* Set the ann pointers correctly */
|
793
|
+
ann->first_layer = layers;
|
794
|
+
ann->last_layer = layers + num_layers;
|
795
|
+
|
796
|
+
#ifdef CASCADE_DEBUG_FULL
|
797
|
+
printf("add layer at pos %d\n", layer_pos);
|
798
|
+
#endif
|
799
|
+
|
800
|
+
return layers + layer_pos;
|
801
|
+
}
|
802
|
+
|
803
|
+
void fann_set_shortcut_connections(struct fann *ann)
|
804
|
+
{
|
805
|
+
struct fann_layer *layer_it;
|
806
|
+
struct fann_neuron *neuron_it, **neuron_pointers, *neurons;
|
807
|
+
unsigned int num_connections = 0, i;
|
808
|
+
|
809
|
+
neuron_pointers = ann->connections;
|
810
|
+
neurons = ann->first_layer->first_neuron;
|
811
|
+
|
812
|
+
for(layer_it = ann->first_layer + 1; layer_it != ann->last_layer; layer_it++)
|
813
|
+
{
|
814
|
+
for(neuron_it = layer_it->first_neuron; neuron_it != layer_it->last_neuron; neuron_it++)
|
815
|
+
{
|
816
|
+
|
817
|
+
neuron_pointers += num_connections;
|
818
|
+
num_connections = neuron_it->last_con - neuron_it->first_con;
|
819
|
+
|
820
|
+
for(i = 0; i != num_connections; i++)
|
821
|
+
{
|
822
|
+
neuron_pointers[i] = neurons + i;
|
823
|
+
}
|
824
|
+
}
|
825
|
+
}
|
826
|
+
}
|
827
|
+
|
828
|
+
void fann_add_candidate_neuron(struct fann *ann, struct fann_layer *layer)
|
829
|
+
{
|
830
|
+
unsigned int num_connections_in = layer->first_neuron - ann->first_layer->first_neuron;
|
831
|
+
unsigned int num_connections_out =
|
832
|
+
(ann->last_layer - 1)->last_neuron - (layer + 1)->first_neuron;
|
833
|
+
unsigned int num_connections_move = num_connections_out + num_connections_in;
|
834
|
+
|
835
|
+
unsigned int candidate_con, candidate_output_weight;
|
836
|
+
int i;
|
837
|
+
|
838
|
+
struct fann_layer *layer_it;
|
839
|
+
struct fann_neuron *neuron_it, *neuron_place, *candidate;
|
840
|
+
|
841
|
+
/* We know that there is enough room for the new neuron
|
842
|
+
* (the candidates are in the same arrays), so move
|
843
|
+
* the last neurons to make room for this neuron.
|
844
|
+
*/
|
845
|
+
|
846
|
+
/* first move the pointers to neurons in the layer structs */
|
847
|
+
for(layer_it = ann->last_layer - 1; layer_it != layer; layer_it--)
|
848
|
+
{
|
849
|
+
#ifdef CASCADE_DEBUG_FULL
|
850
|
+
printf("move neuron pointers in layer %d, first(%d -> %d), last(%d -> %d)\n",
|
851
|
+
layer_it - ann->first_layer,
|
852
|
+
layer_it->first_neuron - ann->first_layer->first_neuron,
|
853
|
+
layer_it->first_neuron - ann->first_layer->first_neuron + 1,
|
854
|
+
layer_it->last_neuron - ann->first_layer->first_neuron,
|
855
|
+
layer_it->last_neuron - ann->first_layer->first_neuron + 1);
|
856
|
+
#endif
|
857
|
+
layer_it->first_neuron++;
|
858
|
+
layer_it->last_neuron++;
|
859
|
+
}
|
860
|
+
|
861
|
+
/* also move the last neuron in the layer that needs the neuron added */
|
862
|
+
layer->last_neuron++;
|
863
|
+
|
864
|
+
/* this is the place that should hold the new neuron */
|
865
|
+
neuron_place = layer->last_neuron - 1;
|
866
|
+
|
867
|
+
#ifdef CASCADE_DEBUG_FULL
|
868
|
+
printf("num_connections_in=%d, num_connections_out=%d\n", num_connections_in,
|
869
|
+
num_connections_out);
|
870
|
+
#endif
|
871
|
+
|
872
|
+
candidate = ann->first_layer->first_neuron + ann->cascade_best_candidate;
|
873
|
+
|
874
|
+
/* the output weights for the candidates are located after the input weights */
|
875
|
+
candidate_output_weight = candidate->last_con;
|
876
|
+
|
877
|
+
/* move the actual output neurons and the indexes to the connection arrays */
|
878
|
+
for(neuron_it = (ann->last_layer - 1)->last_neuron - 1; neuron_it != neuron_place; neuron_it--)
|
879
|
+
{
|
880
|
+
#ifdef CASCADE_DEBUG_FULL
|
881
|
+
printf("move neuron %d -> %d\n", neuron_it - ann->first_layer->first_neuron - 1,
|
882
|
+
neuron_it - ann->first_layer->first_neuron);
|
883
|
+
#endif
|
884
|
+
*neuron_it = *(neuron_it - 1);
|
885
|
+
|
886
|
+
/* move the weights */
|
887
|
+
#ifdef CASCADE_DEBUG_FULL
|
888
|
+
printf("move weight[%d ... %d] -> weight[%d ... %d]\n", neuron_it->first_con,
|
889
|
+
neuron_it->last_con - 1, neuron_it->first_con + num_connections_move - 1,
|
890
|
+
neuron_it->last_con + num_connections_move - 2);
|
891
|
+
#endif
|
892
|
+
for(i = neuron_it->last_con - 1; i >= (int)neuron_it->first_con; i--)
|
893
|
+
{
|
894
|
+
#ifdef CASCADE_DEBUG_FULL
|
895
|
+
printf("move weight[%d] = weight[%d]\n", i + num_connections_move - 1, i);
|
896
|
+
#endif
|
897
|
+
ann->weights[i + num_connections_move - 1] = ann->weights[i];
|
898
|
+
}
|
899
|
+
|
900
|
+
/* move the indexes to weights */
|
901
|
+
neuron_it->last_con += num_connections_move;
|
902
|
+
num_connections_move--;
|
903
|
+
neuron_it->first_con += num_connections_move;
|
904
|
+
|
905
|
+
/* set the new weight to the newly allocated neuron */
|
906
|
+
ann->weights[neuron_it->last_con - 1] =
|
907
|
+
(ann->weights[candidate_output_weight]) * ann->cascade_weight_multiplier;
|
908
|
+
candidate_output_weight++;
|
909
|
+
}
|
910
|
+
|
911
|
+
/* Now inititalize the actual neuron */
|
912
|
+
neuron_place->value = 0;
|
913
|
+
neuron_place->sum = 0;
|
914
|
+
neuron_place->activation_function = candidate->activation_function;
|
915
|
+
neuron_place->activation_steepness = candidate->activation_steepness;
|
916
|
+
neuron_place->last_con = (neuron_place + 1)->first_con;
|
917
|
+
neuron_place->first_con = neuron_place->last_con - num_connections_in;
|
918
|
+
#ifdef CASCADE_DEBUG_FULL
|
919
|
+
printf("neuron[%d] = weights[%d ... %d] activation: %s, steepness: %f\n",
|
920
|
+
neuron_place - ann->first_layer->first_neuron, neuron_place->first_con,
|
921
|
+
neuron_place->last_con - 1, FANN_ACTIVATIONFUNC_NAMES[neuron_place->activation_function],
|
922
|
+
neuron_place->activation_steepness);/* TODO remove */
|
923
|
+
#endif
|
924
|
+
|
925
|
+
candidate_con = candidate->first_con;
|
926
|
+
/* initialize the input weights at random */
|
927
|
+
#ifdef CASCADE_DEBUG_FULL
|
928
|
+
printf("move cand weights[%d ... %d] -> [%d ... %d]\n", candidate_con,
|
929
|
+
candidate_con + num_connections_in - 1, neuron_place->first_con,
|
930
|
+
neuron_place->last_con - 1);
|
931
|
+
#endif
|
932
|
+
|
933
|
+
for(i = 0; i < (int)num_connections_in; i++)
|
934
|
+
{
|
935
|
+
ann->weights[i + neuron_place->first_con] = ann->weights[i + candidate_con];
|
936
|
+
#ifdef CASCADE_DEBUG_FULL
|
937
|
+
printf("move weights[%d] -> weights[%d] (%f)\n", i + candidate_con,
|
938
|
+
i + neuron_place->first_con, ann->weights[i + neuron_place->first_con]);
|
939
|
+
#endif
|
940
|
+
}
|
941
|
+
|
942
|
+
/* Change some of main variables */
|
943
|
+
ann->total_neurons++;
|
944
|
+
ann->total_connections += num_connections_in + num_connections_out;
|
945
|
+
|
946
|
+
return;
|
947
|
+
}
|
948
|
+
|
949
|
+
void fann_install_candidate(struct fann *ann)
|
950
|
+
{
|
951
|
+
struct fann_layer *layer;
|
952
|
+
|
953
|
+
layer = fann_add_layer(ann, ann->last_layer - 1);
|
954
|
+
fann_add_candidate_neuron(ann, layer);
|
955
|
+
return;
|
956
|
+
}
|
957
|
+
|
958
|
+
#endif /* FIXEDFANN */
|
959
|
+
|
960
|
+
FANN_EXTERNAL unsigned int FANN_API fann_get_cascade_num_candidates(struct fann *ann)
|
961
|
+
{
|
962
|
+
return ann->cascade_activation_functions_count *
|
963
|
+
ann->cascade_activation_steepnesses_count *
|
964
|
+
ann->cascade_num_candidate_groups;
|
965
|
+
}
|
966
|
+
|
967
|
+
FANN_GET_SET(float, cascade_output_change_fraction)
|
968
|
+
FANN_GET_SET(unsigned int, cascade_output_stagnation_epochs)
|
969
|
+
FANN_GET_SET(float, cascade_candidate_change_fraction)
|
970
|
+
FANN_GET_SET(unsigned int, cascade_candidate_stagnation_epochs)
|
971
|
+
FANN_GET_SET(unsigned int, cascade_num_candidate_groups)
|
972
|
+
FANN_GET_SET(fann_type, cascade_weight_multiplier)
|
973
|
+
FANN_GET_SET(fann_type, cascade_candidate_limit)
|
974
|
+
FANN_GET_SET(unsigned int, cascade_max_out_epochs)
|
975
|
+
FANN_GET_SET(unsigned int, cascade_max_cand_epochs)
|
976
|
+
|
977
|
+
FANN_GET(unsigned int, cascade_activation_functions_count)
|
978
|
+
FANN_GET(enum fann_activationfunc_enum *, cascade_activation_functions)
|
979
|
+
|
980
|
+
FANN_EXTERNAL void FANN_API fann_set_cascade_activation_functions(struct fann *ann,
|
981
|
+
enum fann_activationfunc_enum *
|
982
|
+
cascade_activation_functions,
|
983
|
+
unsigned int
|
984
|
+
cascade_activation_functions_count)
|
985
|
+
{
|
986
|
+
if(ann->cascade_activation_functions_count != cascade_activation_functions_count)
|
987
|
+
{
|
988
|
+
ann->cascade_activation_functions_count = cascade_activation_functions_count;
|
989
|
+
|
990
|
+
/* reallocate mem */
|
991
|
+
ann->cascade_activation_functions =
|
992
|
+
(enum fann_activationfunc_enum *)realloc(ann->cascade_activation_functions,
|
993
|
+
ann->cascade_activation_functions_count * sizeof(enum fann_activationfunc_enum));
|
994
|
+
if(ann->cascade_activation_functions == NULL)
|
995
|
+
{
|
996
|
+
fann_error((struct fann_error*)ann, FANN_E_CANT_ALLOCATE_MEM);
|
997
|
+
return;
|
998
|
+
}
|
999
|
+
}
|
1000
|
+
|
1001
|
+
memmove(ann->cascade_activation_functions, cascade_activation_functions,
|
1002
|
+
ann->cascade_activation_functions_count * sizeof(enum fann_activationfunc_enum));
|
1003
|
+
}
|
1004
|
+
|
1005
|
+
FANN_GET(unsigned int, cascade_activation_steepnesses_count)
|
1006
|
+
FANN_GET(fann_type *, cascade_activation_steepnesses)
|
1007
|
+
|
1008
|
+
FANN_EXTERNAL void FANN_API fann_set_cascade_activation_steepnesses(struct fann *ann,
|
1009
|
+
fann_type *
|
1010
|
+
cascade_activation_steepnesses,
|
1011
|
+
unsigned int
|
1012
|
+
cascade_activation_steepnesses_count)
|
1013
|
+
{
|
1014
|
+
if(ann->cascade_activation_steepnesses_count != cascade_activation_steepnesses_count)
|
1015
|
+
{
|
1016
|
+
ann->cascade_activation_steepnesses_count = cascade_activation_steepnesses_count;
|
1017
|
+
|
1018
|
+
/* reallocate mem */
|
1019
|
+
ann->cascade_activation_steepnesses =
|
1020
|
+
(fann_type *)realloc(ann->cascade_activation_steepnesses,
|
1021
|
+
ann->cascade_activation_steepnesses_count * sizeof(fann_type));
|
1022
|
+
if(ann->cascade_activation_steepnesses == NULL)
|
1023
|
+
{
|
1024
|
+
fann_error((struct fann_error*)ann, FANN_E_CANT_ALLOCATE_MEM);
|
1025
|
+
return;
|
1026
|
+
}
|
1027
|
+
}
|
1028
|
+
|
1029
|
+
memmove(ann->cascade_activation_steepnesses, cascade_activation_steepnesses,
|
1030
|
+
ann->cascade_activation_steepnesses_count * sizeof(fann_type));
|
1031
|
+
}
|