|
|
025224 |
#ifndef NNLAYER_LNK_INC_CPP
|
|
|
025224 |
#define NNLAYER_LNK_INC_CPP
|
|
|
025224 |
|
|
|
025224 |
|
|
|
025224 |
#include <algorithm></algorithm>
|
|
|
025224 |
|
|
|
025224 |
#include "nnlayer.inc.cpp"
|
|
|
025224 |
|
|
|
025224 |
|
|
|
025224 |
class LayerLink: public Layer {
|
|
|
025224 |
public:
|
|
|
025224 |
int lsize;
|
|
|
025224 |
double **wa, **wda;
|
|
|
025224 |
|
|
|
025224 |
LayerLink(Layer &prev, int size, int lsize):
|
|
|
025224 |
Layer(&prev, size), lsize(lsize)
|
|
|
025224 |
{
|
|
|
025224 |
assert(lsize > 0);
|
|
|
025224 |
links = wsize = size*lsize;
|
|
|
025224 |
w = new double[wsize];
|
|
|
025224 |
wa = new double*[wsize*2];
|
|
|
025224 |
wda = wa + wsize;
|
|
|
025224 |
memset(wa, 0, sizeof(*wa)*wsize*2);
|
|
|
025224 |
for(double *iw = w, *e = iw + wsize; iw < e; ++iw)
|
|
|
025224 |
*iw = rand()/(double)RAND_MAX*2 - 1;
|
|
|
53488e |
memsize += wsize*sizeof(double) + wsize*2*sizeof(double*);
|
|
|
025224 |
}
|
|
|
025224 |
|
|
|
025224 |
~LayerLink()
|
|
|
025224 |
{ delete[] wa; }
|
|
|
025224 |
|
|
|
53488e |
bool selfCheck() const {
|
|
|
53488e |
for(int i = 0; i < wsize; ++i)
|
|
|
53488e |
if ( !wa[i] || wa[i] < prev->a || wa[i] >= prev->a + prev->size
|
|
|
53488e |
|| !wda[i] || wda[i] < prev->da || wda[i] >= prev->da + prev->size )
|
|
|
53488e |
return false;
|
|
|
53488e |
return true;
|
|
|
53488e |
}
|
|
|
53488e |
|
|
|
025224 |
Layer& pass() override {
|
|
|
025224 |
double *ia = a;
|
|
|
025224 |
double *iw = w;
|
|
|
025224 |
double **iwa = wa;
|
|
|
025224 |
for(double *e = ia + size; ia < e; ++ia) {
|
|
|
025224 |
double s = 0;
|
|
|
025224 |
for(double *e = iw + lsize; iw < e; ++iw, ++iwa) {
|
|
|
025224 |
assert(*iwa);
|
|
|
025224 |
s += *iw * **iwa;
|
|
|
025224 |
}
|
|
|
025224 |
*ia = 1/(1 + exp(-s)); // sigmoid
|
|
|
025224 |
}
|
|
|
025224 |
return next ? next->pass() : *this;
|
|
|
025224 |
}
|
|
|
025224 |
|
|
|
025224 |
template<bool deep=""></bool>
|
|
|
025224 |
Layer& backpassT(double trainRatio) {
|
|
|
025224 |
double *ia = a;
|
|
|
025224 |
double *ida = da;
|
|
|
025224 |
double *iw = w;
|
|
|
025224 |
double **iwa = wa;
|
|
|
025224 |
double **iwda = wda;
|
|
|
025224 |
if (Deep) memset(prev->da, 0, sizeof(*prev->da)*prev->size);
|
|
|
025224 |
for(double *e = ia + size; ia < e; ++ia, ++ida) {
|
|
|
025224 |
double a = *ia;
|
|
|
025224 |
double ds = a * (1-a) * *ida; // sigmoid derivation * *ida
|
|
|
025224 |
double dst = ds*trainRatio;
|
|
|
025224 |
for(double *e = iw + lsize; iw < e; ++iw, ++iwa, ++iwda) {
|
|
|
025224 |
assert(*iwa && *iwda);
|
|
|
025224 |
if (Deep) **iwda += ds * *iw;
|
|
|
025224 |
*iw += dst * **iwa;
|
|
|
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 |
class LayerLinkConvolution: public LayerLink {
|
|
|
025224 |
public:
|
|
|
53488e |
LayerLinkConvolution(Layer &prev, int psx, int psy, int psz, int sx, int sy, int sz, int lsize):
|
|
|
025224 |
LayerLink(prev, sx*sy*sz, lsize*psz)
|
|
|
025224 |
{
|
|
|
025224 |
assert(psx > 0 && psy > 0 && psz > 0);
|
|
|
025224 |
assert(sx > 0 && sy > 0 && sz > 0);
|
|
|
025224 |
assert(psx*psy*psz == this->prev->size);
|
|
|
53488e |
assert(lsize > 0 && lsize <= psx*psy);
|
|
|
025224 |
|
|
|
53488e |
int hs = (int)sqrt(lsize*1.5) + 2;
|
|
|
025224 |
int s = hs*2 + 1;
|
|
|
53488e |
|
|
|
025224 |
struct Point {
|
|
|
025224 |
int x, y, r;
|
|
|
53488e |
inline bool operator<(const Point &b) const
|
|
|
53488e |
{ return r < b.r; }
|
|
|
025224 |
} *points = new Point[s*s], *p = points;
|
|
|
025224 |
|
|
|
53488e |
int r = 0;
|
|
|
53488e |
static const int rnd[] = { 9, 12, 4, 6, 0, 15, 13, 8, 2, 3, 10, 1, 5, 11, 14, 7 };
|
|
|
53488e |
for(int y = -hs; y <= hs; ++y)
|
|
|
53488e |
for(int x = -hs; x <= hs; ++x, ++r, ++p)
|
|
|
53488e |
{ p->x = x, p->y = y, p->r = (x*x + y*y)*16 + rnd[r%16]; }
|
|
|
53488e |
std::sort(points, p);
|
|
|
025224 |
|
|
|
025224 |
int *order = new int[lsize];
|
|
|
53488e |
|
|
|
53488e |
for(int y = 0; y < sy; ++y) {
|
|
|
53488e |
for(int x = 0; x < sx; ++x) {
|
|
|
53488e |
int cx = (int)((x + 0.5)/(sx + 1)*(psx + 1));
|
|
|
53488e |
int cy = (int)((y + 0.5)/(sy + 1)*(psy + 1));
|
|
|
53488e |
|
|
|
53488e |
p = points;
|
|
|
53488e |
for(int l = 0; l < lsize; ++l) {
|
|
|
53488e |
int px, py;
|
|
|
53488e |
do { px = cx + p->x; py = cy + p->y; ++p; }
|
|
|
53488e |
while(px < 0 || py < 0 || px >= psx || py >= psy);
|
|
|
53488e |
order[l] = py*psx + px;
|
|
|
53488e |
}
|
|
|
53488e |
std::sort(order, order + lsize);
|
|
|
53488e |
|
|
|
53488e |
for(int z = 0; z < sz; ++z) {
|
|
|
53488e |
for(int l = 0; l < lsize; ++l, ++p) {
|
|
|
53488e |
for(int pz = 0; pz < psz; ++pz) {
|
|
|
53488e |
int i = (((y*sx + x)*sz + z)*lsize + l)*psz + pz;
|
|
|
53488e |
int pi = order[l]*psz + pz;
|
|
|
53488e |
assert(i >= 0 && i < wsize);
|
|
|
53488e |
assert(pi >= 0 && pi < this->prev->size);
|
|
|
53488e |
wa[i] = &this->prev->a[pi];
|
|
|
53488e |
wda[i] = &this->prev->da[pi];
|
|
|
025224 |
}
|
|
|
025224 |
}
|
|
|
025224 |
}
|
|
|
025224 |
}
|
|
|
025224 |
}
|
|
|
025224 |
|
|
|
025224 |
delete[] points;
|
|
|
53488e |
delete[] order;
|
|
|
53488e |
assert(selfCheck());
|
|
|
025224 |
}
|
|
|
025224 |
};
|
|
|
025224 |
|
|
|
025224 |
|
|
|
025224 |
#endif
|