IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 40371


Ignore:
Timestamp:
Mar 16, 2018, 4:06:05 PM (8 years ago)
Author:
eugene
Message:

fix up the nnet code to match behavior of the python version

Location:
trunk/Ohana/src/opihi
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Ohana/src/opihi/cmd.data/nnet.c

    r40320 r40371  
    44  {1, "list",     nnet_list,     "list nnets"},
    55  {1, "delete",   nnet_delete,   "delete a nnet"},
    6   // {1, "show",     nnet_show,     "display nnet values"},
     6  {1, "print",    nnet_print,    "display nnet values"},
    77  {1, "create",   nnet_create,   "create a nnet"},
    88  {1, "set",      nnet_set,      "set nnet node values"},
    99  {1, "get",      nnet_get,      "get nnet node values"},
     10  {1, "read",     nnet_read,     "read nnet values from a file"},
     11// {1, "write",    nnet_write,    "write nnet values to a file"},
    1012  {1, "train",    nnet_train,    "train nnet on a set of data"},
    1113  {1, "apply",    nnet_apply,    "apply nnet to a set of data"},
     
    2022    gprint (GP_ERR, "    nnet list          : list nnets\n");
    2123    gprint (GP_ERR, "    nnet delete (nnet) : delete a nnet\n");
    22     gprint (GP_ERR, "    nnet show   (nnet) : show values for a nnet\n");
     24    gprint (GP_ERR, "    nnet print  (nnet) : print values for a nnet\n");
    2325    gprint (GP_ERR, "    nnet create (nnet) (Ninput) [Nnodes] [Nnodes] ... (Noutput) : create a nnet\n");
    2426    gprint (GP_ERR, "    nnet set    (nnet) [weights] [biases] ... [weights] [biases] : set nnet weights (images) and biases (vectors)\n");
    2527    gprint (GP_ERR, "    nnet get    (nnet) [weights] [biases] ... [weights] [biases] : get nnet weights (images) and biases (vectors)\n");
     28    gprint (GP_ERR, "    nnet read   (nnet) (filename) : set nnet weights and biases using a data file\n");
    2629    gprint (GP_ERR, "    nnet train  (nnet) [input] [input] ... [output] [output] ... : train nnet on data from a set of vectors\n");
    2730    gprint (GP_ERR, "    nnet apply  (nnet) [input] [input] ... [output] [output] ... : apply nnet to input data and generate output\n");
  • trunk/Ohana/src/opihi/cmd.data/nnet_commands.c

    r40336 r40371  
    6262  CreateNnetData (nnet, LargeWeightInit);
    6363
     64  return TRUE;
     65}
     66
     67int nnet_print (int argc, char **argv) {
     68
     69  if (argc != 2) {
     70    gprint (GP_ERR, "USAGE: nnet print (nnet)\n");
     71    return FALSE;
     72  }
     73
     74  Nnet *nnet = FindNnet (argv[1]);
     75  if (nnet == NULL) {
     76    gprint (GP_ERR, "nnet %s not found, create it first\n", argv[1]);
     77    return FALSE;
     78  }
     79
     80  PrintNnet (nnet);
    6481  return TRUE;
    6582}
     
    146163}
    147164
     165int nnet_read (int argc, char **argv) {
     166
     167  # define D_LINE 0x10000
     168  char word[128];
     169  char line[D_LINE];
     170
     171  if (argc < 3) {
     172    gprint (GP_ERR, "USAGE: nnet read (nnet) (filename) : set nnet weights and biases based on a file\n");
     173    gprint (GP_ERR, "the first line of the file specifies the number of layers, each layer in the network is written as a matrix of numbers (weights) and a vector\n");
     174    return FALSE;
     175  }
     176
     177  // open the file and read the number of layers
     178  FILE *f = fopen (argv[2], "r");
     179  if (f == NULL) {
     180    gprint (GP_ERR, "USAGE: nnet read (nnet) (filename) : set nnet weights and biases based on a file\n");
     181    gprint (GP_ERR, "file %s could not be opened\n", argv[2]);
     182    return FALSE;
     183  }
     184
     185  // read the number of layers
     186  // NLAYER 3
     187  int Nlayer;
     188  scan_line_maxlen (f, line, D_LINE);
     189  sscanf (line, "%127s %d", word, &Nlayer);
     190  if (strcmp(word, "NLAYER")) {
     191    gprint (GP_ERR, "warning: NLAYER keyword not found\n");
     192  }
     193
     194  Nnet *nnet = CreateNnet (argv[1], Nlayer);
     195
     196  // read the number of nodes
     197  // LAYERS 2 4 2
     198  scan_line_maxlen (f, line, D_LINE);
     199  char *tmpword = getword (line);
     200  if (strcmp (tmpword, "LAYERS")) {
     201    gprint (GP_ERR, "warning: LAYERS keyword not found\n");
     202  }
     203  FREE (tmpword);
     204  for (int i = 0; i < Nlayer; i++) {
     205    int Nnode;
     206    int status = iparse (&Nnode, i + 2, line); // numbering is fields 1 2 3
     207    if (!status) {
     208      gprint (GP_ERR, "error: failed to find all Nnode values\n");
     209      fclose (f);
     210      DeleteNnet (nnet);
     211      return FALSE;
     212    }
     213    nnet[0].Nnodes[i] = Nnode;
     214  }
     215
     216  // this creates the data for each node and inits with gaussian weights
     217  CreateNnetData (nnet, FALSE);
     218
     219  // read the weights and biases from the data file
     220  for (int L = 1; L < nnet[0].Nlayer; L++) {
     221   
     222    char word1[128], word2[128], word3[128];
     223    int Nx, Ny, layer;
     224    scan_line_maxlen (f, line, D_LINE);
     225    sscanf (line, "%127s %d %127s %d %127s %d", word1, &layer, word2, &Nx, word3, &Ny);
     226    gprint (GP_ERR, "LAYER: %d, Nx: %d, Ny: %d\n", layer, Nx, Ny);
     227
     228    if (layer != L - 1) {
     229      gprint (GP_ERR, "warning: expect layer = %d, got %d\n", L - 1, layer);
     230    }
     231    if (Nx != nnet[0].Nnodes[L - 1]) {
     232      gprint (GP_ERR, "warning: expect Nx = %d, got %d\n", nnet[0].Nnodes[L - 1], Nx);
     233    }
     234    if (Ny != nnet[0].Nnodes[L]) {
     235      gprint (GP_ERR, "warning: expect Ny = %d, got %d\n", nnet[0].Nnodes[L], Ny);
     236    }
     237
     238    double value;
     239    for (int j = 0; j < Ny; j++) {
     240      scan_line_maxlen (f, line, D_LINE);
     241      for (int i = 0; i < Nx; i++) {
     242        int k = i + j*nnet[0].Nnodes[L-1];
     243        int status = dparse (&value, i + 1, line);
     244        if (!status) {
     245          gprint (GP_ERR, "error: failed to read entry from a line (layer: %d, i: %d, j: %d)\n", layer, i, j);
     246          fclose (f);
     247          DeleteNnet (nnet);
     248          return FALSE;
     249        }
     250        nnet[0].weight[L][k] = value;
     251      }
     252      dparse (&value, Nx + 1, line);
     253      nnet[0].biases[L][j] = value;
     254    }
     255  }
     256
     257  return TRUE;
     258}
     259
    148260int nnet_get (int argc, char **argv) {
    149261
  • trunk/Ohana/src/opihi/cmd.data/nnet_train.c

    r40336 r40371  
    1010void  nnet_backprop (Nnet *nnet, Vector **inVec, Vector **outVec, int N);
    1111void  nnet_descent_step (Nnet *nnet, Vector **inVec, Vector **outVec, int *seq, int pass, int Nmini, float eta, float lambda);
     12void  nnet_print_Nabla (Nnet *nnet);
     13void  nnet_write_Nabla (char *filename, Nnet *nnet);
    1214
    1315static int QUADRATIC_COST = 0;
     
    7678    gprint (GP_ERR, "USAGE: nnet train (nnet) [input] [input] ... [output] [output] ...\n");
    7779    gprint (GP_ERR, "OPTIONS: -Nepoch [N] -Nmini [N]\n");
    78     FREE (resid);
     80    // FREE (resid);
    7981    return FALSE;
    8082  }
     
    8385  if (nnet == NULL) {
    8486    gprint (GP_ERR, "nnet %s not found, create it first\n", argv[1]);
    85     FREE (resid);
     87    // FREE (resid);
    8688    return FALSE;
    8789  }
     
    9597  if (argc != Ninput + Noutput + 2) {
    9698    gprint (GP_ERR, "need %d input and %d output vectors, but we have %d total\n", nnet[0].Nnodes[0], nnet[0].Nnodes[Nlayer - 1], argc - 2);
    97     FREE (resid);
     99    // FREE (resid);
    98100    return FALSE;
    99101  }
     
    111113      free (inVec);
    112114      free (outVec);
    113       FREE (resid);
     115      // FREE (resid);
    114116      return FALSE;   
    115117    }
     
    118120      free (inVec);
    119121      free (outVec);
    120       FREE (resid);
     122      // FREE (resid);
    121123      return FALSE;   
    122124    }
     
    126128      free (inVec);
    127129      free (outVec);
    128       FREE (resid);
     130      // FREE (resid);
    129131      return FALSE;   
    130132    }
     
    136138      free (inVec);
    137139      free (outVec);
    138       FREE (resid);
     140      // FREE (resid);
    139141      return FALSE;   
    140142    }
     
    143145      free (inVec);
    144146      free (outVec);
    145       FREE (resid);
     147      // FREE (resid);
    146148      return FALSE;   
    147149    }
     
    181183  }
    182184
     185  // PrintNnet (nnet);
     186
    183187  // train for Nepochs
    184188  // this recreates 'SGD' from http://neuralnetworksanddeeplearning.com/chap1.html
     
    194198      // update the weights and biases using the mini batch subset
    195199      nnet_descent_step (nnet, inVec, outVec, seq, pass, Nmini, eta, lambda);
    196     }
     200      // return TRUE; // XXX short-circuit at one step
     201    }
     202    // PrintNnet (nnet);
    197203
    198204    if (resid) {
     
    218224      float mean = s1 / Npts;
    219225      float sigma = sqrt(s2 / Npts - mean*mean);
    220       if (epoch % 10 == 0) gprint (GP_ERR, "epoch %d of %d, %f +/- %f\n", epoch, Nepoch, mean, sigma);
     226      // if (epoch % 10 == 0) gprint (GP_ERR, "epoch %d of %d, %f +/- %f\n", epoch, Nepoch, mean, sigma);
     227      gprint (GP_ERR, "epoch %d of %d, %f +/- %f\n", epoch, Nepoch, mean, sigma);
    221228      resid[0].elements.Flt[epoch] = sigma;
    222229    } else {
    223       if (epoch % 10 == 0) gprint (GP_ERR, "epoch %d of %d\n", epoch, Nepoch);
     230      // if (epoch % 10 == 0) gprint (GP_ERR, "epoch %d of %d\n", epoch, Nepoch);
     231      gprint (GP_ERR, "epoch %d of %d\n", epoch, Nepoch);
    224232    }
    225233  } 
     234  // PrintNnet (nnet);
    226235
    227236  if (result) {
     
    265274
    266275    // N is the element of the mini batch on which we are currently operating
    267     int N = seq[pass*Nmini + i];
     276    // int N = seq[pass*Nmini + i]; // XXX uncomment to turn on random shuffle
     277    int N = pass*Nmini + i;
    268278
    269279    // backprop generates a dNabla_b, dNabla_w pair for the element N of the input and output vectors
    270280    nnet_backprop (nnet, inVec, outVec, N);
    271 
    272281    nnet_update_Nabla (nnet);
    273   }
    274 
     282    // gprint (GP_ERR, ". ");
     283
     284    // nnet_print_Nabla (nnet); // XXX print nabla for each epoch
     285    // XXX uncomment to dump nablas after one step, one element
     286    // nnet_write_Nabla ("test.nabla.op.dat", nnet); // XXX print nabla for each epoch
     287    // return;
     288  }
     289  // gprint (GP_ERR, " done mini batch\n");
     290
     291  // nnet_print_Nabla (nnet);
    275292  nnet_apply_Nabla (nnet, Nmini, eta, lambda, Ntrial);
     293
     294  // XXX uncomment to dump nablas after one mini batch
     295  // nnet_write_Nabla ("test.nabla.op.dat", nnet); // XXX print nabla for each epoch
     296  // PrintNnet (nnet);
    276297}
    277298
     
    317338      }
    318339    } else {
     340      // XXX TEST PRINTS to catch code errors compared to python implementation
     341      // gprint (GP_ERR, "z: ");
     342      // for (int j = 0; j < nnet[0].Nnodes[L]; j++) {
     343      //        gprint (GP_ERR, "%f ",  nnet[0].zvalue[L][j]);
     344      // } gprint (GP_ERR, "\n");
     345      // gprint (GP_ERR, "sp: ");
     346      // for (int j = 0; j < nnet[0].Nnodes[L]; j++) {
     347      //        gprint (GP_ERR, "%f ",  nnet[0].sprime[L][j]);
     348      // } gprint (GP_ERR, "\n");
     349
    319350      // delta = DOT(delta, transpose(weight[L+1])) * sprime;
    320351      for (int j = 0; j < nnet[0].Nnodes[L]; j++) {
     
    322353        for (int i = 0; i < nnet[0].Nnodes[L+1]; i++) {
    323354          int k = j + i*nnet[0].Nnodes[L]; // note order of (i,j) : j is [L+1] direction
    324           tmpdelta += nnet[0].weight[L][k] * nnet[0].delta[L+1][i];
     355          myAssert (k < nnet[0].Nnodes[L]*nnet[0].Nnodes[L+1], "overflow");
     356          tmpdelta += nnet[0].weight[L+1][k] * nnet[0].delta[L+1][i];
     357          // gprint (GP_ERR, "%e %e\n", nnet[0].weight[L+1][k], nnet[0].delta[L+1][i]);
    325358        }
    326359        nnet[0].delta[L][j] = tmpdelta * nnet[0].sprime[L][j];
     
    335368    // Nabla_b[L] = delta;
    336369    for (int j = 0; j < nnet[0].Nnodes[L]; j++) {
    337       nnet[0]. Nabla_b[L][j] = nnet[0].delta[L][j];
     370      nnet[0]. dNabla_b[L][j] = nnet[0].delta[L][j];
    338371    }
    339372   
     
    342375      for (int i = 0; i < nnet[0].Nnodes[L-1]; i++) {
    343376        int k = i + j*nnet[0].Nnodes[L-1];
    344         nnet[0]. Nabla_w[L][k] = nnet[0].svalue[L-1][i] * nnet[0].delta[L][j];
     377        myAssert (k < nnet[0].Nnodes[L-1]*nnet[0].Nnodes[L], "overflow");
     378        nnet[0]. dNabla_w[L][k] = nnet[0].svalue[L-1][i] * nnet[0].delta[L][j];
    345379      }
    346380    }
     
    349383
    350384// support functions to loop over the Nabla entries
     385void nnet_reset_Nabla (Nnet *nnet) {
     386  for (int L = 1; L < nnet[0].Nlayer; L++) {
     387
     388    for (int j = 0; j < nnet[0].Nnodes[L]; j++) {
     389
     390      nnet[0]. Nabla_b[L][j] = 0;
     391      nnet[0].dNabla_b[L][j] = 0;
     392
     393      for (int i = 0; i < nnet[0].Nnodes[L-1]; i++) {
     394        int k = i + j*nnet[0].Nnodes[L-1];
     395        myAssert (k < nnet[0].Nnodes[L-1]*nnet[0].Nnodes[L], "overflow");
     396        nnet[0]. Nabla_w[L][k] = 0;
     397        nnet[0].dNabla_w[L][k] = 0;
     398      }
     399    }
     400  }
     401}
     402void nnet_update_Nabla (Nnet *nnet) {
     403  for (int L = 1; L < nnet[0].Nlayer; L++) {
     404
     405    for (int j = 0; j < nnet[0].Nnodes[L]; j++) {
     406      nnet[0]. Nabla_b[L][j] += nnet[0].dNabla_b[L][j];
     407
     408      for (int i = 0; i < nnet[0].Nnodes[L-1]; i++) {
     409        int k = i + j*nnet[0].Nnodes[L-1];
     410        myAssert (k < nnet[0].Nnodes[L-1]*nnet[0].Nnodes[L], "overflow");
     411        nnet[0]. Nabla_w[L][k] += nnet[0].dNabla_w[L][k];
     412      }
     413    }
     414  }
     415}
    351416void nnet_apply_Nabla (Nnet *nnet, int Nmini, float eta, float lambda, int Ntrial) {
    352417  for (int L = 1; L < nnet[0].Nlayer; L++) {
     
    357422      for (int i = 0; i < nnet[0].Nnodes[L-1]; i++) {
    358423        int k = i + j*nnet[0].Nnodes[L-1];
     424        myAssert (k < nnet[0].Nnodes[L-1]*nnet[0].Nnodes[L], "overflow");
    359425        // nnet[0].weight[L][k] -= (eta / Nmini) * nnet[0].Nabla_w[L][k];
    360426        // with lambda > 0.0, we have L2 regularization.  if lambda = 0.0, we recover the default implementation
     
    364430  }
    365431}
    366 void nnet_update_Nabla (Nnet *nnet) {
     432
     433void nnet_print_Nabla (Nnet *nnet) {
     434
    367435  for (int L = 1; L < nnet[0].Nlayer; L++) {
    368 
    369     for (int j = 0; j < nnet[0].Nnodes[L]; j++) {
    370       nnet[0]. Nabla_b[L][j] += nnet[0].dNabla_b[L][j];
    371 
     436    gprint (GP_ERR, " ----- Nabla %d -----\n", L);
     437    for (int j = 0; j < nnet[0].Nnodes[L]; j++) {
    372438      for (int i = 0; i < nnet[0].Nnodes[L-1]; i++) {
    373         int k = i + j*nnet[0].Nnodes[L-1];
    374         nnet[0]. Nabla_w[L][k] += nnet[0].dNabla_w[L][k];
    375       }
    376     }
    377   }
    378 }
    379 void nnet_reset_Nabla (Nnet *nnet) {
     439        int k = j * nnet[0].Nnodes[L-1] + i;
     440        myAssert (k < nnet[0].Nnodes[L-1]*nnet[0].Nnodes[L], "overflow");
     441        gprint (GP_ERR, "%10.3e ", nnet[0].Nabla_w[L][k]);
     442      }
     443      gprint (GP_ERR, " : %10.3e\n", nnet[0].Nabla_b[L][j]);
     444    }
     445  }
     446  return;
     447}
     448
     449void nnet_write_Nabla (char *filename, Nnet *nnet) {
     450
     451  FILE *f = fopen (filename, "w");
     452
     453  fprintf (f, "NLAYER %d\n", nnet[0].Nlayer);
     454  fprintf (f, "LAYERS ");
     455  for (int L = 0; L < nnet[0].Nlayer; L++) {
     456    fprintf (f, "%d ", nnet[0].Nnodes[L]);
     457  }
     458  fprintf (f, "\n");
     459
    380460  for (int L = 1; L < nnet[0].Nlayer; L++) {
    381 
    382     for (int j = 0; j < nnet[0].Nnodes[L]; j++) {
    383 
    384       nnet[0]. Nabla_b[L][j] = 0;
    385       nnet[0].dNabla_b[L][j] = 0;
    386 
     461    fprintf (f, "LAYER %d NX %d NY %d\n", L - 1, nnet[0].Nnodes[L-1], nnet[0].Nnodes[L]);
     462    for (int j = 0; j < nnet[0].Nnodes[L]; j++) {
    387463      for (int i = 0; i < nnet[0].Nnodes[L-1]; i++) {
    388         int k = i + j*nnet[0].Nnodes[L-1];
    389         nnet[0]. Nabla_w[L][k] = 0;
    390         nnet[0].dNabla_w[L][k] = 0;
    391       }
    392     }
    393   }
     464        int k = j * nnet[0].Nnodes[L-1] + i;
     465        myAssert (k < nnet[0].Nnodes[L-1]*nnet[0].Nnodes[L], "overflow");
     466        fprintf (f, "%.9f ", nnet[0].Nabla_w[L][k]);
     467      }
     468      fprintf (f, "%.9f\n", nnet[0].Nabla_b[L][j]);
     469    }
     470  }
     471
     472  fclose (f);
     473  return;
    394474}
    395475
     
    410490
    411491  // evaluating a single layer [L], n > 0, n < Nlayer:
    412   int Ninput   = nnet[0].Nnodes[L - 1];
     492  int Ninput   = nnet[0].Nnodes[L-1];
    413493  int Noutput  = nnet[0].Nnodes[L];
    414494
     
    419499      // weight matrix order is (0, 1, ... Ninput-1, Ninput, Ninput + 1, ... Ninput * Noutput - 1)
    420500      int k = j * Ninput + i;
     501      myAssert (k < Ninput*Noutput, "overflow");
    421502      sum += nnet[0].weight[L][k]*nnet[0].svalue[L-1][i];
    422503    }
  • trunk/Ohana/src/opihi/cmd.data/test/nnet.sh

    r40335 r40371  
    11
    2 macro test
    3 
    4   nnet create t0 5 10 15 3
    5   nnet list
    6 
    7   nnet create t1 6 4 5
    8   nnet list
    9 
    10   nnet create t1 5 8
    11   nnet list
    12 
    13   # vlist v0 1 2 3 4 5
    14   vlist v1 1 2 3 4 5 6 7 8
    15 
    16   mcreate m1 5 8
    17  
    18   # generate a weight vector of length v1[]
    19   vlist my 9 8 7 6 5 4 3 2
    20 
    21   for i 0 5
    22     mset m1 my -y $i
    23     set my = my + $i
    24   end
    25  
    26   # set weights and biases
    27   nnet set t1 m1 v1
    28 
    29   # get weights and biases
    30   nnet get t1 M1 V1
    31 
    32   # compare
    33   set dv = v1 - V1
    34   vstat dv
    35 
    36   set dm = m1 - M1
    37   stat dm
    38  
    39 end
    40 
    41 macro test2
    42 
    43   nnet create t1 2 2
    44   nnet list
    45 
    46   # output = sigmoid (sum(weight[i][j] * input[i]) + bias[j])
    47 
    48   # biases of
    49   vlist v1 0.8 0.2
    50 
    51   mcreate m1 2 2
    52   m1[0][0] =  0.5
    53   m1[1][0] =  0.1
    54   m1[0][1] = -0.2
    55   m1[1][1] =  0.8
    56 
    57   # set weights and biases
    58   nnet set t1 m1 v1
    59 
    60   vlist vin0 1 2
    61   vlist vin1 2 1
    62 
    63   # get weights and biases
    64   nnet apply t1 vin0 vin1 vout0 vout1
    65  
    66   vlist z0 {m1[0][0]*vin0[0] + m1[1][0]*vin1[0] + v1[0]} {m1[0][0]*vin0[1] + m1[1][0]*vin1[1] + v1[0]}
    67   vlist z1 {m1[0][1]*vin0[0] + m1[1][1]*vin1[0] + v1[1]} {m1[0][1]*vin0[1] + m1[1][1]*vin1[1] + v1[1]}
    68   set t0 = 1 / (1 + exp(-1*z0))
    69   set t1 = 1 / (1 + exp(-1*z1))
    70 
    71   # compare
    72   set dt0 = t0 - vout0
    73   vstat dt0
    74 
    75   set dt1 = t1 - vout1
    76   vstat dt1
    77 end
    78 
    79 macro test3
    80 
    81   memory all
    82 
    83   nnet create t0 5 10 15 3
    84   nnet list
    85 
    86   nnet create t1 5 8
    87   nnet list
    88 
    89   # vlist v0 1 2 3 4 5
    90   vlist v1 1 2 3 4 5 6 7 8
    91 
    92   mcreate m1 5 8
    93  
    94   # generate a weight vector of length v1[]
    95   vlist my 9 8 7 6 5 4 3 2
    96 
    97   for i 0 5
    98     mset m1 my -y $i
    99     set my = my + $i
    100   end
    101  
    102   # set weights and biases
    103   nnet set t1 m1 v1
    104 
    105   # get weights and biases
    106   nnet get t1 M1 V1
    107 
    108   # compare
    109   set dv = v1 - V1
    110   vstat dv
    111 
    112   set dm = m1 - M1
    113   stat dm
    114  
    115   nnet delete t0
    116   nnet delete t1
    117 
    118   delete m1 M1 dm
    119   delete v1 V1 dv my
    120 
    121   vectors
    122   buffers
    123 
    124   memory all
    125 end
    126 
    127 macro test.simple
     2macro test.python
    1283  if ($0 != 4)
    129     echo "USAGE: test.simple (Nmini) (Nepoch) (eta)"
     4    echo "USAGE: test.python (Nmini) (Nepoch) (eta)"
    1305    break
    1316  end
     7
     8  # test I/O
     9
     10  create x 0 100
     11  set y = dsin(x/10)
     12  write test.dat x y
     13  break
    13214
    13315  local Nmini Nepoch eta
     
    18769end
    18870
     71macro test
     72
     73  nnet create t0 5 10 15 3
     74  nnet list
     75
     76  nnet create t1 6 4 5
     77  nnet list
     78
     79  nnet create t1 5 8
     80  nnet list
     81
     82  # vlist v0 1 2 3 4 5
     83  vlist v1 1 2 3 4 5 6 7 8
     84
     85  mcreate m1 5 8
     86 
     87  # generate a weight vector of length v1[]
     88  vlist my 9 8 7 6 5 4 3 2
     89
     90  for i 0 5
     91    mset m1 my -y $i
     92    set my = my + $i
     93  end
     94 
     95  # set weights and biases
     96  nnet set t1 m1 v1
     97
     98  # get weights and biases
     99  nnet get t1 M1 V1
     100
     101  # compare
     102  set dv = v1 - V1
     103  vstat dv
     104
     105  set dm = m1 - M1
     106  stat dm
     107 
     108end
     109
     110macro test2
     111
     112  nnet create t1 2 2
     113  nnet list
     114
     115  # output = sigmoid (sum(weight[i][j] * input[i]) + bias[j])
     116
     117  # biases of
     118  vlist v1 0.8 0.2
     119
     120  mcreate m1 2 2
     121  m1[0][0] =  0.5
     122  m1[1][0] =  0.1
     123  m1[0][1] = -0.2
     124  m1[1][1] =  0.8
     125
     126  # set weights and biases
     127  nnet set t1 m1 v1
     128
     129  vlist vin0 1 2
     130  vlist vin1 2 1
     131
     132  # get weights and biases
     133  nnet apply t1 vin0 vin1 vout0 vout1
     134 
     135  vlist z0 {m1[0][0]*vin0[0] + m1[1][0]*vin1[0] + v1[0]} {m1[0][0]*vin0[1] + m1[1][0]*vin1[1] + v1[0]}
     136  vlist z1 {m1[0][1]*vin0[0] + m1[1][1]*vin1[0] + v1[1]} {m1[0][1]*vin0[1] + m1[1][1]*vin1[1] + v1[1]}
     137  set t0 = 1 / (1 + exp(-1*z0))
     138  set t1 = 1 / (1 + exp(-1*z1))
     139
     140  # compare
     141  set dt0 = t0 - vout0
     142  vstat dt0
     143
     144  set dt1 = t1 - vout1
     145  vstat dt1
     146end
     147
     148macro test3
     149
     150  memory all
     151
     152  nnet create t0 5 10 15 3
     153  nnet list
     154
     155  nnet create t1 5 8
     156  nnet list
     157
     158  # vlist v0 1 2 3 4 5
     159  vlist v1 1 2 3 4 5 6 7 8
     160
     161  mcreate m1 5 8
     162 
     163  # generate a weight vector of length v1[]
     164  vlist my 9 8 7 6 5 4 3 2
     165
     166  for i 0 5
     167    mset m1 my -y $i
     168    set my = my + $i
     169  end
     170 
     171  # set weights and biases
     172  nnet set t1 m1 v1
     173
     174  # get weights and biases
     175  nnet get t1 M1 V1
     176
     177  # compare
     178  set dv = v1 - V1
     179  vstat dv
     180
     181  set dm = m1 - M1
     182  stat dm
     183 
     184  nnet delete t0
     185  nnet delete t1
     186
     187  delete m1 M1 dm
     188  delete v1 V1 dv my
     189
     190  vectors
     191  buffers
     192
     193  memory all
     194end
     195
     196macro test.simple
     197  if ($0 != 4)
     198    echo "USAGE: test.simple (Nmini) (Nepoch) (eta)"
     199    break
     200  end
     201
     202  local Nmini Nepoch eta
     203  $Nmini  = $1
     204  $Nepoch = $2
     205  $eta    = $3
     206
     207  # create a nnet with just 2 inputs and 2 outputs
     208  nnet create t1 2 2
     209
     210  # biases:
     211  vlist v1 0.5 0.0
     212
     213  # weights
     214  mcreate m1 2 2
     215  m1[0][0] =  0.5
     216  m1[1][0] = -0.2
     217  m1[0][1] = -0.5
     218  m1[1][1] =  0.2
     219
     220  # set weights and biases
     221  nnet set t1 m1 v1
     222
     223  # generate an input set spanning the range -5 to +5
     224
     225  create n 0 1000
     226  set x0 = 10*rnd(n) - 5.0
     227  set x1 = 10*rnd(n) - 5.0
     228
     229  # get output vectors the these input vectors
     230  nnet apply t1 x0 x1 y0 y1
     231
     232# -large-weight-initializer : revert to original implementation
     233# nnet create tn 2 2
     234  nnet create tn 2 2 -large-weight-initializer
     235
     236# -quadratic-cost : revert to original implementation
     237  nnet train tn x0 x1 y0 y1 -Nmini $Nmini -Nepoch $Nepoch -eta $eta -lambda 0.0 -quadratic-cost -resid resid -result result
     238# nnet train tn x0 x1 y0 y1 -Nmini $Nmini -Nepoch $Nepoch -eta $eta -lambda 0.0
     239# nnet train tn x0 x1 y0 y1 -Nmini $Nmini -Nepoch $Nepoch -eta $eta -lambda 2.0
     240
     241  nnet apply tn x0 x1 Y0 Y1
     242
     243  set dy0 = y0 - Y0
     244  set dy1 = y1 - Y1
     245
     246  vstat dy0
     247  $yp = $MAX
     248  $ym = $MIN
     249
     250  vstat dy1
     251  $yp = max ($MAX , $yp)
     252  $ym = min ($MIN , $ym)
     253  $yp = 0.02; $ym = -0.02
     254
     255  style -pt circle -sz 2; lim x0 $ym $yp; clear; box; plot -c blue x0 dy0; plot -c red x0 dy1
     256end
     257
    189258macro test.bilevel
    190259  if ($0 != 4)
     
    284353end
    285354
     355macro test.bilevel.small
     356  if ($0 != 4)
     357    echo "USAGE: test.bilevel (Nmini) (Nepoch) (eta)"
     358    break
     359  end
     360
     361  local Nmini Nepoch eta
     362  $Nmini  = $1
     363  $Nepoch = $2
     364  $eta    = $3
     365
     366  # create a nnet with just 2 inputs and 2 outputs
     367  nnet create t1 2 3 2
     368
     369  # biases:
     370  vlist v1 -0.2 0.0 0.2
     371  vlist v2 -0.3 0.3
     372
     373  # weights
     374  mcreate m1 2 3
     375  m1[0][0] =  0.2
     376  m1[1][0] = -0.2
     377  m1[0][1] = -0.6
     378  m1[1][1] =  0.5
     379  m1[0][2] = -0.2
     380  m1[1][2] =  0.2
     381
     382  mcreate m2 3 2
     383  m2[0][0] = -0.6
     384  m2[1][0] = -0.4
     385  m2[2][0] = -0.5
     386
     387  m2[0][1] = -0.2
     388  m2[1][1] = -0.5
     389  m2[2][1] =  0.1
     390
     391  # set weights and biases
     392  nnet set t1 m1 v1 m2 v2
     393
     394  # generate an input set spanning the range -5 to +5
     395
     396  create n 0 1000
     397  set x0 = 10*rnd(n) - 5.0
     398  set x1 = 10*rnd(n) - 5.0
     399
     400  # get output vectors the these input vectors
     401  nnet apply t1 x0 x1 y0 y1
     402
     403# nnet create tn 3 4 3 -large-weight-initializer
     404  nnet create tn 2 3 2
     405
     406# make the starting point close to the solution
     407  m2[0][0] = -0.58
     408# v2[1] = 0.25
     409  nnet set tn m1 v1 m2 v2
     410
     411# nnet train tn x0 x1 x2 y0 y1 y2 -Nmini $Nmini -Nepoch $Nepoch -eta $eta -lambda 0.1
     412# nnet train tn x0 x1 y0 y1 -Nmini $Nmini -Nepoch $Nepoch -eta $eta -lambda 0.0 -quadratic-cost -resid dS -result result
     413  nnet train tn x0 x1 y0 y1 -Nmini $Nmini -Nepoch $Nepoch -eta $eta -lambda 0.0 -resid dS -result result
     414
     415  nnet apply tn x0 x1 Y0 Y1
     416
     417  set dy0 = y0 - Y0
     418  set dy1 = y1 - Y1
     419
     420  vstat dy0
     421  $yp = $MAX
     422  $ym = $MIN
     423
     424  vstat dy1
     425  $yp = max ($MAX , $yp)
     426  $ym = min ($MIN , $ym)
     427
     428  dev -n 0
     429  style -pt circle -sz 2;
     430  lim x0 $ym $yp; clear; box;
     431  plot -c blue  x0 dy0;
     432  plot -c red   x0 dy1
     433
     434  set n = ramp(dS)
     435  lim -n 1 n dS; clear; box; plot n dS
     436end
     437
     438macro test.bilevel.grid.wt
     439  if ($0 != 4)
     440    echo "USAGE: test.bilevel.grid.wt (level) (x) (y)"
     441    break
     442  end
     443
     444  local Level ix iy
     445  $Level  = $1
     446  $ix     = $2
     447  $iy     = $3
     448
     449  # create a nnet with just 2 inputs and 2 outputs
     450  nnet create t1 2 3 2
     451
     452  # biases:
     453  vlist v1 -0.2 0.0 0.2
     454  vlist v2 -0.3 0.3
     455
     456  # weights
     457  mcreate m1 2 3
     458  m1[0][0] =  0.2
     459  m1[1][0] = -0.2
     460  m1[0][1] = -0.6
     461  m1[1][1] =  0.5
     462  m1[0][2] = -0.2
     463  m1[1][2] =  0.2
     464
     465  mcreate m2 3 2
     466  m2[0][0] = -0.6
     467  m2[1][0] = -0.4
     468  m2[2][0] = -0.5
     469
     470  m2[0][1] = -0.2
     471  m2[1][1] = -0.5
     472  m2[2][1] =  0.1
     473
     474  # set weights and biases
     475  nnet set t1 m1 v1 m2 v2
     476
     477  # generate an input set spanning the range -5 to +5
     478
     479  create n 0 1000
     480  set x0 = 10*rnd(n) - 5.0
     481  set x1 = 10*rnd(n) - 5.0
     482
     483  # get output vectors from these input vectors
     484  nnet apply t1 x0 x1 y0 y1
     485
     486  # create a test nnet
     487  nnet create tn 2 3 2
     488
     489  # 1D chi-square grid about truth
     490 
     491  set M1 = m1
     492  set M2 = m2
     493  set V1 = v1
     494  set V2 = v2
     495
     496  # disturb one element to see cross terms
     497  M2[0][0] = -0.58
     498
     499  $To = M$Level[$ix][$iy]
     500
     501  delete -q value svec0 svec1 sigvec
     502  for frac 0.90 1.10 0.005
     503    M$Level[$ix][$iy] = $frac * $To
     504
     505    nnet set tn M1 V1 M2 V2
     506    nnet apply tn x0 x1 Y0 Y1
     507
     508    set dy0 = y0 - Y0
     509    set dy1 = y1 - Y1
     510
     511    vstat -q dy0
     512    $S0 = $SIGMA 
     513
     514    vstat -q dy1
     515    $S1 = $SIGMA
     516
     517    concat {$frac * $To} value
     518    concat $S0 svec0
     519    concat $S1 svec1
     520
     521    concat {sqrt($S0^2 + $S1^2)} sigvec
     522  end
     523
     524  vstat -q sigvec
     525
     526  lim -n 1 value -0.0001 $MAX; clear; box;
     527  plot -c black value sigvec;
     528  plot -c blue value svec0 -pt ocir -sz 2 ;
     529  plot -c red value svec1 -pt ocir -sz 2
     530end
     531
     532macro test.bilevel.grid.wt.2d
     533  if ($0 != 7)
     534    echo "USAGE: test.bilevel.grid.wt.2d (level) (x) (y) (level) (x) (y)"
     535    break
     536  end
     537
     538  local LevelA ixA iyA LevelB ixB iyB
     539  $LevelA  = $1
     540  $ixA     = $2
     541  $iyA     = $3
     542  $LevelB  = $4
     543  $ixB     = $5
     544  $iyB     = $6
     545
     546  # create a nnet with just 2 inputs and 2 outputs
     547  nnet create t1 2 3 2
     548
     549  # biases:
     550  vlist v1 -0.2 0.0 0.2
     551  vlist v2 -0.3 0.3
     552
     553  # weights
     554  mcreate m1 2 3
     555  m1[0][0] =  0.2
     556  m1[1][0] = -0.2
     557  m1[0][1] = -0.6
     558  m1[1][1] =  0.5
     559  m1[0][2] = -0.2
     560  m1[1][2] =  0.2
     561
     562  mcreate m2 3 2
     563  m2[0][0] = -0.6
     564  m2[1][0] = -0.4
     565  m2[2][0] = -0.5
     566
     567  m2[0][1] = -0.2
     568  m2[1][1] = -0.5
     569  m2[2][1] =  0.1
     570
     571  # set weights and biases
     572  nnet set t1 m1 v1 m2 v2
     573
     574  # generate an input set spanning the range -5 to +5
     575
     576  create n 0 1000
     577  set x0 = 10*rnd(n) - 5.0
     578  set x1 = 10*rnd(n) - 5.0
     579
     580  # get output vectors from these input vectors
     581  nnet apply t1 x0 x1 y0 y1
     582
     583  # create a test nnet
     584  nnet create tn 2 3 2
     585
     586  # 1D chi-square grid about truth
     587 
     588  set M1 = m1
     589  set M2 = m2
     590  set V1 = v1
     591  set V2 = v2
     592
     593  # disturb one element to see cross terms
     594  M2[0][0] = -0.58
     595
     596  $ToA = M$LevelA[$ixA][$iyA]
     597  $ToB = M$LevelB[$ixB][$iyB]
     598
     599  delete -q valueA valueB sigvec
     600
     601  mcreate sigbuf 41 41
     602
     603  $ix = 0
     604  for fracA 0.90 1.10 0.005
     605    M$LevelA[$ixA][$iyA] = $fracA * $ToA
     606
     607    $iy = 0   
     608    for fracB 0.90 1.10 0.005
     609   
     610      M$LevelB[$ixB][$iyB] = $fracB * $ToB
     611
     612      nnet set tn M1 V1 M2 V2
     613      nnet apply tn x0 x1 Y0 Y1
     614     
     615      set dy0 = y0 - Y0
     616      set dy1 = y1 - Y1
     617     
     618      vstat -q dy0
     619      $S0 = $SIGMA 
     620     
     621      vstat -q dy1
     622      $S1 = $SIGMA
     623     
     624      $sigval = sqrt($S0^2 + $S1^2)
     625      concat {$fracA * $ToA} valueA
     626      concat {$fracB * $ToB} valueB
     627      concat $sigval sigvec
     628
     629      sigbuf[$ix][$iy] = $sigval
     630      $iy ++
     631    end
     632    $ix ++
     633  end
     634
     635  stat -q sigbuf
     636  tv -n tv sigbuf $MIN {$MAX - $MIN}
     637end
  • trunk/Ohana/src/opihi/include/data.h

    r40325 r40371  
    263263void CreateNnetData (Nnet *nnet, int LargeWeightInit);
    264264
    265 int DeleteNnet (Nnet *nnet);
     265void PrintNnet (Nnet *nnet);
     266int  DeleteNnet (Nnet *nnet);
    266267void ListNnets ();
    267268
     
    273274int nnet_list (int argc, char **argv);
    274275int nnet_delete (int argc, char **argv);
    275 int nnet_show (int argc, char **argv);
    276276int nnet_create (int argc, char **argv);
    277277int nnet_set (int argc, char **argv);
    278278int nnet_get (int argc, char **argv);
     279int nnet_read (int argc, char **argv);
     280int nnet_print (int argc, char **argv);
    279281
    280282// in cmd.data/nnet_train.c:
  • trunk/Ohana/src/opihi/lib.data/nnet.c

    r40325 r40371  
    4545
    4646  nnet[0].Nlayer = Nlayer;
    47   ALLOCATE (nnet[0].Nnodes, int, Nlayer);
    48   ALLOCATE (nnet[0].weight, float *, Nlayer);
    49   ALLOCATE (nnet[0].biases, float *, Nlayer);
    50   ALLOCATE (nnet[0].svalue, float *, Nlayer);
    51   ALLOCATE (nnet[0].zvalue, float *, Nlayer);
    52   ALLOCATE (nnet[0].sprime, float *, Nlayer);
    53   ALLOCATE (nnet[0].delta , float *, Nlayer);
    54 
    55   ALLOCATE (nnet[0]. Nabla_b, float *, Nlayer);
    56   ALLOCATE (nnet[0].dNabla_b, float *, Nlayer);
    57   ALLOCATE (nnet[0]. Nabla_w, float *, Nlayer);
    58   ALLOCATE (nnet[0].dNabla_w, float *, Nlayer);
     47  ALLOCATE_ZERO (nnet[0].Nnodes, int, Nlayer);
     48  ALLOCATE_ZERO (nnet[0].weight, float *, Nlayer);
     49  ALLOCATE_ZERO (nnet[0].biases, float *, Nlayer);
     50  ALLOCATE_ZERO (nnet[0].svalue, float *, Nlayer);
     51  ALLOCATE_ZERO (nnet[0].zvalue, float *, Nlayer);
     52  ALLOCATE_ZERO (nnet[0].sprime, float *, Nlayer);
     53  ALLOCATE_ZERO (nnet[0].delta , float *, Nlayer);
     54
     55  ALLOCATE_ZERO (nnet[0]. Nabla_b, float *, Nlayer);
     56  ALLOCATE_ZERO (nnet[0].dNabla_b, float *, Nlayer);
     57  ALLOCATE_ZERO (nnet[0]. Nabla_w, float *, Nlayer);
     58  ALLOCATE_ZERO (nnet[0].dNabla_w, float *, Nlayer);
    5959}
    6060
     
    6363    int i;
    6464
    65     free (nnet[0].name);
     65    FREE (nnet[0].name);
    6666    for (i = 0; i < nnet[0].Nlayer; i++) {
    67       free (nnet[0].weight[i]);
    68       free (nnet[0].biases[i]);
    69       free (nnet[0].svalue[i]);
    70       free (nnet[0].zvalue[i]);
    71       free (nnet[0].sprime[i]);
    72       free (nnet[0].delta [i]);
    73 
    74       free (nnet[0]. Nabla_b[i]);
    75       free (nnet[0].dNabla_b[i]);
    76       free (nnet[0]. Nabla_w[i]);
    77       free (nnet[0].dNabla_w[i]);
    78     }
    79     free (nnet[0].Nnodes);
    80     free (nnet[0].weight);
    81     free (nnet[0].biases);
    82     free (nnet[0].svalue);
    83     free (nnet[0].zvalue);
    84     free (nnet[0].sprime);
    85     free (nnet[0].delta );
    86 
    87     free (nnet[0]. Nabla_b);
    88     free (nnet[0].dNabla_b);
    89     free (nnet[0]. Nabla_w);
    90     free (nnet[0].dNabla_w);
     67      FREE (nnet[0].weight[i]);
     68      FREE (nnet[0].biases[i]);
     69      FREE (nnet[0].svalue[i]);
     70      FREE (nnet[0].zvalue[i]);
     71      FREE (nnet[0].sprime[i]);
     72      FREE (nnet[0].delta [i]);
     73
     74      FREE (nnet[0]. Nabla_b[i]);
     75      FREE (nnet[0].dNabla_b[i]);
     76      FREE (nnet[0]. Nabla_w[i]);
     77      FREE (nnet[0].dNabla_w[i]);
     78    }
     79    FREE (nnet[0].Nnodes);
     80    FREE (nnet[0].weight);
     81    FREE (nnet[0].biases);
     82    FREE (nnet[0].svalue);
     83    FREE (nnet[0].zvalue);
     84    FREE (nnet[0].sprime);
     85    FREE (nnet[0].delta );
     86
     87    FREE (nnet[0]. Nabla_b);
     88    FREE (nnet[0].dNabla_b);
     89    FREE (nnet[0]. Nabla_w);
     90    FREE (nnet[0].dNabla_w);
    9191}
    9292
     
    236236}
    237237
     238void PrintNnet (Nnet *nnet) {
     239
     240  for (int L = 1; L < nnet[0].Nlayer; L++) {
     241    gprint (GP_ERR, " ----- Layer %d -----\n", L);
     242    for (int j = 0; j < nnet[0].Nnodes[L]; j++) {
     243      for (int i = 0; i < nnet[0].Nnodes[L-1]; i++) {
     244        int k = j * nnet[0].Nnodes[L-1] + i;
     245        myAssert (k < nnet[0].Nnodes[L-1]*nnet[0].Nnodes[L], "overflow");
     246        gprint (GP_ERR, "%7.4f ", nnet[0].weight[L][k]);
     247      }
     248      gprint (GP_ERR, " : %7.4f\n", nnet[0].biases[L][j]);
     249    }
     250  }
     251  return;
     252}
     253
Note: See TracChangeset for help on using the changeset viewer.