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

Ivan Mahonin e865c9
#ifndef TRAIN_IMAGE_INC_CPP
Ivan Mahonin e865c9
#define TRAIN_IMAGE_INC_CPP
Ivan Mahonin e865c9
Ivan Mahonin e865c9
Ivan Mahonin b579b3
#include <set>
Ivan Mahonin b579b3
Ivan Mahonin e865c9
#include "train.inc.cpp"
Ivan Mahonin e865c9
#include "layer.simple.inc.cpp"
Ivan Mahonin e865c9
Ivan Mahonin e865c9
Ivan Mahonin e865c9
class TrainerImage: public Trainer {
Ivan Mahonin e865c9
protected:
Ivan Mahonin e865c9
  std::vector<unsigned char> data;
Ivan Mahonin b579b3
  std::vector<unsigned char> tmpdata;
Ivan Mahonin b579b3
  std::vector<int> shuffle;
Ivan Mahonin b579b3
  std::vector<int> shuffle2;
Ivan Mahonin b579b3
  Layout pbl;
Ivan Mahonin b579b3
  Layout::List flist, blist;
Ivan Mahonin b579b3
  FILE *f;
Ivan Mahonin b579b3
  size_t imgsize;
Ivan Mahonin b579b3
  int count;
Ivan Mahonin b579b3
  int workCount;
Ivan Mahonin e865c9
Ivan Mahonin e865c9
public:
Ivan Mahonin b579b3
  int pad;
Ivan Mahonin b579b3
  const char *datafile;
Ivan Mahonin b579b3
  const char *outfile;
Ivan Mahonin b579b3
  Layer *dataLayer;
Ivan Mahonin b579b3
  
Ivan Mahonin b579b3
  TrainerImage(): f(), imgsize(), count(), workCount(), pad(), datafile(), outfile(), dataLayer() { }
Ivan Mahonin e865c9
Ivan Mahonin b579b3
protected:
Ivan Mahonin b579b3
  bool prepare() override {
Ivan Mahonin b579b3
    assert(datafile);   
Ivan Mahonin b579b3
    assert(fl->layout.getD() == 3);
Ivan Mahonin b579b3
    
Ivan Mahonin e4740d
    #ifndef NDEBUG
Ivan Mahonin b579b3
    Layer *dl = dataLayer ? dataLayer : fl;
Ivan Mahonin b579b3
    assert(dl->layout.getW() == bl->layout.getW());
Ivan Mahonin b579b3
    assert(dl->layout.getH() == bl->layout.getH());
Ivan Mahonin b579b3
    assert(dl->layout.getD() == bl->layout.getD());
Ivan Mahonin e4740d
    #endif
Ivan Mahonin b579b3
    
Ivan Mahonin b579b3
    imgsize = fl->layout.getActiveCount();
Ivan Mahonin b579b3
    fl->layout.split(flist, threadsCount);
Ivan Mahonin b579b3
    bl->layout.split(blist, threadsCount);
Ivan Mahonin b579b3
    pbl = bl->layout;
Ivan Mahonin b579b3
    pbl.padXY(pad);
Ivan Mahonin b579b3
    
Ivan Mahonin b579b3
    f = fopen(datafile, "rb");
Ivan Mahonin b579b3
    if (!f) return false;
Ivan Mahonin e865c9
    
Ivan Mahonin b579b3
    fseeko64(f, 0, SEEK_END);
Ivan Mahonin b579b3
    long long size = ftello64(f);
Ivan Mahonin b579b3
    count = size/imgsize;
Ivan Mahonin b579b3
    if (count < 1) return fclose(f), f = nullptr, false;
Ivan Mahonin e865c9
Ivan Mahonin b579b3
    workCount = itersPerBlock > count ? count : itersPerBlock;
Ivan Mahonin b579b3
    printf("allocated size: %lld\n", (long long)(imgsize*workCount));
Ivan Mahonin b579b3
    data.resize(workCount*imgsize);
Ivan Mahonin e865c9
Ivan Mahonin b579b3
    shuffle.resize(count);
Ivan Mahonin b579b3
    for(int i = 0; i < count; ++i)
Ivan Mahonin b579b3
      shuffle[i] = i;
Ivan Mahonin e865c9
Ivan Mahonin b579b3
    shuffle2.resize(workCount);
Ivan Mahonin b579b3
    for(int i = 0; i < workCount; ++i)
Ivan Mahonin b579b3
      shuffle2[i] = i;
Ivan Mahonin b579b3
    
Ivan Mahonin b579b3
    return loadBlocks();
Ivan Mahonin b579b3
    //return true;
Ivan Mahonin e865c9
  }
Ivan Mahonin e865c9
  
Ivan Mahonin b579b3
  
Ivan Mahonin b579b3
  void finish() override
Ivan Mahonin b579b3
    { if (f) fclose(f), f = nullptr; }
Ivan Mahonin e865c9
Ivan Mahonin b579b3
    
Ivan Mahonin b579b3
  bool loadBlocks() {
Ivan Mahonin b579b3
    for(int i = 0; i < workCount; ++i) {
Ivan Mahonin b579b3
      int j = rand()%count;
Ivan Mahonin b579b3
      if (i != j) std::swap(shuffle[i], shuffle[j]);
Ivan Mahonin e865c9
    }
Ivan Mahonin b579b3
    
Ivan Mahonin b579b3
    typedef std::pair<int, int> Pair;
Ivan Mahonin b579b3
    typedef std::set<Pair> Set;
Ivan Mahonin b579b3
    Set set;
Ivan Mahonin b579b3
    for(int i = 0; i < workCount; ++i)
Ivan Mahonin b579b3
      set.insert(Pair(shuffle[i], i));
Ivan Mahonin b579b3
    
Ivan Mahonin b579b3
    for(Set::iterator i = set.begin(); i != set.end(); ++i) {
Ivan Mahonin b579b3
      fseeko64(f, i->first*imgsize, SEEK_SET);
Ivan Mahonin b579b3
      if (!fread(data.data() + i->second*imgsize, imgsize, 1, f))
Ivan Mahonin b579b3
        return fclose(f), f = nullptr, false;
Ivan Mahonin e865c9
    }
Ivan Mahonin e865c9
    
Ivan Mahonin e865c9
    return true;
Ivan Mahonin e865c9
  }
Ivan Mahonin e865c9
Ivan Mahonin e865c9
  bool prepareBlock() override {
Ivan Mahonin b579b3
    for(int i = 0; i < workCount; ++i) {
Ivan Mahonin b579b3
      int j = rand()%workCount;
Ivan Mahonin b579b3
      if (i != j) std::swap(shuffle2[i], shuffle2[j]);
Ivan Mahonin e865c9
    }
Ivan Mahonin b579b3
    //return loadBlocks();
Ivan Mahonin e865c9
    return true;
Ivan Mahonin e865c9
  }
Ivan Mahonin b579b3
  
Ivan Mahonin b579b3
  
Ivan Mahonin b579b3
  void finishBlock() override {
Ivan Mahonin b579b3
    if (outfile && !dataLayer) {
Ivan Mahonin b579b3
      std::string outfile0(outfile);
Ivan Mahonin b579b3
      std::string outfile1 = outfile0 + ".1.tga";
Ivan Mahonin b579b3
      outfile0 += ".0.tga";
Ivan Mahonin b579b3
      
Ivan Mahonin b579b3
      unsigned char *id0 = data.data() + shuffle2[(itersPerBlock-1)%workCount]*imgsize;
Ivan Mahonin b579b3
      tgaSave(outfile0.c_str(), id0, fl->layout.getW(), fl->layout.getH(), fl->layout.getD());
Ivan Mahonin b579b3
Ivan Mahonin b579b3
      struct I: public Iter {
Ivan Mahonin b579b3
        typedef unsigned char* DataType;
Ivan Mahonin b579b3
        static inline void iter4(Neuron &n, DataType d, DataAccumType&) { *d = n.v < 0 ? 0 : n.v > 1 ? 255 : (unsigned char)(n.v*255.999); }
Ivan Mahonin b579b3
      };
Ivan Mahonin b579b3
      
Ivan Mahonin b579b3
      tmpdata.resize(imgsize);
Ivan Mahonin b579b3
      unsigned char *id1 = tmpdata.data();
Ivan Mahonin b579b3
      iterateNeurons2(bl->layout, bl->layout, bl->neurons, id1);
Ivan Mahonin b579b3
      tgaSave(outfile1.c_str(), id1, bl->layout.getW(), bl->layout.getH(), bl->layout.getD());
Ivan Mahonin b579b3
    }
Ivan Mahonin b579b3
  }
Ivan Mahonin e865c9
Ivan Mahonin e865c9
Ivan Mahonin e865c9
  void loadData(Barrier &barrier, int, int iter) override {
Ivan Mahonin e865c9
    struct I: public Iter {
Ivan Mahonin b579b3
      typedef const unsigned char* DataType;
Ivan Mahonin b579b3
      static inline void iter4(Neuron &n, DataType d, DataAccumType&) { n.v = *d/(NeuronReal)255; }
Ivan Mahonin e865c9
    };
Ivan Mahonin b579b3
    const unsigned char *id = data.data() + shuffle2[iter%workCount]*imgsize;
Ivan Mahonin b579b3
    iterateNeurons2(flist[barrier.tid], fl->layout, fl->neurons, id);
Ivan Mahonin e865c9
  }
Ivan Mahonin e865c9
Ivan Mahonin e865c9
Ivan Mahonin b579b3
  Quality verifyData(Barrier &barrier, int, int iter) override {
Ivan Mahonin b579b3
    Layout l = blist[barrier.tid];
Ivan Mahonin b579b3
    Layout dl = bl->layout;
Ivan Mahonin b579b3
    Layout pl = pbl;
Ivan Mahonin b579b3
    
Ivan Mahonin b579b3
    int d = l.getD();
Ivan Mahonin b579b3
    int w = l.getW();
Ivan Mahonin b579b3
    int dx = l.sz - d;
Ivan Mahonin b579b3
    int dy = (l.sx - w)*l.sz;
Ivan Mahonin b579b3
    int ddx = dl.getD();
Ivan Mahonin b579b3
    int ddy = (dl.getW() - w)*ddx;
Ivan Mahonin b579b3
      
Ivan Mahonin b579b3
    AccumReal aq = 0;
Ivan Mahonin b579b3
    NeuronReal ratio = this->ratio;
Ivan Mahonin b579b3
    Neuron *in = bl->neurons + (l.y0*l.sx + l.x0)*l.sz + l.z0;
Ivan Mahonin b579b3
    const unsigned char *id = data.data() + shuffle2[iter%workCount]*imgsize + ((l.y0-dl.y0)*l.sx + l.x0-dl.x0)*l.sz + l.z0-dl.z0;
Ivan Mahonin e865c9
    
Ivan Mahonin b579b3
    for(int y = l.y0; y < l.y1; ++y, in += dy, id += ddy) {
Ivan Mahonin b579b3
      bool outside = y < pl.y0 || y >= pl.y1;
Ivan Mahonin b579b3
      for(int x = l.x0; x < l.x1; ++x, in += dx, id += ddx) {
Ivan Mahonin b579b3
        if (outside || x < pl.x0 || x >= pl.x1) {
Ivan Mahonin b579b3
          for(Neuron *e = in + d; in < e; ++in) in->d = 0;
Ivan Mahonin b579b3
        } else {
Ivan Mahonin b579b3
          const unsigned char *iid = id;
Ivan Mahonin b579b3
          for(Neuron *e = in + d; in < e; ++in, ++iid) {
Ivan Mahonin b579b3
            NeuronReal v1 = *iid/(NeuronReal)255;
Ivan Mahonin b579b3
            NeuronReal v0 = in->v;
Ivan Mahonin b579b3
            NeuronReal diff = v1 - v0;
Ivan Mahonin b579b3
            in->d *= diff*ratio;
Ivan Mahonin b579b3
            aq += diff*diff;
Ivan Mahonin b579b3
          }
Ivan Mahonin b579b3
        }
Ivan Mahonin b579b3
      }
Ivan Mahonin b579b3
    }
Ivan Mahonin e865c9
    
Ivan Mahonin b579b3
    return Quality( sqrt(aq/pbl.getActiveCount()) );
Ivan Mahonin e865c9
  }
Ivan Mahonin e865c9
};
Ivan Mahonin e865c9
Ivan Mahonin e865c9
Ivan Mahonin e865c9
#endif