📄 fann_io.c
字号:
/*
Fast Artificial Neural Network Library (fann)
Copyright (C) 2003 Steffen Nissen (lukesky@diku.dk)
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 <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "config.h"
#include "fann.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=%u\n", 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_max_cand_epochs=%u\n", ann->cascade_max_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, "%u ", 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, "(%u, %d) ",
connected_neurons[i] - first_neuron,
(int) floor((weights[i] * fixed_multiplier) + 0.5));
}
else
{
/* save the connection "(source weight) " */
fprintf(conf, "(%u, " FANNPRINTF ") ", connected_neurons[i] - first_neuron, weights[i]);
}
#else
/* save the connection "(source weight) " */
fprintf(conf, "(%u, " FANNPRINTF ") ", 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; \
} \
}
/* 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;
#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;
}
fread(read_version, 1, strlen(FANN_CONF_VERSION "\n"), conf); /* reads version */
/* 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -