Blame projects/neural/train.image.inc.cpp

e865c9
#ifndef TRAIN_IMAGE_INC_CPP
e865c9
#define TRAIN_IMAGE_INC_CPP
e865c9
e865c9
e865c9
#include "train.inc.cpp"
e865c9
#include "layer.simple.inc.cpp"
e865c9
e865c9
e865c9
class TrainerImage: public Trainer {
e865c9
protected:
e865c9
  std::vector<unsigned char=""> data;</unsigned>
e865c9
  std::vector<unsigned int=""> shuffle;</unsigned>
e865c9
  const char *datafile;
e865c9
  const char *outfile;
e865c9
  Layout ofl, obl;
e865c9
  Layout::List oflist, oblist;
e865c9
  int stride, count;
e865c9
e865c9
public:
e865c9
  TrainerImage(): stride(), count() { }
e865c9
e865c9
  bool configure(const char *datafile, const char *outfile) {
e865c9
    this->datafile = datafile;
e865c9
    this->outfile = outfile;
e865c9
  }
e865c9
    
e865c9
    data.clear();
e865c9
e865c9
    FILE *f = fopen(filename, "rb");
e865c9
    if (!f)
e865c9
      return printf("cannot open file for read: %s\n", filename), false;
e865c9
    fseek(f, 0, SEEK_END);
e865c9
    size_t fs = ftello(f);
e865c9
    fseek(f, 0, SEEK_SET);
e865c9
e865c9
    data.resize(fs, 0);
e865c9
    if (!fread(data.data(), fs, 1, f))
e865c9
      return printf("cannot read from file: %s\n", filename), fclose(f), data.clear(), false;
e865c9
e865c9
    fclose(f);
e865c9
    return true;
e865c9
  }
e865c9
e865c9
  
e865c9
void imgTrain(Layer &l, const char *datafile, int size, const char *outfile, double trainRatio, int count) {
e865c9
  Layer &bl = l.back();
e865c9
e865c9
  assert(!l.prev);
e865c9
  assert(datafile);
e865c9
  assert(count > 0 && size > 0);
e865c9
  assert(l.size == size);
e865c9
  assert(bl.size == size);
e865c9
e865c9
  int blockSize = 1000;//1024*1024*1024/size;
e865c9
  assert(blockSize > 0);
e865c9
e865c9
  FILE *f = fopen(datafile, "rb");
e865c9
  if (!f)
e865c9
    { printf("cannot open file: %s\n", datafile); return; }
e865c9
  fseeko64(f, 0, SEEK_END);
e865c9
  long long fsize = ftello64(f);
e865c9
  int xCount = (int)(fsize/size);
e865c9
  if (xCount <= 0)
e865c9
    { printf("no tests in file: %s\n", datafile); return; }
e865c9
e865c9
  int *block = new int[blockSize*2];
e865c9
  int *shuffle = block + blockSize;
e865c9
  double *results = new double[blockSize];
e865c9
  unsigned char *blockData = new unsigned char[(blockSize + 1)*size];
e865c9
  unsigned char *blockResData = blockData + blockSize*size;
e865c9
  bool err = false;
e865c9
e865c9
  for(int j = 0; j < blockSize; ++j)
e865c9
    { shuffle[j] = j; results[j] = 0; }
e865c9
e865c9
  int blocksCount = (count - 1)/blockSize + 1;
e865c9
e865c9
  printf("training %d (%d x %d blocks), tests: %d, ratio: %f:\n", blocksCount*blockSize, blocksCount, blockSize, xCount, trainRatio);
e865c9
e865c9
  double avgSum = 0;
e865c9
  for(int i = 0; i < blocksCount; ++i) {
e865c9
    for(int j = 0; j < blockSize; ++j) {
e865c9
      block[j] = rand()%xCount;
e865c9
      std::swap(shuffle[i], shuffle[rand()%blockSize]);
e865c9
    }
e865c9
    std::sort(block, block + blockSize);
e865c9
e865c9
    for(int j = 0; j < blockSize; ++j) {
e865c9
      fseeko64(f, block[j]*(long long)size, SEEK_SET);
e865c9
      if (!fread(blockData + j*size, size, 1, f))
e865c9
        { printf("cannot read data from file: %s\n", datafile); err = true; break; }
e865c9
    }
e865c9
    if (err) break;
e865c9
e865c9
    printf("  next data block loaded\n");
e865c9
e865c9
    double sumQ = 0;
e865c9
    for(int j = 0; j < blockSize; ++j) {
e865c9
      unsigned char *data = blockData + shuffle[j]*size;
e865c9
      for(double *ia = l.a, *e = ia + l.size; ia < e; ++ia, ++data)
e865c9
        *ia = *data/255.0;
e865c9
e865c9
      double firstQ = 0, q = 0;
e865c9
      for(int repeat = 0; repeat < 1; ++repeat) {
e865c9
        l.pass();
e865c9
e865c9
        for(double *ia = l.a, *iba = bl.a, *ibda = bl.da, *e = ia + l.size; ia < e; ++ia, ++iba, ++ibda) {
e865c9
          double d = *ia - *iba;
e865c9
          *ibda = d;
e865c9
          q += d*d;
e865c9
        }
e865c9
        q /= size;
e865c9
        if (!repeat) firstQ = q;
e865c9
e865c9
        bl.backpass(trainRatio);
e865c9
      }
e865c9
e865c9
      sumQ += firstQ;
e865c9
      avgSum += firstQ - results[j];
e865c9
      results[j] = firstQ;
e865c9
      int avgCnt = i ? blockSize : j + 1;
e865c9
      printf("  %4d: total: %6d, avg result: %f, last result: %f -> %f\n", j+1, i*blockSize+j+1, avgSum/avgCnt, firstQ, q);
e865c9
    }
e865c9
e865c9
    printf("%4d: total: %6d, avg result: %f\n", i+1, (i+1)*blockSize, sumQ/blockSize);
e865c9
e865c9
    if (outfile && !l.save(outfile))
e865c9
      { printf("cannot save neural network weights to file: %s\n", outfile); err = true; break; }
e865c9
e865c9
    unsigned char *data = blockResData;
e865c9
    for(double *iba = bl.a, *e = iba + bl.size; iba < e; ++iba, ++data)
e865c9
      *data = (unsigned char)(*iba*255.999);
e865c9
    tgaSave("data/output/sampleX.tga", blockData + shuffle[blockSize-1]*size, 256, 256, 3);
e865c9
    tgaSave("data/output/sampleY.tga", blockResData, 256, 256, 3);
e865c9
  }
e865c9
e865c9
  delete[] block;
e865c9
  delete[] results;
e865c9
  delete[] blockData;
e865c9
e865c9
  printf("finished\n");
e865c9
}
e865c9
  
e865c9
e865c9
protected:
e865c9
  bool prepare() override {
e865c9
    ofl = optimizeLayoutSimple(fl->layout);
e865c9
    obl = optimizeLayoutSimple(bl->layout);
e865c9
    assert(ofl && obl);
e865c9
    assert(ofl.getActiveCount() == obl.getActiveCount());
e865c9
    
e865c9
    ofl.split(oflist, threadsCount);
e865c9
    obl.split(oblist, threadsCount);
e865c9
    stride = ofl.getActiveCount() + 1;
e865c9
    count = data.size()/stride;
e865c9
    if (count <= 0) return false;
e865c9
    shuffle.resize(count);
e865c9
    for(int i = 0; i < count; ++i)
e865c9
      shuffle[i] = i;
e865c9
    return true;
e865c9
  }
e865c9
e865c9
e865c9
  bool prepareBlock() override {
e865c9
    int cnt = itersPerBlock > count ? count : itersPerBlock;
e865c9
    for(int i = 0; i < cnt; ++i) {
e865c9
      int j = rand()%count;
e865c9
      if (i != j) std::swap(shuffle[i], shuffle[j]);
e865c9
    }
e865c9
    return true;
e865c9
  }
e865c9
e865c9
e865c9
  void loadData(Barrier &barrier, int, int iter) override {
e865c9
    struct I: public Iter {
e865c9
      typedef const unsigned char* Type;
e865c9
      static inline void iter4(Neuron &n, Type d, AccumType&) { n.v = *d/(NeuronReal)255; }
e865c9
    };
e865c9
    const unsigned char *id = data.data() + shuffle[iter%count]*stride;
e865c9
    iterateNeurons2(oflist[barrier.tid], ofl, fl->neurons, id);
e865c9
  }
e865c9
e865c9
e865c9
  AccumReal verifyDataMain(int, int iter) override {
e865c9
    struct I: public Iter {
e865c9
      typedef int Type;
e865c9
      struct AccumType { int ri, mi; NeuronReal m; };
e865c9
      static inline void iter4(Neuron &n, Type d, AccumType &a) {
e865c9
        NeuronReal v1 = d == a.ri;
e865c9
        NeuronReal v0 = n.v;
e865c9
        n.d *= v1 - v0;
e865c9
        if (a.m < v0) { a.m = v0; a.mi = d; }
e865c9
      }
e865c9
    };
e865c9
    
e865c9
    I::AccumType a = { data[ (shuffle[iter%count] + 1)*stride - 1 ], 0, 0 };
e865c9
    iterateNeurons2(obl, obl, bl->neurons, 0, 1, &a);
e865c9
    
e865c9
    return a.mi != a.ri;
e865c9
  }
e865c9
};
e865c9
e865c9
e865c9
#endif