Blame simple/neural/nnlayer.conv.inc.cpp

025224
#ifndef NNLAYER_CONV_INC_CPP
025224
#define NNLAYER_CONV_INC_CPP
025224
025224
025224
#include "nnlayer.inc.cpp"
025224
025224
025224
template<bool int="" padding="0" ralu,="" size,="" step="1,"></bool>
025224
class LayerConvolution: public Layer {
025224
public:
025224
  enum { W = Size, WW = W*W, D = Step, P = Padding, P2 = P*2 };
025224
025224
  int sx, sy, sz;
025224
  int psx, psy, psz;
025224
025224
  LayerConvolution(Layer &prev, int sx, int sy, int sz):
025224
    Layer(&prev, sx*sy*sz),
025224
    sx(sx), sy(sy), sz(sz),
025224
    psx((sx-P2-1)*D + W), psy((sy-P2-1)*D + W), psz(this->prev->size/(psx*psy))
025224
  {
025224
    assert(sx > 0 && sy > 0 && sz > 0);
025224
    assert(psx > 0 && psy > 0 && psz > 0);
025224
    assert(psx*psy*psz == this->prev->size);
025224
    links = wsize = WW*psz*sz*(sy-P2)*(sx-P2);
025224
    w = new double[wsize];
025224
    double k = RaLU ? 1.0/(WW*psz*sz) : 1;
025224
    for(double *iw = w, *e = iw + wsize; iw < e; ++iw)
025224
      *iw = (rand()/(double)RAND_MAX*2 - 1)*k;
53488e
    memsize += wsize*sizeof(double);
025224
  }
025224
025224
  Layer& pass() override {
025224
    const int asy = sx*(sy-P2);
025224
    const int asx = sx-P2;
025224
    const int adz = sx*P2;
025224
    const int wdz = WW*psz;
025224
    const int pady = D*(psx-asx);
025224
    const int paddz = psx*(psy - W);
025224
    const int paddy = psx - W;
025224
    double *pa = prev->a;
025224
025224
    double *ia = a + P*sx + P;
025224
    double *iw = w;
025224
    double *ipa = pa;
025224
    for(double *e = ia + asy*sz; ia < e; ia += adz, ipa = pa) {
025224
      for(double *e = ia + asy; ia < e; ia += P2, ipa += pady) {
025224
        for(double *e = ia + asx; ia < e; ++ia, ipa += D) {
025224
          double s = 0;
025224
          double *iipa = ipa;
025224
          for(double *ew = iw + wdz; iw < ew; iipa += paddz)
025224
            for(int yy = 0; yy < W; ++yy, iipa += paddy)
025224
              for(int xx = 0; xx < W; ++xx, ++iw, ++iipa)
025224
                s += *iipa * *iw;
025224
          *ia = RaLU ? (s < -1 ? -1 : s > 1 ? 1 : s) : 1/(1 + exp(-s)); // RaLU : sigmoid
025224
        }
025224
      }
025224
    }
025224
    return next ? next->pass() : *this;
025224
  }
025224
025224
  template<bool deep=""></bool>
025224
  Layer& backpassT(double trainRatio) {
025224
    const int asy = sx*(sy-P2);
025224
    const int asx = sx-P2;
025224
    const int adz = sx*P2;
025224
    const int wdz = WW*psz;
025224
    const int pady = D*(psx-asx);
025224
    const int paddz = psx*(psy - W);
025224
    const int paddy = psx - W;
025224
    double *pa = prev->a;
025224
    double *pda = prev->da;
025224
025224
    double *ia = a + P*sx + P;
025224
    double *iw = w;
025224
    double *ida = da + P*sx + P;
025224
    double *ipa = pa;
025224
    double *ipda = pda;
025224
    if (Deep) memset(pda, 0, sizeof(*pda)*prev->size);
025224
    for(double *e = ia + asy*sz; ia < e; ia += adz, ida += adz, ipa = pa, ipda = pda) {
025224
      for(double *e = ia + asy; ia < e; ia += P2, ida += P2, ipa += pady, ipda += pady) {
025224
        for(double *e = ia + asx; ia < e; ++ia, ++ida, ipa += D, ipda += D) {
025224
          double ds;
025224
          if (RaLU) {
025224
            double a = *ia;
025224
            if (a == -1 || a == 1) { iw += wdz; continue; }
025224
            ds = *ida; // RaLU derivation * *ida
025224
          } else {
025224
            double a = *ia;
025224
            ds = a * (1-a) * *ida; // sigmoid derivation * *ida
025224
          }
025224
          double dst = ds*trainRatio;
025224
025224
          double *iipa = ipa;
025224
          double *iipda = ipda;
025224
          for(double *ew = iw + wdz; iw < ew; iipa += paddz, iipda += paddz)
025224
            for(int yy = 0; yy < W; ++yy, iipa += paddy, iipda += paddy)
025224
              for(int xx = 0; xx < W; ++xx, ++iw, ++iipa, ++iipda) {
025224
                if (Deep) *iipda += ds * *iw;
025224
                *iw += dst * *iipa;
025224
              }
025224
        }
025224
      }
025224
    }
025224
025224
    return prev->backpass(trainRatio);
025224
  }
025224
025224
  Layer& backpass(double trainRatio) override
025224
    { return prev->prev ? backpassT<true>(trainRatio) : backpassT<false>(trainRatio); }</false></true>
025224
};
025224
025224
025224
025224
template<int int="" padding="0" size,="" step="1,"></int>
025224
class LayerConvolutionShared: public Layer {
025224
public:
025224
  enum { W = Size, WW = W*W, D = Step, P = Padding, P2 = P*2 };
025224
025224
  double *dw;
025224
  int sx, sy, sz;
025224
  int psx, psy, psz;
025224
025224
  LayerConvolutionShared(Layer &prev, int sx, int sy, int sz):
025224
    Layer(&prev, sx*sy*sz),
025224
    sx(sx), sy(sy), sz(sz),
025224
    psx((sx-P2-1)*D + W), psy((sy-P2-1)*D + W), psz(this->prev->size/(psx*psy))
025224
  {
025224
    assert(sx > 0 && sy > 0 && sz > 0);
025224
    assert(psx > 0 && psy > 0 && psz > 0);
025224
    assert(psx*psy*psz == this->prev->size);
025224
    wsize = WW*psz*sz;
025224
    links = wsize*(sy-P2)*(sx-P2);
025224
    w = new double[wsize + WW*psz];
025224
    dw = w + wsize;
025224
    for(double *iw = w, *e = iw + wsize; iw < e; ++iw)
025224
      *iw = (rand()/(double)RAND_MAX*2 - 1)*1;
53488e
    memsize += (wsize + WW*psz)*sizeof(double);
025224
  }
025224
025224
  Layer& pass() override {
025224
    const int asy = sx*(sy-P2);
025224
    const int asx = sx-P2;
025224
    const int adz = sx*P2;
025224
    const int wdz = WW*psz;
025224
    const int pady = D*(psx-asx);
025224
    const int paddz = psx*(psy - W);
025224
    const int paddy = psx - W;
025224
    double *pa = prev->a;
025224
025224
    double *ia = a + P*sx + P;
025224
    double *iw = w;
025224
    double *ipa = pa;
025224
    for(double *e = ia + asy*sz; ia < e; ia += adz, iw += wdz, ipa = pa) {
025224
      double *eew = iw + wdz;
025224
      for(double *e = ia + asy; ia < e; ia += P2, ipa += pady) {
025224
        for(double *e = ia + asx; ia < e; ++ia, ipa += D) {
025224
          double s = 0;
025224
          double *iipa = ipa;
025224
          for(double *iiw = iw; iiw < eew; iipa += paddz)
025224
            for(int yy = 0; yy < W; ++yy, iipa += paddy)
025224
              for(int xx = 0; xx < W; ++xx, ++iiw, ++iipa)
025224
                s += *iipa * *iiw;
025224
          *ia = 1/(1 + exp(-s)); // sigmoid
025224
        }
025224
      }
025224
    }
025224
    return next ? next->pass() : *this;
025224
  }
025224
025224
  template<bool deep=""></bool>
025224
  Layer& backpassT(double trainRatio) {
025224
    const int asy = sx*(sy-P2);
025224
    const int asx = sx-P2;
025224
    const int adz = sx*P2;
025224
    const int wdz = WW*psz;
025224
    const int pady = D*(psx-asx);
025224
    const int paddz = psx*(psy - W);
025224
    const int paddy = psx - W;
025224
    double *dw = this->dw;
025224
    double *edw = dw + wdz;
025224
    double *pa = prev->a;
025224
    double *pda = prev->da;
025224
025224
    double *ia = a + P*sx + P;
025224
    double *iw = w;
025224
    double *ida = da + P*sx + P;
025224
    double *ipa = pa;
025224
    double *ipda = pda;
025224
    if (Deep) memset(pda, 0, sizeof(*pda)*prev->size);
025224
    for(double *e = ia + asy*sz; ia < e; ia += adz, ida += adz, ipa = pa, ipda = pda) {
025224
      memset(dw, 0, sizeof(*dw) * wdz);
025224
025224
      for(double *e = ia + asy; ia < e; ia += P2, ida += P2, ipa += pady, ipda += pady) {
025224
        for(double *e = ia + asx; ia < e; ++ia, ++ida, ipa += D, ipda += D) {
025224
          const double a = *ia;
025224
          const double ds = a * (1-a) * *ida; // sigmoid derivation * *ida
025224
          const double dst = ds*trainRatio;
025224
025224
          double *iiw = iw;
025224
          double *iipa = ipa;
025224
          double *iipda = ipda;
025224
          for(double *idw = dw; idw < edw; iipa += paddz, iipda += paddz)
025224
            for(int yy = 0; yy < W; ++yy, iipa += paddy, iipda += paddy)
025224
              for(int xx = 0; xx < W; ++xx, ++iiw, ++idw, ++iipa, ++iipda) {
025224
                if (Deep) *iipda += ds * *iiw;
025224
                *idw += dst * *iipa;
025224
              }
025224
        }
025224
      }
025224
025224
      for(double *idw = dw; idw < edw; ++iw, ++idw)
025224
        *iw += *idw;
025224
    }
025224
025224
    return prev->backpass(trainRatio);
025224
  }
025224
025224
  Layer& backpass(double trainRatio) override
025224
    { return prev->prev ? backpassT<true>(trainRatio) : backpassT<false>(trainRatio); }</false></true>
025224
};
025224
025224
025224
#endif