-1

I have a 3-layed neural network, and I'm getting a seg fault. I know that means I'm writing to the wrong memory space. In this scenario I would guess it is because I am running out of space.

The thing is I have calloced all of my large store items, so I thought that would resolve this issue.

gdb is freezing at the line

   81                 for( j = 0 ; j < NumHidden ; j++ ) {    /* compute hidden unit activations */
   82                     SumH[p][j] = WeightIH[0][j] ;
-> 83                     for( i = 0 ; i < NumInput ; i++ ) {
   84                         temp1 = Input[game][0][i] * WeightIH[i][j] ;

the code looks like:

    /*******************************************************************************
*    nn.c   1.0                                       � JOHN BULLINARIA  2004  *
*******************************************************************************/

/*      To compile use "cc nn.c -O -lm -o nn" and then run using "./nn"       */
/*      For explanations see:  http://www.cs.bham.ac.uk/~jxb/NN/nn.html       */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <fcntl.h>

#define NUMPAT 51
#define NUMIN  51
#define NUMHID 20
#define NUMOUT 20

#define rando() ((double)rand()/(RAND_MAX+1))

int main() {
    int    i, j, k, p, np, op, ranpat[NUMPAT+1], epoch, temp1, temp2, game;
    int    NumPattern = NUMPAT, NumInput = NUMIN, NumHidden = NUMHID, NumOutput = NUMOUT;

    double ***Input = calloc(51*40, sizeof(double ***));
    char line[128];
    int varCount = 0;
    double num;

    FILE *csvFile = fopen("ks vs tt.csv", "r");

    if (csvFile){
      char *token;
      while (fgets(line, 1024, csvFile)){
        token = strtok(&line[0], ",");
        while(token){
          num = atof(token);
          Input[varCount] = &num;
          token = strtok(NULL, ",");
          varCount++;
        }
      }
      fclose(csvFile);
    }
    double Target[20] = {10,10,3,-4,11,-2,13,-5,4,3,4,5,-5,25,13,25,3,2,5,17};
    double **SumH = calloc(51*20, sizeof(double **));
    double **WeightIH = calloc(51*20, sizeof(double **));
    double **Hidden = calloc(51*20, sizeof(double **));
    double **SumO= calloc(51*20, sizeof(double **));
    double **WeightHO = calloc(51*20, sizeof(double **));
    double **Output = calloc(51*20, sizeof(double **));
    double *DeltaO = calloc(51*20, sizeof(double *));
    double *SumDOW = calloc(51*20, sizeof(double *));
    double *DeltaH = calloc(51*20, sizeof(double *));
    double **DeltaWeightIH = calloc(51*20, sizeof(double **));
    double **DeltaWeightHO = calloc(51*20, sizeof(double **));
    double Error, eta = 0.5, alpha = 0.9, smallwt = 0.5;

    for( j = 0 ; j < NumHidden ; j++ ) {    /* initialize WeightIH and DeltaWeightIH */
        for( i = 0 ; i < NumInput ; i++ ) {
            DeltaWeightIH[i][j] = 0.0 ;
            WeightIH[i][j] = 2.0 * ( rand() - 0.5 ) * smallwt ;
        }
    }
    for( k = 0 ; k < NumOutput ; k ++ ) {    /* initialize WeightHO and DeltaWeightHO */
        for( j = 0 ; j < NumHidden ; j++ ) {
            DeltaWeightHO[j][k] = 0.0 ;
            WeightHO[j][k] = 2.0 * ( rand() - 0.5 ) * smallwt ;
        }
    }

    for( epoch = 0 ; epoch < 100000 ; epoch++) {    /* iterate weight updates */
        for( p = 1 ; p <= NumPattern ; p++ ) {    /* randomize order of individuals */
            ranpat[p] = p ;
        }
        for( p = 1 ; p <= NumPattern ; p++) {
            np = p + rand() * ( NumPattern + 1 - p ) ;
            op = ranpat[p] ;
            ranpat[p] = ranpat[np] ;
            ranpat[np] = op ;
        }
        Error = 0.0 ;
        for( np = 1 ; np <= NumPattern ; np++ ) {    /* repeat for all the training patterns */
            p = ranpat[np];
            for (game = 0; game < 20; game++){
              for( j = 0 ; j < NumHidden ; j++ ) {    /* compute hidden unit activations */
                  SumH[p][j] = WeightIH[0][j] ;
                  for( i = 0 ; i < NumInput ; i++ ) {
                      temp1 = Input[game][0][i] * WeightIH[i][j] ;
                      temp2 = Input[game][1][i] * WeightIH[i][j] ;
                      SumH[p][j] += temp1 - temp2 ;
                  }
                  Hidden[p][j] = 1.0/(1.0 + exp(-SumH[p][j])) ;
              }
              for( k = 0 ; k < NumOutput ; k++ ) {    /* compute output unit activations and errors */
                  SumO[p][k] = WeightHO[0][k] ;
                  for( j = 0 ; j < NumHidden ; j++ ) {
                      SumO[p][k] += Hidden[p][j] * WeightHO[j][k] ;
                  }
                  Output[p][k] = 1.0/(1.0 + exp(-SumO[p][k])) ;   /* Sigmoidal Outputs */
  /*              Output[p][k] = SumO[p][k];      L
ear Outputs */
                  Error += 0.5 * (Target[k] - Output[p][k]) * (Target[k] - Output[p][k]) ;   /* SSE */
  /*              Error -= ( Target[p][k] * log( Output[p][k] ) + ( 1.0 - Target[p][k] ) * log( 1.0 - Output[p][k] ) ) ;    Cross-Entropy Error */
                  DeltaO[k] = (Target[k] - Output[p][k]) * Output[p][k] * (1.0 - Output[p][k]) ;   /* Sigmoidal Outputs, SSE */
  /*              DeltaO[k] = Target[p][k] - Output[p][k];     Sigmoidal Outputs, Cross-Entropy Error */
  /*              DeltaO[k] = Target[p][k] - Output[p][k];     Linear Outputs, SSE */
              }
              for( j = 0 ; j < NumHidden ; j++ ) {    /* 'back-propagate' errors to hidden layer */
                  SumDOW[j] = 0.0 ;
                  for( k = 0 ; k < NumOutput ; k++ ) {
                      SumDOW[j] += WeightHO[j][k] * DeltaO[k] ;
                  }
                  DeltaH[j] = SumDOW[j] * Hidden[p][j] * (1.0 - Hidden[p][j]) ;
              }
              for( j = 0 ; j < NumHidden ; j++ ) {     /* update weights WeightIH */
                  DeltaWeightIH[0][j] = eta * DeltaH[j] + alpha * DeltaWeightIH[0][j] ;
                  WeightIH[0][j] += DeltaWeightIH[0][j] ;
                  for( i = 0 ; i < NumInput ; i++ ) {
                      DeltaWeightIH[i][j] = eta * Input[game][0][i] * DeltaH[j] + alpha * DeltaWeightIH[i][j];
                      WeightIH[i][j] += DeltaWeightIH[i][j] ;
                  }
              }
              for( k = 0 ; k < NumOutput ; k ++ ) {    /* update weights WeightHO */
                  DeltaWeightHO[0][k] = eta * DeltaO[k] + alpha * DeltaWeightHO[0][k] ;
                  WeightHO[0][k] += DeltaWeightHO[0][k] ;
                  for( j = 0 ; j < NumHidden ; j++ ) {
                      DeltaWeightHO[j][k] = eta * Hidden[p][j] * DeltaO[k] + alpha * DeltaWeightHO[j][k] ;
                      WeightHO[j][k] += DeltaWeightHO[j][k] ;
                  }
              }
            }

        }
        if( epoch%100 == 0 ) fprintf(stdout, "\nEpoch %-5d :   Error = %f", epoch, Error) ;
        if( Error < 0.0004 ) break ;  /* stop learning when 'near enough' */
    }
    int sum = 0;
    double weights[51];
    for (i = 0; i < NumInput; i++){
      for (j = 0; j < NumHidden; j++){
        sum = WeightIH[i][j];
      }
      sum /= 51;
      weights[i] = sum;
    }
    for (i = 0; i < 51; i++){
      printf("weight[%d] = %G\n", i, weights[i]);
    }
    return 1 ;
}

/*******************************************************************************/

I'm compiling with: gcc nn.c -O -lm -o nn -mmacosx-version-min=10.11 and it compiles fine.

Any idea what's going on here?

tkausl
  • 13,686
  • 2
  • 33
  • 50
  • I see a lot of allocations on stack, just as a check, did you try switching to static storage allocation all the locals without success? – Jack Jan 13 '16 at 02:42
  • @Jack as in pointers? yes I tried – kendall weihe Jan 13 '16 at 02:43
  • as pointers through callic or static (which is a different thing), both prevents the stack from growing too much – Jack Jan 13 '16 at 02:45
  • @Jack I don't think that is the case since the program isn't getting past the line `ranpat[p];` – kendall weihe Jan 13 '16 at 02:48
  • @Jack or do you think the array size alone is overflowing the stack space? – kendall weihe Jan 13 '16 at 02:49
  • Often an illegal instruction is given by the fact that your code jumps to an invalid address, which can be caused by a buffer overflow (eg. you write in the memory that contains the return address of an activation frame) – Jack Jan 13 '16 at 02:51
  • @Jack I tried `calloc` and it's doing the same thing – kendall weihe Jan 13 '16 at 03:46
  • What makes you think that `calloc` will allocate memory on the stack? The only direct way that you have to influence that (aside from declaring a local variable) is to use `alloca`. – David Hoelzer Jan 13 '16 at 04:10
  • @DavidHoelzer please see updated code, I still get the same error – kendall weihe Jan 13 '16 at 04:25
  • I wasn't really suggesting that you use `alloca`... I was asking what made you think you were allocating data on the stack. :) – David Hoelzer Jan 13 '16 at 04:29
  • @DavidHoelzer lol never used alloca though I see it's bad to use. Why wouldnt calloc allocate memory? – kendall weihe Jan 13 '16 at 04:31
  • Your local variables (the pointer variables) will be on the stack but when you dynamically allocate memory it is always coming out of the heap, not the stack. It's not that `calloc` doesn't allocate memory, it just doesn't allocate it where you seem to think that it does. – David Hoelzer Jan 13 '16 at 04:32
  • @DavidHoelzer Doh! I knew that lol. I've been on break for a couple of weeks. I guess I'm a little rusty. Any ideas why it would be seg faulting? – kendall weihe Jan 13 '16 at 04:33
  • Well, your reading or writing memory that you don't own... that's what a segfault is. You should not cast the return from `malloc`, `calloc` or `realloc` because it can conceal errors. Have you tried compiling with a `-g` option and running it under GDB? You could also enable coredumps (`ulimit -c unlimited`) after compiling with debug (`-g`) and see exactly what's going on when it crashes (`gdb --core core`). – David Hoelzer Jan 13 '16 at 04:36
  • @DavidHoelzer in gdb the program just freezes, it won't go past a line. when I enter n it just sits on the same line. coredumps doesn't fix the problem either – kendall weihe Jan 13 '16 at 04:39
  • Try enabling core dumps, compiling with `-g`, letting it crash and examining the coredump – David Hoelzer Jan 13 '16 at 04:48
  • 1
    After `double **DeltaWeightIH = calloc(51*20, sizeof(double **));`, `DeltaWeightIH[i][j] = 0.0 ;` is *at best* a `NULL`-dereference (if `NULL` is bitwise-zero, which is not guaranteed). Also, if you can't count `*`s, consider using the `foo *bar = [m/c/re]alloc(x*sizeof(*bar))`-idiom. – EOF Jan 13 '16 at 10:48
  • @EOF how would I assign 0.0 to the array then? – kendall weihe Jan 13 '16 at 17:43
  • @kendallweihe How about initializing `DeltaWeight[i]` to a valid `double *` before trying to dereference it? – EOF Jan 13 '16 at 19:54
  • when compiling, always enable all the warnings. (for gcc, at a minimum use: `-Wall -Wextra -pedantic` (I also use `-Wconversion -std=c99`) Then fix those warnings. The first warning to fix is the implicit definition of the `strtok()` function, which can be fixed by inserting the statement: `#include at the top of the file. There there are warnings about incompatible pointer assignments and implicit conversions from `int` to `double` – user3629249 Jan 14 '16 at 21:54
  • for readability and ease of understanding, please follow the axiom: only one statement per line and (at most) one variable declaration per statement. – user3629249 Jan 14 '16 at 21:56
  • when calling any memory allocation function: (malloc, calloc, realloc), always check (!=NULL) the returned value to assure the operation was successful – user3629249 Jan 14 '16 at 22:00
  • the posted code contains several 'magic' numbers. 51, 0, 1024, 20, 100000, 100, 0.0004 'magic' numbers make the code much more difficult to understand, debug, maintain. Suggest using #define statements or an enum to give the 'magic' numbers meaningful names, then use those meaningful names throughout the code. – user3629249 Jan 14 '16 at 22:05
  • when calling `fopen()`, always check (!=NULL) the returned value to assure the operation was successful. – user3629249 Jan 14 '16 at 22:08
  • strongly suggest, before exiting the program to pass file pointers to `fclose()` and pass all memory allocation pointers to `free()`. Now, a modern OS will recover those memory leaks and close the files for you, however, such sloppy programming will (sooner or later) burn you. – user3629249 Jan 14 '16 at 22:11
  • for readability and ease of understanding by us humans, please separate code blocks (if, else, for, while, do...while, switch, case, default) by a blank line – user3629249 Jan 14 '16 at 22:12
  • please consistently indent the code, never use tabs for indenting, suggest using 4 spaces for each indent level as that is visible even with variable width fonts and enables many indent levels across the page. Indent after every opening brace '{'. un-indent before every closing brace '}'. – user3629249 Jan 14 '16 at 22:15
  • the char array `line[]` is declared as 128 bytes, BUT the call to `fgets()` states the size is 1024 bytes the call to `fgets()` should be: `while (fgets(line, sizeof(line), csvFile)) .. this is a major error – user3629249 Jan 14 '16 at 22:46
  • regarding this line: `while ( fgets(line, sizeof(line), csvFile))`, if the file has a lot of lines (and each line must contain only one value, followed (optionally by a comma)) this loop can overflow the Input[] array. suggest: `while ( (51*40) < varCount && fgets(line, sizeof(line), csvFile)) – user3629249 Jan 14 '16 at 23:07
  • it is usually a problem to create files those names contain spaces. Suggest using underscores rather than spaces – user3629249 Jan 14 '16 at 23:09

1 Answers1

1

this line:

double ***Input = calloc(51*40, sizeof(double ***)); 

is allocating an array of pointers to arrays of pointers to double.

However only the first level of the array is ever allocated.

For each of the arrays in the first allocation,

there needs to be an allocation for each of the second level arrays

and an allocation for each of the third level arrays within the second level of arrays.

This problem is displayed in several areas of the code when working with the ** allocations and with the *** allocations.

the code is accessing memory that it does not own. << =root of crash>>

This (above) problem is not fixed in the following code:

here is a version that implements the comments,

but does not fix the memory allocation problems

but does not handle the problem about a invalid pointer assignment nor 3 problems about implicit conversions.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <fcntl.h>
#include <string.h>

#define NUMPAT (51)
#define NUMIN  (51)
#define NUMHID (20)
#define NUMOUT (20)

#define MAX_EPOCH      (100000)
#define ALLOC_51x40    (51*40)
// used larger allocation (above) so next line not used
//#define ALLOC_51x20    (51*20)
#define MAX_LINE_LEN   (128)
#define MAX_TARGET_LEN (20)

#define rando() ((double)rand()/(RAND_MAX+1))


    // removed some unneeded local variables
    // int    NumPattern = NUMPAT, NumInput = NUMIN, NumHidden = NUMHID, NumOutput = NUMOUT;


int main( void )
{
    int i;
    int j;
    int k;
    int p;
    int np;
    int op;
    int ranpat[NUMPAT+1];
    int epoch;
    int temp1;
    int temp2;
    int game;

    double ***Input = NULL;
    if( NULL == (Input = calloc(ALLOC_51x40, sizeof(double ***)) ) )
    { // then calloc failed
        perror( "calloc failed");
        exit( EXIT_FAILURE );
    }

    // implied else, calloc successful

    FILE *csvFile = NULL;
    if( NULL == (csvFile = fopen("ks vs tt.csv", "r") ) )
    { // then fopen failed
        perror( "fopen failed for read of ks vs tt.csv" );
        exit( EXIT_FAILURE );
    }

    // implied else, fopen successful

    char line[ MAX_LINE_LEN ];
    int varCount = 0;
    double num;
    char *token;

    while ( ALLOC_51x40 < varCount && fgets(line, sizeof(line), csvFile))
    {
        token = strtok(&line[0], ",");

        while(token)
        {
            num = atof(token);
            Input[varCount] = &num;
            token = strtok(NULL, ",");
            varCount++;
        }
    }
    fclose(csvFile);


    double Target[ MAX_TARGET_LEN ] =
    {
        10.0,
        10.0,
        3.0,
        -4.0,
        11.0,
        2.0,
        13.0,
        -5.0,
        4.0,
        3.0,
        4.0,
        5.0,
        -5.0,
        25.0,
        13.0,
        25.0,
        3.0,
        2.0,
        5.0,
        17.0
    };

    double **SumH = NULL;
    if( NULL == (SumH = calloc(ALLOC_51x40, sizeof(double **)) ) )
    { // then calloc failed
        perror( "calloc failed for SumH" );
        exit( EXIT_FAILURE );
    }

    // implied else, calloc successful

    double **WeightIH = NULL;
    if( NULL == (WeightIH = calloc(ALLOC_51x40, sizeof(double **)) ) )
    { // then calloc failed
        perror( "calloc failed for WeighIH" );
        exit( EXIT_FAILURE );
    }

    // implied else, calloc successful

    double **Hidden = NULL;
    if( NULL == (Hidden = calloc(ALLOC_51x40, sizeof(double **)) ) )
    { // then calloc failed
        perror( "calloc failed for Hidden" );
        exit( EXIT_FAILURE);
    }

    // implied else, calloc successful

    double **SumO = NULL;
    if( NULL == (SumO = calloc(ALLOC_51x40, sizeof(double **)) ) )
    { // then calloc failed
        perror( "calloc failed for SumO" );
        exit( EXIT_FAILURE );
    }

    // implied else, calloc successful

    double **WeightHO = NULL;
    if( NULL == (WeightHO = calloc(ALLOC_51x40, sizeof(double **)) ) )
    { // then calloc failed
        perror( "calloc failed for WeightHo" );
        exit( EXIT_FAILURE );
    }

    // implied else, calloc successful

    double **Output = NULL;
    if( NULL == (Output = calloc(ALLOC_51x40, sizeof(double **)) ) )
    { // then calloc failed
        perror( "calloc failed for Output" );
        exit( EXIT_FAILURE );
    }

    // implied else, calloc successful

    double *DeltaO = NULL;
    if( NULL == (DeltaO = calloc(ALLOC_51x40, sizeof(double *)) ) )
    { // then calloc failed
        perror( "calloc failed for DeltaO" );
        exit( EXIT_FAILURE );
    }

    // implied else, calloc successful

    double *SumDOW = NULL;
    if( NULL == (SumDOW = calloc(ALLOC_51x40, sizeof(double *)) ) )
    { // then calloc failed
        perror( "calloc failed for SumDOW" );
        exit( EXIT_FAILURE );
    }

    // implied else, calloc successful

    double *DeltaH = NULL;
    if( NULL == (DeltaH = calloc(ALLOC_51x40, sizeof(double *)) ) )
    { // then calloc failed
        perror( "calloc failed for DeltaH" );
        exit( EXIT_FAILURE );
    }

    // implied else, calloc successful

    double **DeltaWeightIH = NULL;
    if( NULL == (DeltaWeightIH = calloc(ALLOC_51x40, sizeof(double **)) ) )
    { // then calloc failed
        perror( "calloc failed for DeltaWeightIH" );
        exit( EXIT_FAILURE );
    }

    // implied else, calloc successful

    double **DeltaWeightHO = NULL;
    if( NULL == (DeltaWeightHO = calloc(ALLOC_51x40, sizeof(double **)) ) )
    { // then calloc failed
        perror( "calloc failed for DeltaWeightHO" );
        exit( EXIT_FAILURE );
    }

    // implied else, calloc successful

    double Error   = 0.0;
    double eta     = 0.5;
    double alpha   = 0.9;
    double smallwt = 0.5;

    for( j = 0 ; j < NUMHID ; j++ )
    {    /* initialize WeightIH and DeltaWeightIH */
        for( i = 0 ; i < NUMIN ; i++ )
        {
            DeltaWeightIH[i][j] = 0.0 ;
            WeightIH[i][j] = 2.0 * ( rand() - 0.5 ) * smallwt ;
        }
    }

    for( k = 0 ; k < NUMOUT ; k ++ )
    {    /* initialize WeightHO and DeltaWeightHO */
        for( j = 0 ; j < NUMHID ; j++ )
        {
            DeltaWeightHO[j][k] = 0.0 ;
            WeightHO[j][k] = 2.0 * ( rand() - 0.5 ) * smallwt ;
        }
    }

    for( epoch = 0 ; epoch < MAX_EPOCH ; epoch++)
    {    /* iterate weight updates */
        for( p = 1 ; p <= NUMPAT ; p++ )
        {    /* randomize order of individuals */
            ranpat[p] = p ;
        }

        for( p = 1 ; p <= NUMPAT ; p++)
        {
            np = p + rand() * ( NUMPAT + 1 - p ) ;
            op = ranpat[p] ;
            ranpat[p] = ranpat[np] ;
            ranpat[np] = op ;
        }

        Error = 0.0 ;
        for( np = 1 ; np <= NUMPAT ; np++ )
        {    /* repeat for all the training patterns */
            p = ranpat[np];

            for (game = 0; game < 20; game++)
            {
              for( j = 0 ; j < NUMHID ; j++ )
              {    /* compute hidden unit activations */
                  SumH[p][j] = WeightIH[0][j] ;
                  for( i = 0 ; i < NUMIN ; i++ )
                  {
                      temp1 = Input[game][0][i] * WeightIH[i][j] ;
                      temp2 = Input[game][1][i] * WeightIH[i][j] ;
                      SumH[p][j] += temp1 - temp2 ;
                  }

                  Hidden[p][j] = 1.0/(1.0 + exp(-SumH[p][j])) ;
              }

              for( k = 0 ; k < NUMOUT ; k++ )
              {    /* compute output unit activations and errors */
                  SumO[p][k] = WeightHO[0][k] ;

                  for( j = 0 ; j < NUMHID ; j++ )
                  {
                      SumO[p][k] += Hidden[p][j] * WeightHO[j][k] ;
                  }

                  Output[p][k] = 1.0/(1.0 + exp(-SumO[p][k])) ;   /* Sigmoidal Outputs */
  /*              Output[p][k] = SumO[p][k];      L
ear Outputs */
                  Error += 0.5 * (Target[k] - Output[p][k]) * (Target[k] - Output[p][k]) ;   /* SSE */
  /*              Error -= ( Target[p][k] * log( Output[p][k] ) + ( 1.0 - Target[p][k] ) * log( 1.0 - Output[p][k] ) ) ;    Cross-Entropy Error */
                  DeltaO[k] = (Target[k] - Output[p][k]) * Output[p][k] * (1.0 - Output[p][k]) ;   /* Sigmoidal Outputs, SSE */
  /*              DeltaO[k] = Target[p][k] - Output[p][k];     Sigmoidal Outputs, Cross-Entropy Error */
  /*              DeltaO[k] = Target[p][k] - Output[p][k];     Linear Outputs, SSE */
              }

              for( j = 0 ; j < NUMHID ; j++ )
              {    /* 'back-propagate' errors to hidden layer */
                  SumDOW[j] = 0.0 ;

                  for( k = 0 ; k < NUMOUT ; k++ )
                  {
                      SumDOW[j] += WeightHO[j][k] * DeltaO[k] ;
                  }

                  DeltaH[j] = SumDOW[j] * Hidden[p][j] * (1.0 - Hidden[p][j]) ;
              }

              for( j = 0 ; j < NUMHID ; j++ )
              {     /* update weights WeightIH */
                  DeltaWeightIH[0][j] = eta * DeltaH[j] + alpha * DeltaWeightIH[0][j] ;
                  WeightIH[0][j] += DeltaWeightIH[0][j] ;

                  for( i = 0 ; i < NUMIN ; i++ )
                  {
                      DeltaWeightIH[i][j] = eta * Input[game][0][i] * DeltaH[j] + alpha * DeltaWeightIH[i][j];
                      WeightIH[i][j] += DeltaWeightIH[i][j] ;
                  }
              }

              for( k = 0 ; k < NUMOUT ; k ++ )
              {    /* update weights WeightHO */
                  DeltaWeightHO[0][k] = eta * DeltaO[k] + alpha * DeltaWeightHO[0][k] ;
                  WeightHO[0][k] += DeltaWeightHO[0][k] ;

                  for( j = 0 ; j < NUMHID ; j++ )
                  {
                      DeltaWeightHO[j][k] = eta * Hidden[p][j] * DeltaO[k] + alpha * DeltaWeightHO[j][k] ;
                      WeightHO[j][k] += DeltaWeightHO[j][k] ;
                  }
              }
            }
        }

        if( epoch%100 == 0 ) fprintf(stdout, "\nEpoch %-5d :   Error = %f", epoch, Error) ;

        if( Error < 0.0004 ) break ;  /* stop learning when 'near enough' */
    }

    int sum = 0;
    double weights[51];

    for (i = 0; i < NUMIN; i++)
    {
      for (j = 0; j < NUMHID; j++)
      {
        sum = WeightIH[i][j];
      }
      sum /= 51;
      weights[i] = sum;
    }

    for (i = 0; i < 51; i++)
    {
      printf("weight[%d] = %G\n", i, weights[i]);
    }
    return 1 ;
}
user3629249
  • 16,402
  • 1
  • 16
  • 17