Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change type double to int16_t #57

Open
lazy-dude opened this issue May 10, 2023 · 4 comments
Open

Change type double to int16_t #57

lazy-dude opened this issue May 10, 2023 · 4 comments

Comments

@lazy-dude
Copy link

Hi,

I want to change all data types from double to int16_t. In genann.h addition :

typedef int16_t ann_t;

Then change every occurrence of double to ann_t. Now modifying example1.c :

const ann_t input[4][2] = {{0, 0}, {0, 1}, {1, 0}, {1, 1}};
const ann_t output[4] = {0, 1, 1, 0};

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 ?

@codeplea
Copy link
Owner

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.

@lazy-dude
Copy link
Author

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;
}

@codeplea
Copy link
Owner

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?

@lazy-dude
Copy link
Author

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; 
        }
    }

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants