/* Fast Artificial Neural Network Library (fann) Copyright (C) 2003-2016 Steffen Nissen (steffen.fann@gmail.com) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include "config.h" #include "fann.h" #include "fann_data.h" /* Create a network from a configuration file. */ FANN_EXTERNAL struct fann *FANN_API fann_create_from_file(const char *configuration_file) { struct fann *ann; FILE *conf = fopen(configuration_file, "r"); if(!conf) { fann_error(NULL, FANN_E_CANT_OPEN_CONFIG_R, configuration_file); return NULL; } ann = fann_create_from_fd(conf, configuration_file); fclose(conf); return ann; } /* Save the network. */ FANN_EXTERNAL int FANN_API fann_save(struct fann *ann, const char *configuration_file) { return fann_save_internal(ann, configuration_file, 0); } /* Save the network as fixed point data. */ FANN_EXTERNAL int FANN_API fann_save_to_fixed(struct fann *ann, const char *configuration_file) { return fann_save_internal(ann, configuration_file, 1); } /* INTERNAL FUNCTION Used to save the network to a file. */ int fann_save_internal(struct fann *ann, const char *configuration_file, unsigned int save_as_fixed) { int retval; FILE *conf = fopen(configuration_file, "w+"); if(!conf) { fann_error((struct fann_error *) ann, FANN_E_CANT_OPEN_CONFIG_W, configuration_file); return -1; } retval = fann_save_internal_fd(ann, conf, configuration_file, save_as_fixed); fclose(conf); return retval; } /* INTERNAL FUNCTION Used to save the network to a file descriptor. */ int fann_save_internal_fd(struct fann *ann, FILE * conf, const char *configuration_file, unsigned int save_as_fixed) { struct fann_layer *layer_it; int calculated_decimal_point = 0; struct fann_neuron *neuron_it, *first_neuron; fann_type *weights; struct fann_neuron **connected_neurons; unsigned int i = 0; #ifndef FIXEDFANN /* variabels for use when saving floats as fixed point variabels */ unsigned int decimal_point = 0; unsigned int fixed_multiplier = 0; fann_type max_possible_value = 0; unsigned int bits_used_for_max = 0; fann_type current_max_value = 0; #endif #ifndef FIXEDFANN if(save_as_fixed) { /* save the version information */ fprintf(conf, FANN_FIX_VERSION "\n"); } else { /* save the version information */ fprintf(conf, FANN_FLO_VERSION "\n"); } #else /* save the version information */ fprintf(conf, FANN_FIX_VERSION "\n"); #endif #ifndef FIXEDFANN if(save_as_fixed) { /* calculate the maximal possible shift value */ for(layer_it = ann->first_layer + 1; layer_it != ann->last_layer; layer_it++) { for(neuron_it = layer_it->first_neuron; neuron_it != layer_it->last_neuron; neuron_it++) { /* look at all connections to each neurons, and see how high a value we can get */ current_max_value = 0; for(i = neuron_it->first_con; i != neuron_it->last_con; i++) { current_max_value += fann_abs(ann->weights[i]); } if(current_max_value > max_possible_value) { max_possible_value = current_max_value; } } } for(bits_used_for_max = 0; max_possible_value >= 1; bits_used_for_max++) { max_possible_value /= 2.0; } /* The maximum number of bits we shift the fix point, is the number * of bits in a integer, minus one for the sign, one for the minus * in stepwise, and minus the bits used for the maximum. * This is devided by two, to allow multiplication of two fixed * point numbers. */ calculated_decimal_point = (sizeof(int) * 8 - 2 - bits_used_for_max) / 2; if(calculated_decimal_point < 0) { decimal_point = 0; } else { decimal_point = calculated_decimal_point; } fixed_multiplier = 1 << decimal_point; #ifdef DEBUG printf("calculated_decimal_point=%d, decimal_point=%u, bits_used_for_max=%u\n", calculated_decimal_point, decimal_point, bits_used_for_max); #endif /* save the decimal_point on a seperate line */ fprintf(conf, "decimal_point=%u\n", decimal_point); } #else /* save the decimal_point on a seperate line */ fprintf(conf, "decimal_point=%u\n", ann->decimal_point); #endif /* Save network parameters */ fprintf(conf, "num_layers=%d\n", (int)(ann->last_layer - ann->first_layer)); fprintf(conf, "learning_rate=%f\n", ann->learning_rate); fprintf(conf, "connection_rate=%f\n", ann->connection_rate); fprintf(conf, "network_type=%u\n", ann->network_type); fprintf(conf, "learning_momentum=%f\n", ann->learning_momentum); fprintf(conf, "training_algorithm=%u\n", ann->training_algorithm); fprintf(conf, "train_error_function=%u\n", ann->train_error_function); fprintf(conf, "train_stop_function=%u\n", ann->train_stop_function); fprintf(conf, "cascade_output_change_fraction=%f\n", ann->cascade_output_change_fraction); fprintf(conf, "quickprop_decay=%f\n", ann->quickprop_decay); fprintf(conf, "quickprop_mu=%f\n", ann->quickprop_mu); fprintf(conf, "rprop_increase_factor=%f\n", ann->rprop_increase_factor); fprintf(conf, "rprop_decrease_factor=%f\n", ann->rprop_decrease_factor); fprintf(conf, "rprop_delta_min=%f\n", ann->rprop_delta_min); fprintf(conf, "rprop_delta_max=%f\n", ann->rprop_delta_max); fprintf(conf, "rprop_delta_zero=%f\n", ann->rprop_delta_zero); fprintf(conf, "cascade_output_stagnation_epochs=%u\n", ann->cascade_output_stagnation_epochs); fprintf(conf, "cascade_candidate_change_fraction=%f\n", ann->cascade_candidate_change_fraction); fprintf(conf, "cascade_candidate_stagnation_epochs=%u\n", ann->cascade_candidate_stagnation_epochs); fprintf(conf, "cascade_max_out_epochs=%u\n", ann->cascade_max_out_epochs); fprintf(conf, "cascade_min_out_epochs=%u\n", ann->cascade_min_out_epochs); fprintf(conf, "cascade_max_cand_epochs=%u\n", ann->cascade_max_cand_epochs); fprintf(conf, "cascade_min_cand_epochs=%u\n", ann->cascade_min_cand_epochs); fprintf(conf, "cascade_num_candidate_groups=%u\n", ann->cascade_num_candidate_groups); #ifndef FIXEDFANN if(save_as_fixed) { fprintf(conf, "bit_fail_limit=%u\n", (int) floor((ann->bit_fail_limit * fixed_multiplier) + 0.5)); fprintf(conf, "cascade_candidate_limit=%u\n", (int) floor((ann->cascade_candidate_limit * fixed_multiplier) + 0.5)); fprintf(conf, "cascade_weight_multiplier=%u\n", (int) floor((ann->cascade_weight_multiplier * fixed_multiplier) + 0.5)); } else #endif { fprintf(conf, "bit_fail_limit="FANNPRINTF"\n", ann->bit_fail_limit); fprintf(conf, "cascade_candidate_limit="FANNPRINTF"\n", ann->cascade_candidate_limit); fprintf(conf, "cascade_weight_multiplier="FANNPRINTF"\n", ann->cascade_weight_multiplier); } fprintf(conf, "cascade_activation_functions_count=%u\n", ann->cascade_activation_functions_count); fprintf(conf, "cascade_activation_functions="); for(i = 0; i < ann->cascade_activation_functions_count; i++) fprintf(conf, "%u ", ann->cascade_activation_functions[i]); fprintf(conf, "\n"); fprintf(conf, "cascade_activation_steepnesses_count=%u\n", ann->cascade_activation_steepnesses_count); fprintf(conf, "cascade_activation_steepnesses="); for(i = 0; i < ann->cascade_activation_steepnesses_count; i++) { #ifndef FIXEDFANN if(save_as_fixed) fprintf(conf, "%u ", (int) floor((ann->cascade_activation_steepnesses[i] * fixed_multiplier) + 0.5)); else #endif fprintf(conf, FANNPRINTF" ", ann->cascade_activation_steepnesses[i]); } fprintf(conf, "\n"); fprintf(conf, "layer_sizes="); for(layer_it = ann->first_layer; layer_it != ann->last_layer; layer_it++) { /* the number of neurons in the layers (in the last layer, there is always one too many neurons, because of an unused bias) */ fprintf(conf, "%d ", (int)(layer_it->last_neuron - layer_it->first_neuron)); } fprintf(conf, "\n"); #ifndef FIXEDFANN /* 2.1 */ #define SCALE_SAVE( what, where ) \ fprintf( conf, #what "_" #where "=" ); \ for( i = 0; i < ann->num_##where##put; i++ ) \ fprintf( conf, "%f ", ann->what##_##where[ i ] ); \ fprintf( conf, "\n" ); if(!save_as_fixed) { if(ann->scale_mean_in != NULL) { fprintf(conf, "scale_included=1\n"); SCALE_SAVE( scale_mean, in ) SCALE_SAVE( scale_deviation, in ) SCALE_SAVE( scale_new_min, in ) SCALE_SAVE( scale_factor, in ) SCALE_SAVE( scale_mean, out ) SCALE_SAVE( scale_deviation, out ) SCALE_SAVE( scale_new_min, out ) SCALE_SAVE( scale_factor, out ) } else fprintf(conf, "scale_included=0\n"); } #undef SCALE_SAVE #endif /* 2.0 */ fprintf(conf, "neurons (num_inputs, activation_function, activation_steepness)="); for(layer_it = ann->first_layer; layer_it != ann->last_layer; layer_it++) { /* the neurons */ for(neuron_it = layer_it->first_neuron; neuron_it != layer_it->last_neuron; neuron_it++) { #ifndef FIXEDFANN if(save_as_fixed) { fprintf(conf, "(%u, %u, %u) ", neuron_it->last_con - neuron_it->first_con, neuron_it->activation_function, (int) floor((neuron_it->activation_steepness * fixed_multiplier) + 0.5)); } else { fprintf(conf, "(%u, %u, " FANNPRINTF ") ", neuron_it->last_con - neuron_it->first_con, neuron_it->activation_function, neuron_it->activation_steepness); } #else fprintf(conf, "(%u, %u, " FANNPRINTF ") ", neuron_it->last_con - neuron_it->first_con, neuron_it->activation_function, neuron_it->activation_steepness); #endif } } fprintf(conf, "\n"); connected_neurons = ann->connections; weights = ann->weights; first_neuron = ann->first_layer->first_neuron; /* Now save all the connections. * We only need to save the source and the weight, * since the destination is given by the order. * * The weight is not saved binary due to differences * in binary definition of floating point numbers. * Especially an iPAQ does not use the same binary * representation as an i386 machine. */ fprintf(conf, "connections (connected_to_neuron, weight)="); for(i = 0; i < ann->total_connections; i++) { #ifndef FIXEDFANN if(save_as_fixed) { /* save the connection "(source weight) " */ fprintf(conf, "(%d, %d) ", (int)(connected_neurons[i] - first_neuron), (int) floor((weights[i] * fixed_multiplier) + 0.5)); } else { /* save the connection "(source weight) " */ fprintf(conf, "(%d, " FANNPRINTF ") ", (int)(connected_neurons[i] - first_neuron), weights[i]); } #else /* save the connection "(source weight) " */ fprintf(conf, "(%d, " FANNPRINTF ") ", (int)(connected_neurons[i] - first_neuron), weights[i]); #endif } fprintf(conf, "\n"); return calculated_decimal_point; } struct fann *fann_create_from_fd_1_1(FILE * conf, const char *configuration_file); #define fann_scanf(type, name, val) \ { \ if(fscanf(conf, name"="type"\n", val) != 1) \ { \ fann_error(NULL, FANN_E_CANT_READ_CONFIG, name, configuration_file); \ fann_destroy(ann); \ return NULL; \ } \ } #define fann_skip(name) \ { \ if(fscanf(conf, name) != 0) \ { \ fann_error(NULL, FANN_E_CANT_READ_CONFIG, name, configuration_file); \ fann_destroy(ann); \ return NULL; \ } \ } /* INTERNAL FUNCTION Create a network from a configuration file descriptor. */ struct fann *fann_create_from_fd(FILE * conf, const char *configuration_file) { unsigned int num_layers, layer_size, input_neuron, i, num_connections; unsigned int tmpVal; #ifdef FIXEDFANN unsigned int decimal_point, multiplier; #else unsigned int scale_included; #endif struct fann_neuron *first_neuron, *neuron_it, *last_neuron, **connected_neurons; fann_type *weights; struct fann_layer *layer_it; struct fann *ann = NULL; char *read_version; read_version = (char *) calloc(strlen(FANN_CONF_VERSION "\n"), 1); if(read_version == NULL) { fann_error(NULL, FANN_E_CANT_ALLOCATE_MEM); return NULL; } if(fread(read_version, 1, strlen(FANN_CONF_VERSION "\n"), conf) == 1) { fann_error(NULL, FANN_E_CANT_READ_CONFIG, "FANN_VERSION", configuration_file); return NULL; } /* compares the version information */ if(strncmp(read_version, FANN_CONF_VERSION "\n", strlen(FANN_CONF_VERSION "\n")) != 0) { #ifdef FIXEDFANN if(strncmp(read_version, "FANN_FIX_1.1\n", strlen("FANN_FIX_1.1\n")) == 0) { #else if(strncmp(read_version, "FANN_FLO_1.1\n", strlen("FANN_FLO_1.1\n")) == 0) { #endif free(read_version); return fann_create_from_fd_1_1(conf, configuration_file); } #ifndef FIXEDFANN /* Maintain compatibility with 2.0 version that doesnt have scale parameters. */ if(strncmp(read_version, "FANN_FLO_2.0\n", strlen("FANN_FLO_2.0\n")) != 0 && strncmp(read_version, "FANN_FLO_2.1\n", strlen("FANN_FLO_2.1\n")) != 0) #else if(strncmp(read_version, "FANN_FIX_2.0\n", strlen("FANN_FIX_2.0\n")) != 0 && strncmp(read_version, "FANN_FIX_2.1\n", strlen("FANN_FIX_2.1\n")) != 0) #endif { free(read_version); fann_error(NULL, FANN_E_WRONG_CONFIG_VERSION, configuration_file); return NULL; } } free(read_version); #ifdef FIXEDFANN fann_scanf("%u", "decimal_point", &decimal_point); multiplier = 1 << decimal_point; #endif fann_scanf("%u", "num_layers", &num_layers); ann = fann_allocate_structure(num_layers); if(ann == NULL) { return NULL; } fann_scanf("%f", "learning_rate", &ann->learning_rate); fann_scanf("%f", "connection_rate", &ann->connection_rate); fann_scanf("%u", "network_type", &tmpVal); ann->network_type = (enum fann_nettype_enum)tmpVal; fann_scanf("%f", "learning_momentum", &ann->learning_momentum); fann_scanf("%u", "training_algorithm", &tmpVal); ann->training_algorithm = (enum fann_train_enum)tmpVal; fann_scanf("%u", "train_error_function", &tmpVal); ann->train_error_function = (enum fann_errorfunc_enum)tmpVal; fann_scanf("%u", "train_stop_function", &tmpVal); ann->train_stop_function = (enum fann_stopfunc_enum)tmpVal; fann_scanf("%f", "cascade_output_change_fraction", &ann->cascade_output_change_fraction); fann_scanf("%f", "quickprop_decay", &ann->quickprop_decay); fann_scanf("%f", "quickprop_mu", &ann->quickprop_mu); fann_scanf("%f", "rprop_increase_factor", &ann->rprop_increase_factor); fann_scanf("%f", "rprop_decrease_factor", &ann->rprop_decrease_factor); fann_scanf("%f", "rprop_delta_min", &ann->rprop_delta_min); fann_scanf("%f", "rprop_delta_max", &ann->rprop_delta_max); fann_scanf("%f", "rprop_delta_zero", &ann->rprop_delta_zero); fann_scanf("%u", "cascade_output_stagnation_epochs", &ann->cascade_output_stagnation_epochs); fann_scanf("%f", "cascade_candidate_change_fraction", &ann->cascade_candidate_change_fraction); fann_scanf("%u", "cascade_candidate_stagnation_epochs", &ann->cascade_candidate_stagnation_epochs); fann_scanf("%u", "cascade_max_out_epochs", &ann->cascade_max_out_epochs); fann_scanf("%u", "cascade_min_out_epochs", &ann->cascade_min_out_epochs); fann_scanf("%u", "cascade_max_cand_epochs", &ann->cascade_max_cand_epochs); fann_scanf("%u", "cascade_min_cand_epochs", &ann->cascade_min_cand_epochs); fann_scanf("%u", "cascade_num_candidate_groups", &ann->cascade_num_candidate_groups); fann_scanf(FANNSCANF, "bit_fail_limit", &ann->bit_fail_limit); fann_scanf(FANNSCANF, "cascade_candidate_limit", &ann->cascade_candidate_limit); fann_scanf(FANNSCANF, "cascade_weight_multiplier", &ann->cascade_weight_multiplier); fann_scanf("%u", "cascade_activation_functions_count", &ann->cascade_activation_functions_count); /* reallocate mem */ ann->cascade_activation_functions = (enum fann_activationfunc_enum *)realloc(ann->cascade_activation_functions, ann->cascade_activation_functions_count * sizeof(enum fann_activationfunc_enum)); if(ann->cascade_activation_functions == NULL) { fann_error((struct fann_error*)ann, FANN_E_CANT_ALLOCATE_MEM); fann_destroy(ann); return NULL; } fann_skip("cascade_activation_functions="); for(i = 0; i < ann->cascade_activation_functions_count; i++) { if(fscanf(conf, "%u ", &tmpVal) != 1) { fann_error(NULL, FANN_E_CANT_READ_CONFIG, "cascade_activation_functions", configuration_file); fann_destroy(ann); return NULL; } ann->cascade_activation_functions[i] = (enum fann_activationfunc_enum)tmpVal; } fann_scanf("%u", "cascade_activation_steepnesses_count", &ann->cascade_activation_steepnesses_count); /* reallocate mem */ ann->cascade_activation_steepnesses = (fann_type *)realloc(ann->cascade_activation_steepnesses, ann->cascade_activation_steepnesses_count * sizeof(fann_type)); if(ann->cascade_activation_steepnesses == NULL) { fann_error((struct fann_error*)ann, FANN_E_CANT_ALLOCATE_MEM); fann_destroy(ann); return NULL; } fann_skip("cascade_activation_steepnesses="); for(i = 0; i < ann->cascade_activation_steepnesses_count; i++) { if(fscanf(conf, FANNSCANF" ", &ann->cascade_activation_steepnesses[i]) != 1) { fann_error(NULL, FANN_E_CANT_READ_CONFIG, "cascade_activation_steepnesses", configuration_file); fann_destroy(ann); return NULL; } } #ifdef FIXEDFANN ann->decimal_point = decimal_point; ann->multiplier = multiplier; #endif #ifdef FIXEDFANN fann_update_stepwise(ann); #endif #ifdef DEBUG printf("creating network with %d layers\n", num_layers); printf("input\n"); #endif fann_skip("layer_sizes="); /* determine how many neurons there should be in each layer */ for(layer_it = ann->first_layer; layer_it != ann->last_layer; layer_it++) { if(fscanf(conf, "%u ", &layer_size) != 1) { fann_error((struct fann_error *) ann, FANN_E_CANT_READ_CONFIG, "layer_sizes", configuration_file); fann_destroy(ann); return NULL; } /* we do not allocate room here, but we make sure that * last_neuron - first_neuron is the number of neurons */ layer_it->first_neuron = NULL; layer_it->last_neuron = layer_it->first_neuron + layer_size; ann->total_neurons += layer_size; #ifdef DEBUG if(ann->network_type == FANN_NETTYPE_SHORTCUT && layer_it != ann->first_layer) { printf(" layer : %d neurons, 0 bias\n", layer_size); } else { printf(" layer : %d neurons, 1 bias\n", layer_size - 1); } #endif } ann->num_input = (unsigned int)(ann->first_layer->last_neuron - ann->first_layer->first_neuron - 1); ann->num_output = (unsigned int)((ann->last_layer - 1)->last_neuron - (ann->last_layer - 1)->first_neuron); if(ann->network_type == FANN_NETTYPE_LAYER) { /* one too many (bias) in the output layer */ ann->num_output--; } #ifndef FIXEDFANN #define SCALE_LOAD( what, where ) \ fann_skip( #what "_" #where "=" ); \ for(i = 0; i < ann->num_##where##put; i++) \ { \ if(fscanf( conf, "%f ", (float *)&ann->what##_##where[ i ] ) != 1) \ { \ fann_error((struct fann_error *) ann, FANN_E_CANT_READ_CONFIG, #what "_" #where, configuration_file); \ fann_destroy(ann); \ return NULL; \ } \ } if(fscanf(conf, "scale_included=%u\n", &scale_included) == 1 && scale_included == 1) { fann_allocate_scale(ann); SCALE_LOAD( scale_mean, in ) SCALE_LOAD( scale_deviation, in ) SCALE_LOAD( scale_new_min, in ) SCALE_LOAD( scale_factor, in ) SCALE_LOAD( scale_mean, out ) SCALE_LOAD( scale_deviation, out ) SCALE_LOAD( scale_new_min, out ) SCALE_LOAD( scale_factor, out ) } #undef SCALE_LOAD #endif /* allocate room for the actual neurons */ fann_allocate_neurons(ann); if(ann->errno_f == FANN_E_CANT_ALLOCATE_MEM) { fann_destroy(ann); return NULL; } last_neuron = (ann->last_layer - 1)->last_neuron; fann_skip("neurons (num_inputs, activation_function, activation_steepness)="); for(neuron_it = ann->first_layer->first_neuron; neuron_it != last_neuron; neuron_it++) { if(fscanf (conf, "(%u, %u, " FANNSCANF ") ", &num_connections, &tmpVal, &neuron_it->activation_steepness) != 3) { fann_error((struct fann_error *) ann, FANN_E_CANT_READ_NEURON, configuration_file); fann_destroy(ann); return NULL; } neuron_it->activation_function = (enum fann_activationfunc_enum)tmpVal; neuron_it->first_con = ann->total_connections; ann->total_connections += num_connections; neuron_it->last_con = ann->total_connections; } fann_allocate_connections(ann); if(ann->errno_f == FANN_E_CANT_ALLOCATE_MEM) { fann_destroy(ann); return NULL; } connected_neurons = ann->connections; weights = ann->weights; first_neuron = ann->first_layer->first_neuron; fann_skip("connections (connected_to_neuron, weight)="); for(i = 0; i < ann->total_connections; i++) { if(fscanf(conf, "(%u, " FANNSCANF ") ", &input_neuron, &weights[i]) != 2) { fann_error((struct fann_error *) ann, FANN_E_CANT_READ_CONNECTIONS, configuration_file); fann_destroy(ann); return NULL; } connected_neurons[i] = first_neuron + input_neuron; } #ifdef DEBUG printf("output\n"); #endif return ann; } /* INTERNAL FUNCTION Create a network from a configuration file descriptor. (backward compatible read of version 1.1 files) */ struct fann *fann_create_from_fd_1_1(FILE * conf, const char *configuration_file) { unsigned int num_layers, layer_size, input_neuron, i, network_type, num_connections; unsigned int activation_function_hidden, activation_function_output; #ifdef FIXEDFANN unsigned int decimal_point, multiplier; #endif fann_type activation_steepness_hidden, activation_steepness_output; float learning_rate, connection_rate; struct fann_neuron *first_neuron, *neuron_it, *last_neuron, **connected_neurons; fann_type *weights; struct fann_layer *layer_it; struct fann *ann; #ifdef FIXEDFANN if(fscanf(conf, "%u\n", &decimal_point) != 1) { fann_error(NULL, FANN_E_CANT_READ_CONFIG, "decimal_point", configuration_file); return NULL; } multiplier = 1 << decimal_point; #endif if(fscanf(conf, "%u %f %f %u %u %u " FANNSCANF " " FANNSCANF "\n", &num_layers, &learning_rate, &connection_rate, &network_type, &activation_function_hidden, &activation_function_output, &activation_steepness_hidden, &activation_steepness_output) != 8) { fann_error(NULL, FANN_E_CANT_READ_CONFIG, "parameters", configuration_file); return NULL; } ann = fann_allocate_structure(num_layers); if(ann == NULL) { return NULL; } ann->connection_rate = connection_rate; ann->network_type = (enum fann_nettype_enum)network_type; ann->learning_rate = learning_rate; #ifdef FIXEDFANN ann->decimal_point = decimal_point; ann->multiplier = multiplier; #endif #ifdef FIXEDFANN fann_update_stepwise(ann); #endif #ifdef DEBUG printf("creating network with learning rate %f\n", learning_rate); printf("input\n"); #endif /* determine how many neurons there should be in each layer */ for(layer_it = ann->first_layer; layer_it != ann->last_layer; layer_it++) { if(fscanf(conf, "%u ", &layer_size) != 1) { fann_error((struct fann_error *) ann, FANN_E_CANT_READ_NEURON, configuration_file); fann_destroy(ann); return NULL; } /* we do not allocate room here, but we make sure that * last_neuron - first_neuron is the number of neurons */ layer_it->first_neuron = NULL; layer_it->last_neuron = layer_it->first_neuron + layer_size; ann->total_neurons += layer_size; #ifdef DEBUG if(ann->network_type == FANN_NETTYPE_SHORTCUT && layer_it != ann->first_layer) { printf(" layer : %d neurons, 0 bias\n", layer_size); } else { printf(" layer : %d neurons, 1 bias\n", layer_size - 1); } #endif } ann->num_input = (unsigned int)(ann->first_layer->last_neuron - ann->first_layer->first_neuron - 1); ann->num_output = (unsigned int)((ann->last_layer - 1)->last_neuron - (ann->last_layer - 1)->first_neuron); if(ann->network_type == FANN_NETTYPE_LAYER) { /* one too many (bias) in the output layer */ ann->num_output--; } /* allocate room for the actual neurons */ fann_allocate_neurons(ann); if(ann->errno_f == FANN_E_CANT_ALLOCATE_MEM) { fann_destroy(ann); return NULL; } last_neuron = (ann->last_layer - 1)->last_neuron; for(neuron_it = ann->first_layer->first_neuron; neuron_it != last_neuron; neuron_it++) { if(fscanf(conf, "%u ", &num_connections) != 1) { fann_error((struct fann_error *) ann, FANN_E_CANT_READ_NEURON, configuration_file); fann_destroy(ann); return NULL; } neuron_it->first_con = ann->total_connections; ann->total_connections += num_connections; neuron_it->last_con = ann->total_connections; } fann_allocate_connections(ann); if(ann->errno_f == FANN_E_CANT_ALLOCATE_MEM) { fann_destroy(ann); return NULL; } connected_neurons = ann->connections; weights = ann->weights; first_neuron = ann->first_layer->first_neuron; for(i = 0; i < ann->total_connections; i++) { if(fscanf(conf, "(%u " FANNSCANF ") ", &input_neuron, &weights[i]) != 2) { fann_error((struct fann_error *) ann, FANN_E_CANT_READ_CONNECTIONS, configuration_file); fann_destroy(ann); return NULL; } connected_neurons[i] = first_neuron + input_neuron; } fann_set_activation_steepness_hidden(ann, activation_steepness_hidden); fann_set_activation_steepness_output(ann, activation_steepness_output); fann_set_activation_function_hidden(ann, (enum fann_activationfunc_enum)activation_function_hidden); fann_set_activation_function_output(ann, (enum fann_activationfunc_enum)activation_function_output); #ifdef DEBUG printf("output\n"); #endif return ann; }