Blame simple/neural/nntrain.inc.cpp

Ivan Mahonin 56d550
#ifndef NNTRAIN_INC_CPP
Ivan Mahonin 56d550
#define NNTRAIN_INC_CPP
Ivan Mahonin 56d550
Ivan Mahonin 56d550
Ivan Mahonin 56d550
#include "nnlayer.inc.cpp"
Ivan Mahonin 56d550
Ivan Mahonin 56d550
Ivan Mahonin 56d550
class Trainer {
Ivan Mahonin 56d550
public:
Ivan Mahonin 025224
  double trainRatio;
Ivan Mahonin 56d550
  int sizeX, sizeY, count;
Ivan Mahonin 56d550
  double *x, *y;
Ivan Mahonin 56d550
Ivan Mahonin 56d550
Ivan Mahonin 025224
  explicit Trainer(double trainRatio = 0.5): trainRatio(trainRatio), sizeX(), sizeY(), count(), x(), y() { }
Ivan Mahonin 56d550
Ivan Mahonin 025224
  Trainer(double trainRatio, int sizeX, int sizeY, int count):
Ivan Mahonin 025224
    Trainer(trainRatio)
Ivan Mahonin 56d550
    { init(sizeX, sizeY, count); }
Ivan Mahonin 56d550
Ivan Mahonin 56d550
  ~Trainer()
Ivan Mahonin 025224
    { deinit(); }
Ivan Mahonin 56d550
Ivan Mahonin 56d550
Ivan Mahonin 56d550
  void init(int sizeX, int sizeY, int count) {
Ivan Mahonin 025224
    deinit();
Ivan Mahonin 56d550
    assert(sizeX > 0);
Ivan Mahonin 56d550
    assert(sizeY > 0);
Ivan Mahonin 56d550
    assert(count > 0);
Ivan Mahonin 56d550
    this->sizeX = sizeX;
Ivan Mahonin 56d550
    this->sizeY = sizeY;
Ivan Mahonin 56d550
    this->count = count;
Ivan Mahonin 56d550
    x = new double[(sizeX + sizeY)*count];
Ivan Mahonin 56d550
    y = x + sizeX*count;
Ivan Mahonin 56d550
    memset(x, 0, sizeof(*x)*(sizeX + sizeY)*count);
Ivan Mahonin 56d550
  }
Ivan Mahonin 56d550
Ivan Mahonin 56d550
  void deinit() {
Ivan Mahonin 56d550
    if (!count) return;
Ivan Mahonin 56d550
    delete[] x;
Ivan Mahonin 56d550
    sizeX = sizeY = count = 0;
Ivan Mahonin 56d550
    x = y = nullptr;
Ivan Mahonin 56d550
  }
Ivan Mahonin 56d550
Ivan Mahonin 56d550
Ivan Mahonin 025224
  double trainSimple(Layer &l, int successCount, double qmin, int reportStep) {
Ivan Mahonin 025224
    assert(count);
Ivan Mahonin 025224
    assert(!l.prev);
Ivan Mahonin 025224
    assert(sizeX == l.size);
Ivan Mahonin 025224
    assert(sizeY == l.back().size);
Ivan Mahonin 025224
    assert(successCount > 0);
Ivan Mahonin 025224
    assert(qmin > 0);
Ivan Mahonin 025224
Ivan Mahonin 025224
    printf("training: %d, %lf\n", successCount, qmin);
Ivan Mahonin 025224
    double *res = new double[successCount];
Ivan Mahonin 025224
    double *rp = res, *re = res + successCount;
Ivan Mahonin 025224
    double rsum = 0;
Ivan Mahonin 025224
    int rcount = 0;
Ivan Mahonin 025224
    memset(res, 0, sizeof(*res)*successCount);
Ivan Mahonin 025224
Ivan Mahonin 025224
    int success = 0, total = 0, nextReport = reportStep;
Ivan Mahonin 025224
    double avg = 0;
Ivan Mahonin 025224
    for(int i = 0; i < 1000000000; ++i) {
Ivan Mahonin 025224
      int index = rand() % count;
Ivan Mahonin 025224
Ivan Mahonin 025224
      double target = avg*0.5;
Ivan Mahonin 025224
      double q = 0;
Ivan Mahonin 025224
      for(int i = 0; i < 10; ++i) {
Ivan Mahonin 025224
        double qq = l.trainPass(trainRatio, x + sizeX*index, y + sizeY*index, target);
Ivan Mahonin 025224
        if (q < qq) q = qq;
Ivan Mahonin 025224
        ++total;
Ivan Mahonin 025224
        if (qq <= target) break;
Ivan Mahonin 025224
        break;
Ivan Mahonin 025224
      }
Ivan Mahonin 025224
Ivan Mahonin 025224
Ivan Mahonin 025224
      rcount += (q > qmin) - (*rp > qmin);
Ivan Mahonin 025224
      rsum += q - *rp;
Ivan Mahonin 025224
      *rp++ = q;
Ivan Mahonin 025224
      if (rp == re) rp = res;
Ivan Mahonin 025224
Ivan Mahonin 025224
      int cnt = i+1 < successCount ? i+1 : successCount;
Ivan Mahonin 025224
      avg = rsum/cnt;
Ivan Mahonin 025224
Ivan Mahonin 025224
      if (q > qmin) success = 0; else ++success;
Ivan Mahonin 025224
Ivan Mahonin 025224
      if (total >= nextReport || success >= successCount) {
Ivan Mahonin 025224
        printf("  iterations: %d, error rate: %lf, avg res: %lf\n", total, rcount/(double)cnt, avg);
Ivan Mahonin 025224
        nextReport = total + reportStep;
Ivan Mahonin 025224
      }
Ivan Mahonin 025224
      if (success >= successCount) break;
Ivan Mahonin 025224
    }
Ivan Mahonin 025224
Ivan Mahonin 025224
    delete[] res;
Ivan Mahonin 025224
    printf("done\n");
Ivan Mahonin 025224
    return rsum/successCount;
Ivan Mahonin 025224
  }
Ivan Mahonin 025224
Ivan Mahonin 025224
Ivan Mahonin 025224
  double trainBlock(Layer &l, int successCount, int blockSize, double qmin, int reportStep = 0) {
Ivan Mahonin 56d550
    assert(count);
Ivan Mahonin 56d550
    assert(!l.prev);
Ivan Mahonin 56d550
    assert(sizeX == l.size);
Ivan Mahonin 56d550
    assert(sizeY == l.back().size);
Ivan Mahonin 56d550
    assert(blockSize > 0 && qmin > 0);
Ivan Mahonin 025224
    assert(reportStep >= 0);
Ivan Mahonin 56d550
Ivan Mahonin 56d550
    printf("training: %d, %lf\n", blockSize, qmin);
Ivan Mahonin 56d550
    double **blockXY = new double*[blockSize*2];
Ivan Mahonin 56d550
    double qmin2 = qmin*0.9;
Ivan Mahonin 56d550
    double qmin3 = qmin2*0.9;
Ivan Mahonin 56d550
Ivan Mahonin 56d550
    int success = 0;
Ivan Mahonin 025224
    int total = 0, nextReport = reportStep;
Ivan Mahonin 56d550
    int repeats, blockRepeats;
Ivan Mahonin 56d550
    double qmax0, qsum0, qmax, qsum;
Ivan Mahonin 025224
    for(int i = 0; i < 1000000; ++i) {
Ivan Mahonin 56d550
      for(int i = 0; i < blockSize; ++i) {
Ivan Mahonin 56d550
        int index = rand() % count;
Ivan Mahonin 56d550
        blockXY[i*2 + 0] = x + sizeX*index;
Ivan Mahonin 56d550
        blockXY[i*2 + 1] = y + sizeY*index;
Ivan Mahonin 56d550
      }
Ivan Mahonin 56d550
Ivan Mahonin 56d550
      repeats = blockRepeats = 0;
Ivan Mahonin 56d550
      qmax0 = qsum0 = 0;
Ivan Mahonin 56d550
      for(int i = 0; i < 1000; ++i) {
Ivan Mahonin 56d550
        double **xy = blockXY;
Ivan Mahonin 56d550
        qmax = 0, qsum = 0;
Ivan Mahonin 56d550
        for(int i = 0; i < blockSize; ++i, xy += 2) {
Ivan Mahonin 56d550
          double q0 = 0;
Ivan Mahonin 56d550
          for(int i = 0; i < 100; ++i) {
Ivan Mahonin 025224
            double q = l.trainPass(trainRatio, xy[0], xy[1], qmin3);
Ivan Mahonin 56d550
            if (!i) q0 = q;
Ivan Mahonin 56d550
            ++repeats;
Ivan Mahonin 56d550
            if (q < qmin3) break;
Ivan Mahonin 56d550
          }
Ivan Mahonin 56d550
          qsum += q0;
Ivan Mahonin 56d550
          if (qmax < q0) qmax = q0;
Ivan Mahonin 56d550
        }
Ivan Mahonin 56d550
        if (!i) { qmax0 = qmax; qsum0 = qsum; }
Ivan Mahonin 56d550
        ++blockRepeats;
Ivan Mahonin 56d550
        if (qmax <= qmin2) break;
Ivan Mahonin 56d550
      }
Ivan Mahonin 56d550
      total += repeats;
Ivan Mahonin 56d550
Ivan Mahonin 56d550
Ivan Mahonin 025224
      if (qmax0 > qmin) success = 0; else ++success;
Ivan Mahonin 025224
Ivan Mahonin 025224
      if (total >= nextReport || success >= successCount) {
Ivan Mahonin 025224
        nextReport = total + reportStep;
Ivan Mahonin 025224
        printf("  blocks %d (samples: %d, total: %d, repeats: %3d (%lf)): %lf -> %lf, %lf -> %lf\n",
Ivan Mahonin 025224
          i+1, (i+1)*blockSize, total, blockRepeats-1, repeats/(double)(blockRepeats*blockSize) - 1, qmax0, qmax, qsum0/blockSize, qsum/blockSize);
Ivan Mahonin 025224
      }
Ivan Mahonin 025224
      if (success >= successCount) break;
Ivan Mahonin 56d550
    }
Ivan Mahonin 56d550
Ivan Mahonin 025224
    delete[] blockXY;
Ivan Mahonin 56d550
    printf("done\n");
Ivan Mahonin 56d550
    return qmax0;
Ivan Mahonin 56d550
  }
Ivan Mahonin 56d550
Ivan Mahonin 56d550
Ivan Mahonin 56d550
  bool loadSymbolMap(const char *filename, int sizeX, int sizeY) {
Ivan Mahonin 56d550
    deinit();
Ivan Mahonin 56d550
Ivan Mahonin 56d550
    FILE *f = fopen(filename, "rb");
Ivan Mahonin 56d550
    if (!f)
Ivan Mahonin 56d550
      return printf("cannot open file '%s' for read\n", filename), false;
Ivan Mahonin 56d550
    fseek(f, 0, SEEK_END);
Ivan Mahonin 56d550
    size_t fs = ftell(f);
Ivan Mahonin 56d550
    fseek(f, 0, SEEK_SET);
Ivan Mahonin 56d550
Ivan Mahonin 56d550
    size_t testSize = sizeX + 1;
Ivan Mahonin 56d550
    int count = fs/testSize;
Ivan Mahonin 56d550
    if (!count)
Ivan Mahonin 56d550
      return printf("file '%s' is lesser minimal size\n", filename), fclose(f), false;
Ivan Mahonin 56d550
Ivan Mahonin 56d550
    unsigned char *data = new unsigned char[testSize*count];
Ivan Mahonin 56d550
    memset(data, 0, testSize*count);
Ivan Mahonin 56d550
    if (!fread(data, testSize*count, 1, f))
Ivan Mahonin 025224
      return printf("cannot read from file '%s'\n", filename), delete[] data, fclose(f), false;
Ivan Mahonin 56d550
Ivan Mahonin 56d550
    fclose(f);
Ivan Mahonin 56d550
Ivan Mahonin 56d550
    init(sizeX, sizeY, count);
Ivan Mahonin 56d550
    const unsigned char *pd = data;
Ivan Mahonin 56d550
    const double delta = 0;
Ivan Mahonin 56d550
    double *ey = y + sizeY*count;
Ivan Mahonin 025224
    for(double *py = y; py < ey; ++py)
Ivan Mahonin 025224
      *py = delta;
Ivan Mahonin 56d550
    for(double *px = x, *py = y; py < ey; py += sizeY) {
Ivan Mahonin 56d550
      for(double *ex = px + sizeX; px < ex; ++px, ++pd)
Ivan Mahonin 56d550
        *px = *pd/255.0;
Ivan Mahonin 56d550
      assert(*pd < sizeY);
Ivan Mahonin 56d550
      py[*pd++] = 1 - delta;
Ivan Mahonin 56d550
    }
Ivan Mahonin 56d550
    delete[] data;
Ivan Mahonin 56d550
Ivan Mahonin 56d550
    return true;
Ivan Mahonin 56d550
  }
Ivan Mahonin 56d550
Ivan Mahonin 56d550
Ivan Mahonin 56d550
  void printSymbol(int index, int width) {
Ivan Mahonin 56d550
    assert(index >= 0 && index < count);
Ivan Mahonin 56d550
    assert(width > 0);
Ivan Mahonin 56d550
    for(int i = 0; i < sizeX; ++i) {
Ivan Mahonin 56d550
      if (i && !(i % width)) printf("\n");
Ivan Mahonin 56d550
      printf("%c", x[sizeX*index + i] > 0 ? '#' : '.');
Ivan Mahonin 56d550
    }
Ivan Mahonin 56d550
    printf("\n");
Ivan Mahonin 56d550
    for(int i = 0; i < sizeY; ++i)
Ivan Mahonin 56d550
      printf(" %4.1lf", y[sizeY*index + i]);
Ivan Mahonin 56d550
    printf("\n");
Ivan Mahonin 56d550
  }
Ivan Mahonin 56d550
};
Ivan Mahonin 56d550
Ivan Mahonin 56d550
Ivan Mahonin 56d550
#endif