📄 fann_train.c
字号:
#ifdef DEBUGTRAIN
printf("\nupdate slopes\n");
#endif
prev_neurons = first_neuron;
for(; layer_begin <= layer_end; layer_begin++)
{
#ifdef DEBUGTRAIN
printf("layer[%d]\n", layer_begin - ann->first_layer);
#endif
last_neuron = layer_begin->last_neuron;
if(ann->connection_rate >= 1)
{
if(ann->network_type == FANN_NETTYPE_LAYER)
{
prev_neurons = (layer_begin - 1)->first_neuron;
}
for(neuron_it = layer_begin->first_neuron; neuron_it != last_neuron; neuron_it++)
{
tmp_error = error_begin[neuron_it - first_neuron];
neuron_slope = slope_begin + neuron_it->first_con;
num_connections = neuron_it->last_con - neuron_it->first_con;
for(i = 0; i != num_connections; i++)
{
neuron_slope[i] += tmp_error * prev_neurons[i].value;
}
}
}
else
{
for(neuron_it = layer_begin->first_neuron; neuron_it != last_neuron; neuron_it++)
{
tmp_error = error_begin[neuron_it - first_neuron];
neuron_slope = slope_begin + neuron_it->first_con;
num_connections = neuron_it->last_con - neuron_it->first_con;
connections = ann->connections + neuron_it->first_con;
for(i = 0; i != num_connections; i++)
{
neuron_slope[i] += tmp_error * connections[i]->value;
}
}
}
}
}
/* INTERNAL FUNCTION
Clears arrays used for training before a new training session.
Also creates the arrays that do not exist yet.
*/
void fann_clear_train_arrays(struct fann *ann)
{
unsigned int i;
fann_type delta_zero;
/* if no room allocated for the slope variabels, allocate it now
* (calloc clears mem) */
if(ann->train_slopes == NULL)
{
ann->train_slopes =
(fann_type *) calloc(ann->total_connections_allocated, sizeof(fann_type));
if(ann->train_slopes == NULL)
{
fann_error((struct fann_error *) ann, FANN_E_CANT_ALLOCATE_MEM);
return;
}
}
else
{
memset(ann->train_slopes, 0, (ann->total_connections_allocated) * sizeof(fann_type));
}
/* if no room allocated for the variabels, allocate it now */
if(ann->prev_steps == NULL)
{
ann->prev_steps = (fann_type *) calloc(ann->total_connections_allocated, sizeof(fann_type));
if(ann->prev_steps == NULL)
{
fann_error((struct fann_error *) ann, FANN_E_CANT_ALLOCATE_MEM);
return;
}
}
else
{
memset(ann->prev_steps, 0, (ann->total_connections_allocated) * sizeof(fann_type));
}
/* if no room allocated for the variabels, allocate it now */
if(ann->prev_train_slopes == NULL)
{
ann->prev_train_slopes =
(fann_type *) malloc(ann->total_connections_allocated * sizeof(fann_type));
if(ann->prev_train_slopes == NULL)
{
fann_error((struct fann_error *) ann, FANN_E_CANT_ALLOCATE_MEM);
return;
}
}
if(ann->training_algorithm == FANN_TRAIN_RPROP)
{
delta_zero = ann->rprop_delta_zero;
for(i = 0; i < ann->total_connections_allocated; i++)
{
ann->prev_train_slopes[i] = delta_zero;
}
}
else
{
memset(ann->prev_train_slopes, 0, (ann->total_connections_allocated) * sizeof(fann_type));
}
}
/* INTERNAL FUNCTION
Update weights for batch training
*/
void fann_update_weights_batch(struct fann *ann, unsigned int num_data, unsigned int first_weight,
unsigned int past_end)
{
fann_type *train_slopes = ann->train_slopes;
fann_type *weights = ann->weights;
const float epsilon = ann->learning_rate / num_data;
unsigned int i = first_weight;
for(; i != past_end; i++)
{
weights[i] += train_slopes[i] * epsilon;
train_slopes[i] = 0.0;
}
}
/* INTERNAL FUNCTION
The quickprop training algorithm
*/
void fann_update_weights_quickprop(struct fann *ann, unsigned int num_data,
unsigned int first_weight, unsigned int past_end)
{
fann_type *train_slopes = ann->train_slopes;
fann_type *weights = ann->weights;
fann_type *prev_steps = ann->prev_steps;
fann_type *prev_train_slopes = ann->prev_train_slopes;
fann_type w, prev_step, slope, prev_slope, next_step;
float epsilon = ann->learning_rate / num_data;
float decay = ann->quickprop_decay; /*-0.0001;*/
float mu = ann->quickprop_mu; /*1.75; */
float shrink_factor = (float) (mu / (1.0 + mu));
unsigned int i = first_weight;
for(; i != past_end; i++)
{
w = weights[i];
prev_step = prev_steps[i];
slope = train_slopes[i] + decay * w;
prev_slope = prev_train_slopes[i];
next_step = 0.0;
/* The step must always be in direction opposite to the slope. */
if(prev_step > 0.001)
{
/* If last step was positive... */
if(slope > 0.0) /* Add in linear term if current slope is still positive. */
next_step += epsilon * slope;
/*If current slope is close to or larger than prev slope... */
if(slope > (shrink_factor * prev_slope))
next_step += mu * prev_step; /* Take maximum size negative step. */
else
next_step += prev_step * slope / (prev_slope - slope); /* Else, use quadratic estimate. */
}
else if(prev_step < -0.001)
{
/* If last step was negative... */
if(slope < 0.0) /* Add in linear term if current slope is still negative. */
next_step += epsilon * slope;
/* If current slope is close to or more neg than prev slope... */
if(slope < (shrink_factor * prev_slope))
next_step += mu * prev_step; /* Take maximum size negative step. */
else
next_step += prev_step * slope / (prev_slope - slope); /* Else, use quadratic estimate. */
}
else /* Last step was zero, so use only linear term. */
next_step += epsilon * slope;
/*
if(next_step > 1000 || next_step < -1000)
{
printf("quickprop[%d] weight=%f, slope=%f, prev_slope=%f, next_step=%f, prev_step=%f\n",
i, weights[i], slope, prev_slope, next_step, prev_step);
if(next_step > 1000)
next_step = 1000;
else
next_step = -1000;
}
*/
/* update global data arrays */
prev_steps[i] = next_step;
w += next_step;
/*
if(w > 1500)
weights[i] = 1500;
else if(w < -1500)
weights[i] = -1500;
else
weights[i] = w;
*/
weights[i] = w;
prev_train_slopes[i] = slope;
train_slopes[i] = 0.0;
}
}
/* INTERNAL FUNCTION
The iRprop- algorithm
*/
void fann_update_weights_irpropm(struct fann *ann, unsigned int first_weight, unsigned int past_end)
{
fann_type *train_slopes = ann->train_slopes;
fann_type *weights = ann->weights;
fann_type *prev_steps = ann->prev_steps;
fann_type *prev_train_slopes = ann->prev_train_slopes;
fann_type prev_step, slope, prev_slope, next_step, same_sign;
float increase_factor = ann->rprop_increase_factor; /*1.2; */
float decrease_factor = ann->rprop_decrease_factor; /*0.5; */
float delta_min = ann->rprop_delta_min; /*0.0; */
float delta_max = ann->rprop_delta_max; /*50.0; */
unsigned int i = first_weight;
for(; i != past_end; i++)
{
prev_step = fann_max(prev_steps[i], (fann_type) 0.001); /* prev_step may not be zero because then the training will stop */
slope = train_slopes[i];
prev_slope = prev_train_slopes[i];
same_sign = prev_slope * slope;
if(same_sign > 0.0)
{
next_step = fann_min(prev_step * increase_factor, delta_max);
}
else if(same_sign < 0.0)
{
next_step = fann_max(prev_step * decrease_factor, delta_min);
slope = 0;
}
else
{
next_step = 0.0;
}
if(slope < 0)
{
weights[i] -= next_step;
}
else
{
weights[i] += next_step;
}
/*if(i == 2){
* printf("weight=%f, slope=%f, next_step=%f, prev_step=%f\n", weights[i], slope, next_step, prev_step);
* } */
/* update global data arrays */
prev_steps[i] = next_step;
prev_train_slopes[i] = slope;
train_slopes[i] = 0.0;
}
}
#endif
FANN_GET_SET(enum fann_train_enum, training_algorithm)
FANN_GET_SET(float, learning_rate)
FANN_EXTERNAL void FANN_API fann_set_activation_function_hidden(struct fann *ann,
enum fann_activationfunc_enum activation_function)
{
struct fann_neuron *last_neuron, *neuron_it;
struct fann_layer *layer_it;
struct fann_layer *last_layer = ann->last_layer - 1; /* -1 to not update the output layer */
for(layer_it = ann->first_layer + 1; layer_it != last_layer; layer_it++)
{
last_neuron = layer_it->last_neuron;
for(neuron_it = layer_it->first_neuron; neuron_it != last_neuron; neuron_it++)
{
neuron_it->activation_function = activation_function;
}
}
}
FANN_EXTERNAL struct fann_layer* FANN_API fann_get_layer(struct fann *ann, int layer)
{
if(layer <= 0 || layer >= (ann->last_layer - ann->first_layer))
{
fann_error((struct fann_error *) ann, FANN_E_INDEX_OUT_OF_BOUND, layer);
return NULL;
}
return ann->first_layer + layer;
}
FANN_EXTERNAL struct fann_neuron* FANN_API fann_get_neuron_layer(struct fann *ann, struct fann_layer* layer, int neuron)
{
if(neuron >= (layer->last_neuron - layer->first_neuron)) // FIX Swapped first and last
{
fann_error((struct fann_error *) ann, FANN_E_INDEX_OUT_OF_BOUND, neuron);
return NULL;
}
return layer->first_neuron + neuron;
}
FANN_EXTERNAL struct fann_neuron* FANN_API fann_get_neuron(struct fann *ann, unsigned int layer, int neuron)
{
struct fann_layer *layer_it = fann_get_layer(ann, layer);
if(layer_it == NULL)
return NULL;
return fann_get_neuron_layer(ann, layer_it, neuron);
}
FANN_EXTERNAL enum fann_activationfunc_enum FANN_API
fann_get_activation_function(struct fann *ann, int layer, int neuron)
{
struct fann_neuron* neuron_it = fann_get_neuron(ann, layer, neuron);
if (neuron_it == NULL)
{
return (enum fann_activationfunc_enum)-1; /* layer or neuron out of bounds */
}
else
{
return neuron_it->activation_function;
}
}
FANN_EXTERNAL void FANN_API fann_set_activation_function(struct fann *ann,
enum fann_activationfunc_enum
activation_function,
int layer,
int neuron)
{
struct fann_neuron* neuron_it = fann_get_neuron(ann, layer, neuron);
if(neuron_it == NULL)
return;
neuron_it->activation_function = activation_function;
}
FANN_EXTERNAL void FANN_API fann_set_activation_function_layer(struct fann *ann,
enum fann_activationfunc_enum
activation_function,
int layer)
{
struct fann_neuron *last_neuron, *neuron_it;
struct fann_layer *layer_it = fann_get_layer(ann, layer);
if(layer_it == NULL)
return;
last_neuron = layer_it->last_neuron;
for(neuron_it = layer_it->first_neuron; neuron_it != last_neuron; neuron_it++)
{
neuron_it->activation_function = activation_function;
}
}
FANN_EXTERNAL void FANN_API fann_set_activation_function_output(struct fann *ann,
enum fann_activationfunc_enum activation_function)
{
struct fann_neuron *last_neuron, *neuron_it;
struct fann_layer *last_layer = ann->last_layer - 1;
last_neuron = last_layer->last_neuron;
for(neuron_it = last_layer->first_neuron; neuron_it != last_neuron; neuron_it++)
{
neuron_it->activation_function = activation_function;
}
}
FANN_EXTERNAL void FANN_API fann_set_activation_steepness_hidden(struct fann *ann,
fann_type steepness)
{
struct fann_neuron *last_neuron, *neuron_it;
struct fann_layer *layer_it;
struct fann_layer *last_layer = ann->last_layer - 1; /* -1 to not update the output layer */
for(layer_it = ann->first_layer + 1; layer_it != last_layer; layer_it++)
{
last_neuron = layer_it->last_neuron;
for(neuron_it = layer_it->first_neuron; neuron_it != last_neuron; neuron_it++)
{
neuron_it->activation_steepness = steepness;
}
}
}
FANN_EXTERNAL fann_type FANN_API
fann_get_activation_steepness(struct fann *ann, int layer, int neuron)
{
struct fann_neuron* neuron_it = fann_get_neuron(ann, layer, neuron);
if(neuron_it == NULL)
{
return -1; /* layer or neuron out of bounds */
}
else
{
return neuron_it->activation_steepness;
}
}
FANN_EXTERNAL void FANN_API fann_set_activation_steepness(struct fann *ann,
fann_type steepness,
int layer,
int neuron)
{
struct fann_neuron* neuron_it = fann_get_neuron(ann, layer, neuron);
if(neuron_it == NULL)
return;
neuron_it->activation_steepness = steepness;
}
FANN_EXTERNAL void FANN_API fann_set_activation_steepness_layer(struct fann *ann,
fann_type steepness,
int layer)
{
struct fann_neuron *last_neuron, *neuron_it;
struct fann_layer *layer_it = fann_get_layer(ann, layer);
if(layer_it == NULL)
return;
last_neuron = layer_it->last_neuron;
for(neuron_it = layer_it->first_neuron; neuron_it != last_neuron; neuron_it++)
{
neuron_it->activation_steepness = steepness;
}
}
FANN_EXTERNAL void FANN_API fann_set_activation_steepness_output(struct fann *ann,
fann_type steepness)
{
struct fann_neuron *last_neuron, *neuron_it;
struct fann_layer *last_layer = ann->last_layer - 1;
last_neuron = last_layer->last_neuron;
for(neuron_it = last_layer->first_neuron; neuron_it != last_neuron; neuron_it++)
{
neuron_it->activation_steepness = steepness;
}
}
FANN_GET_SET(enum fann_errorfunc_enum, train_error_function)
FANN_GET_SET(fann_callback_type, callback)
FANN_GET_SET(float, quickprop_decay)
FANN_GET_SET(float, quickprop_mu)
FANN_GET_SET(float, rprop_increase_factor)
FANN_GET_SET(float, rprop_decrease_factor)
FANN_GET_SET(float, rprop_delta_min)
FANN_GET_SET(float, rprop_delta_max)
FANN_GET_SET(enum fann_stopfunc_enum, train_stop_function)
FANN_GET_SET(fann_type, bit_fail_limit)
FANN_GET_SET(float, learning_momentum)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -