diff --git a/genann.c b/genann.c index b05fa4f..45fa80c 100644 --- a/genann.c +++ b/genann.c @@ -73,6 +73,11 @@ double genann_act_sigmoid(const genann *ann unused, double a) { return 1.0 / (1 + exp(-a)); } +double genann_act_sigmoid_derivative(const genann *ann unused, double a) { + return a * (1 - a); + +} + void genann_init_sigmoid_lookup(const genann *ann) { const double f = (sigmoid_dom_max - sigmoid_dom_min) / LOOKUP_SIZE; int i; @@ -120,7 +125,7 @@ genann *genann_init(int inputs, int hidden_layers, int hidden, int outputs) { /* Allocate extra size for weights, outputs, and deltas. */ const int size = sizeof(genann) + sizeof(double) * (total_weights + total_neurons + (total_neurons - inputs)); - genann *ret = malloc(size); + genann *ret = GENANN_MALLOC(size); if (!ret) return 0; ret->inputs = inputs; @@ -140,6 +145,9 @@ genann *genann_init(int inputs, int hidden_layers, int hidden, int outputs) { ret->activation_hidden = genann_act_sigmoid_cached; ret->activation_output = genann_act_sigmoid_cached; + + ret->activation_hidden_derivative = genann_act_sigmoid_derivative; + ret->activation_output_derivative = genann_act_sigmoid_derivative; genann_init_sigmoid_lookup(ret); @@ -178,7 +186,7 @@ genann *genann_read(FILE *in) { genann *genann_copy(genann const *ann) { const int size = sizeof(genann) + sizeof(double) * (ann->total_weights + ann->total_neurons + (ann->total_neurons - ann->inputs)); - genann *ret = malloc(size); + genann *ret = GENANN_MALLOC(size); if (!ret) return 0; memcpy(ret, ann, size); @@ -204,7 +212,7 @@ void genann_randomize(genann *ann) { void genann_free(genann *ann) { /* The weight, output, and delta pointers go to the same buffer. */ - free(ann); + GENANN_FREE(ann); } @@ -296,7 +304,7 @@ void genann_train(genann const *ann, double const *inputs, double const *desired } } else { for (j = 0; j < ann->outputs; ++j) { - *d++ = (*t - *o) * *o * (1.0 - *o); + *d++ = (*t - *o) * ann->activation_output_derivative(ann, *o); ++o; ++t; } } @@ -327,8 +335,7 @@ void genann_train(genann const *ann, double const *inputs, double const *desired const double forward_weight = ww[windex]; delta += forward_delta * forward_weight; } - - *d = *o * (1.0-*o) * delta; + *d = ann->activation_hidden_derivative(ann, *o) * delta; ++d; ++o; } } @@ -394,6 +401,11 @@ void genann_train(genann const *ann, double const *inputs, double const *desired void genann_write(genann const *ann, FILE *out) { + /* Safety check if file is invalid */ + if (!out) { + return; + + } fprintf(out, "%d %d %d %d", ann->inputs, ann->hidden_layers, ann->hidden, ann->outputs); int i; diff --git a/genann.h b/genann.h index e4b7383..b74059f 100644 --- a/genann.h +++ b/genann.h @@ -28,6 +28,7 @@ #define GENANN_H #include +#include #ifdef __cplusplus extern "C" { @@ -39,6 +40,10 @@ extern "C" { #define GENANN_RANDOM() (((double)rand())/RAND_MAX) #endif +/* Memory management; Redefine these to change the internal malloc/free system. */ +#define GENANN_MALLOC(sz) malloc(sz) +#define GENANN_FREE(sz) free(sz) + struct genann; typedef double (*genann_actfun)(const struct genann *ann, double a); @@ -47,12 +52,18 @@ typedef struct genann { /* How many inputs, outputs, and hidden neurons. */ int inputs, hidden_layers, hidden, outputs; - /* Which activation function to use for hidden neurons. Default: gennann_act_sigmoid_cached*/ + /* Which activation function to use for hidden neurons. Default: genann_act_sigmoid_cached*/ genann_actfun activation_hidden; - /* Which activation function to use for output. Default: gennann_act_sigmoid_cached*/ + /* Which activation function to use for output. Default: genann_act_sigmoid_cached*/ genann_actfun activation_output; + /* Which activation function to use for the hidden layer's derivative. Default: genann_act_sigmoid_derivative */ + genann_actfun activation_hidden_derivative; + + /* Which activation function to use for the output layer's derivative. Default: genann_act_sigmoid_derivative */ + genann_actfun activation_output_derivative; + /* Total number of weights, and size of weights buffer. */ int total_weights; @@ -97,6 +108,7 @@ void genann_write(genann const *ann, FILE *out); void genann_init_sigmoid_lookup(const genann *ann); double genann_act_sigmoid(const genann *ann, double a); double genann_act_sigmoid_cached(const genann *ann, double a); +double genann_act_sigmoid_derivative(const genann *ann, double a); double genann_act_threshold(const genann *ann, double a); double genann_act_linear(const genann *ann, double a);