|
|
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
|