Open lazy-dude opened 1 year ago
You're going to need to change the activation function too. You could do that just by scaling everything. I.e. instead of having it expect most values between 0 and 1, change it so your values are normalized between 0 and 10000.
This activation function does not work. Can you help why ?
#define AF_MAX 10000
ann_t genann_act_sigmoid(const genann *ann unused, ann_t a) {
if (a < -45.0) return 0;
if (a > 45.0) return AF_MAX;
double r = 1.0 / (1.0 + exp(-a));
return r * AF_MAX;
}
I can't do it for you. You'll have to actually read the code and try to understand. Think what happens with the exp() function. What happens when you pass in a large value?
I know your username is lazy-dude, but come on.
What's the point of what you're trying to do anyway? You didn't even try to remove floats from that code, so why not just use floats?
Hi,
After doing some other jobs I am back. As why I do not use floats in my code, that is because I prefer it to run as fast as possible. Performance is an issue here. Even with a little loss of accuracy. So I have this genann_train function. Still not the right job here though:
part of genann.h
typedef int16_t genann_t;
#define GENANN_MAX 10000
The function for now used with genann_act_linear
void genann_train(genann const *ann, genann_t const *inputs, genann_t const *desired_outputs, float learning_rate) {
/* To begin with, we must run the network forward. */
genann_run(ann, inputs);
float quant_factor = GENANN_MAX;
int h, j, k;
/* First set the output layer deltas. */
{
genann_t const *o = ann->output + ann->inputs + ann->hidden * ann->hidden_layers; /* First output. */
genann_t *d = ann->delta + ann->hidden * ann->hidden_layers; /* First delta. */
genann_t const *t = desired_outputs; /* First desired output. */
/* Set output layer deltas. */
if (genann_act_output == genann_act_linear ||
ann->activation_output == genann_act_linear) {
for (j = 0; j < ann->outputs; ++j) {
//*d++ = *t++ - *o++;
float output = (float)(*o++ * quant_factor);
float target = (float)(*t++ * quant_factor);
float delta = target - output;
*d++ = delta;
}
} else {
for (j = 0; j < ann->outputs; ++j) {
float output = (float)(*o++ * quant_factor);
float target = (float)(*t++ * quant_factor);
float delta = (target - output) * output * (quant_factor - output);
*d++ = delta;
}
}
}
/* Set hidden layer deltas, start on last layer and work backwards. */
/* Note that loop is skipped in the case of hidden_layers == 0. */
for (h = ann->hidden_layers - 1; h >= 0; --h) {
/* Find first output and delta in this layer. */
genann_t const *o = ann->output + ann->inputs + (h * ann->hidden);
genann_t *d = ann->delta + (h * ann->hidden);
/* Find first delta in following layer (which may be hidden or output). */
genann_t const * const dd = ann->delta + ((h+1) * ann->hidden);
/* Find first weight in following layer (which may be hidden or output). */
genann_t const * const ww = ann->weight + ((ann->inputs+1) * ann->hidden) + ((ann->hidden+1) * ann->hidden * (h));
for (j = 0; j < ann->hidden; ++j) {
float delta = 0;
for (k = 0; k < (h == ann->hidden_layers-1 ? ann->outputs : ann->hidden); ++k) {
const float forward_delta = dd[k];
const int windex = k * (ann->hidden + 1) + (j + 1);
const float forward_weight = ww[windex];
delta += forward_delta * forward_weight;
}
float output = (float)(*o++ * quant_factor);
*d++ = (genann_t)((float)output * (1.0-output) * ((float)delta * (1.0 / quant_factor)));
}
}
/* Train the output layer */
for (int l = 0; l < ann->outputs; ++l) {
float delta = ann->delta[ann->hidden * ann->hidden_layers + l];
genann_t *w;
w = ann->weight + (ann->hidden_layers
? ((ann->inputs + 1) * ann->hidden + (ann->hidden + 1) * ann->hidden * (ann->hidden_layers - 1))
: 0)
+ l * (ann->hidden + 1);
*w += delta * learning_rate * -1.0;
for (int m = 0; m < ann->hidden; ++m) {
int windex = m + (ann->hidden_layers ? (ann->hidden * (ann->hidden_layers - 1)) : 0);
w[m+1] += delta * learning_rate
* ann->output[windex];
}
}
/* Train the hidden layers. */
for (int n = ann->hidden_layers - 1; n >= 0; --n) {
/* Find first delta in this layer. */
genann_t const *d = ann->delta + (n * ann->hidden);
/* Find first input to this layer. */
genann_t const *i = ann->output + (n ? (ann->inputs + ann->hidden * (n-1)) : 0);
/* Find first weight to this layer. */
genann_t *w = ann->weight + (n ? ((ann->inputs+1) * ann->hidden + (ann->hidden+1) * (ann->hidden) * (n-1)) : 0);
for (int q = 0; q < ann->hidden; ++q) {
*w += *d * learning_rate * -1.0;
++w;
for (int r = 1; r < (n == 0 ? ann->inputs : ann->hidden) + 1; ++r) {
*w += *d * learning_rate * i[r-1];
++w;
}
++d;
}
}
}
Hi,
I want to change all data types from
double
toint16_t
. Ingenann.h
addition :typedef int16_t ann_t;
Then change every occurrence of
double
toann_t
. Now modifyingexample1.c
:I also use
%hd
for printf.And then , compiling the file
example1.c
I get the output:$ ./example1 GENANN example 1. Train a small ANN to the XOR function using backpropagation. Output for [0, 0] is 0. Output for [0, 1] is 0. Output for [1, 0] is 0. Output for [1, 1] is 0.
What can I do to get the examples provided to work correctly with new type ?