Changeset 40371 for trunk/Ohana/src/opihi/cmd.data/nnet_train.c
- Timestamp:
- Mar 16, 2018, 4:06:05 PM (8 years ago)
- File:
-
- 1 edited
-
trunk/Ohana/src/opihi/cmd.data/nnet_train.c (modified) (22 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Ohana/src/opihi/cmd.data/nnet_train.c
r40336 r40371 10 10 void nnet_backprop (Nnet *nnet, Vector **inVec, Vector **outVec, int N); 11 11 void nnet_descent_step (Nnet *nnet, Vector **inVec, Vector **outVec, int *seq, int pass, int Nmini, float eta, float lambda); 12 void nnet_print_Nabla (Nnet *nnet); 13 void nnet_write_Nabla (char *filename, Nnet *nnet); 12 14 13 15 static int QUADRATIC_COST = 0; … … 76 78 gprint (GP_ERR, "USAGE: nnet train (nnet) [input] [input] ... [output] [output] ...\n"); 77 79 gprint (GP_ERR, "OPTIONS: -Nepoch [N] -Nmini [N]\n"); 78 FREE (resid);80 // FREE (resid); 79 81 return FALSE; 80 82 } … … 83 85 if (nnet == NULL) { 84 86 gprint (GP_ERR, "nnet %s not found, create it first\n", argv[1]); 85 FREE (resid);87 // FREE (resid); 86 88 return FALSE; 87 89 } … … 95 97 if (argc != Ninput + Noutput + 2) { 96 98 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); 98 100 return FALSE; 99 101 } … … 111 113 free (inVec); 112 114 free (outVec); 113 FREE (resid);115 // FREE (resid); 114 116 return FALSE; 115 117 } … … 118 120 free (inVec); 119 121 free (outVec); 120 FREE (resid);122 // FREE (resid); 121 123 return FALSE; 122 124 } … … 126 128 free (inVec); 127 129 free (outVec); 128 FREE (resid);130 // FREE (resid); 129 131 return FALSE; 130 132 } … … 136 138 free (inVec); 137 139 free (outVec); 138 FREE (resid);140 // FREE (resid); 139 141 return FALSE; 140 142 } … … 143 145 free (inVec); 144 146 free (outVec); 145 FREE (resid);147 // FREE (resid); 146 148 return FALSE; 147 149 } … … 181 183 } 182 184 185 // PrintNnet (nnet); 186 183 187 // train for Nepochs 184 188 // this recreates 'SGD' from http://neuralnetworksanddeeplearning.com/chap1.html … … 194 198 // update the weights and biases using the mini batch subset 195 199 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); 197 203 198 204 if (resid) { … … 218 224 float mean = s1 / Npts; 219 225 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); 221 228 resid[0].elements.Flt[epoch] = sigma; 222 229 } 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); 224 232 } 225 233 } 234 // PrintNnet (nnet); 226 235 227 236 if (result) { … … 265 274 266 275 // 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; 268 278 269 279 // backprop generates a dNabla_b, dNabla_w pair for the element N of the input and output vectors 270 280 nnet_backprop (nnet, inVec, outVec, N); 271 272 281 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); 275 292 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); 276 297 } 277 298 … … 317 338 } 318 339 } 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 319 350 // delta = DOT(delta, transpose(weight[L+1])) * sprime; 320 351 for (int j = 0; j < nnet[0].Nnodes[L]; j++) { … … 322 353 for (int i = 0; i < nnet[0].Nnodes[L+1]; i++) { 323 354 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]); 325 358 } 326 359 nnet[0].delta[L][j] = tmpdelta * nnet[0].sprime[L][j]; … … 335 368 // Nabla_b[L] = delta; 336 369 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]; 338 371 } 339 372 … … 342 375 for (int i = 0; i < nnet[0].Nnodes[L-1]; i++) { 343 376 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]; 345 379 } 346 380 } … … 349 383 350 384 // support functions to loop over the Nabla entries 385 void 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 } 402 void 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 } 351 416 void nnet_apply_Nabla (Nnet *nnet, int Nmini, float eta, float lambda, int Ntrial) { 352 417 for (int L = 1; L < nnet[0].Nlayer; L++) { … … 357 422 for (int i = 0; i < nnet[0].Nnodes[L-1]; i++) { 358 423 int k = i + j*nnet[0].Nnodes[L-1]; 424 myAssert (k < nnet[0].Nnodes[L-1]*nnet[0].Nnodes[L], "overflow"); 359 425 // nnet[0].weight[L][k] -= (eta / Nmini) * nnet[0].Nabla_w[L][k]; 360 426 // with lambda > 0.0, we have L2 regularization. if lambda = 0.0, we recover the default implementation … … 364 430 } 365 431 } 366 void nnet_update_Nabla (Nnet *nnet) { 432 433 void nnet_print_Nabla (Nnet *nnet) { 434 367 435 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++) { 372 438 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 449 void 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 380 460 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++) { 387 463 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; 394 474 } 395 475 … … 410 490 411 491 // 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]; 413 493 int Noutput = nnet[0].Nnodes[L]; 414 494 … … 419 499 // weight matrix order is (0, 1, ... Ninput-1, Ninput, Ninput + 1, ... Ninput * Noutput - 1) 420 500 int k = j * Ninput + i; 501 myAssert (k < Ninput*Noutput, "overflow"); 421 502 sum += nnet[0].weight[L][k]*nnet[0].svalue[L-1][i]; 422 503 }
Note:
See TracChangeset
for help on using the changeset viewer.
