|
|
b579b3 |
#ifndef TRAIN_CX4_INC_CPP
|
|
|
b579b3 |
#define TRAIN_CX4_INC_CPP
|
|
|
b579b3 |
|
|
|
b579b3 |
|
|
|
b579b3 |
#include "train.segment.inc.cpp"
|
|
|
b579b3 |
#include "segment.cx4.inc.cpp"
|
|
|
b579b3 |
#include "layer.inc.cpp"
|
|
|
b579b3 |
|
|
|
b579b3 |
|
|
|
b579b3 |
class TrainerCx4: public TrainerSegment {
|
|
|
b579b3 |
protected:
|
|
|
b579b3 |
FILE *f;
|
|
|
b579b3 |
std::vector<unsigned char=""> data;</unsigned>
|
|
|
b579b3 |
std::vector<neuronreal> values;</neuronreal>
|
|
|
b579b3 |
std::vector<neuronreal> valuesMeasure;</neuronreal>
|
|
|
b579b3 |
std::vector<unsigned char=""> tmpdata;</unsigned>
|
|
|
b579b3 |
std::vector<int> shuffle;</int>
|
|
|
b579b3 |
|
|
|
b579b3 |
Layout trainLayout;
|
|
|
b579b3 |
Layout measureLayout;
|
|
|
b579b3 |
|
|
|
b579b3 |
size_t imageSize;
|
|
|
b579b3 |
size_t preparedImageSize;
|
|
|
b579b3 |
int imagesInFile;
|
|
|
b579b3 |
int imagesInMemory;
|
|
|
b579b3 |
|
|
|
b579b3 |
volatile unsigned int seed;
|
|
|
b579b3 |
|
|
|
b579b3 |
public:
|
|
|
b579b3 |
Layer *layerFull;
|
|
|
b579b3 |
Layer *layerPre;
|
|
|
b579b3 |
int loadImagesCount;
|
|
|
b579b3 |
int blocksPerLoading;
|
|
|
b579b3 |
|
|
|
b579b3 |
const char *infile;
|
|
|
b579b3 |
const char *cachefile;
|
|
|
b579b3 |
const char *outfile;
|
|
|
b579b3 |
|
|
|
b579b3 |
TrainerCx4():
|
|
|
b579b3 |
f(),
|
|
|
b579b3 |
imageSize(),
|
|
|
b579b3 |
preparedImageSize(),
|
|
|
b579b3 |
imagesInFile(),
|
|
|
b579b3 |
imagesInMemory(),
|
|
|
b579b3 |
seed(),
|
|
|
b579b3 |
layerFull(),
|
|
|
b579b3 |
layerPre(),
|
|
|
b579b3 |
loadImagesCount(),
|
|
|
b579b3 |
blocksPerLoading(1),
|
|
|
b579b3 |
infile(),
|
|
|
b579b3 |
cachefile(),
|
|
|
b579b3 |
outfile() { }
|
|
|
b579b3 |
|
|
|
b579b3 |
protected:
|
|
|
b579b3 |
void preprocess(unsigned char *src, NeuronReal *dst) {
|
|
|
b579b3 |
struct IL: public Iter {
|
|
|
b579b3 |
typedef const unsigned char* DataType;
|
|
|
b579b3 |
static inline void iter4(Neuron &n, DataType d, DataAccumType&) { n.v = *d/(NeuronReal)255; }
|
|
|
b579b3 |
};
|
|
|
b579b3 |
struct IS: public Iter {
|
|
|
b579b3 |
typedef NeuronReal* DataType;
|
|
|
b579b3 |
static inline void iter4(Neuron &n, DataType d, DataAccumType&) { *d = n.v; }
|
|
|
b579b3 |
};
|
|
|
b579b3 |
|
|
|
b579b3 |
Layer &fl = *layerFull;
|
|
|
b579b3 |
Layer &bl = *layerPre;
|
|
|
b579b3 |
|
|
|
b579b3 |
iterateNeurons2<il>(fl.layout, fl.layout, fl.neurons, src);</il>
|
|
|
b579b3 |
fl.passFull(&bl, threadsCount);
|
|
|
b579b3 |
iterateNeurons2<is>(bl.layout, bl.layout, bl.neurons, dst);</is>
|
|
|
b579b3 |
}
|
|
|
b579b3 |
|
|
|
b579b3 |
|
|
|
b579b3 |
bool loadImage(int fromIndex, int toIndex) {
|
|
|
b579b3 |
unsigned char *src = data.data();
|
|
|
b579b3 |
if (!layerPre) src += toIndex*imageSize;
|
|
|
b579b3 |
|
|
|
b579b3 |
fseeko64(f, fromIndex*imageSize, SEEK_SET);
|
|
|
b579b3 |
if (!fread(src, imageSize, 1, f))
|
|
|
b579b3 |
return fclose(f), f = nullptr, false;
|
|
|
b579b3 |
|
|
|
b579b3 |
if (layerPre) preprocess(src, values.data() + toIndex*preparedImageSize);
|
|
|
b579b3 |
|
|
|
b579b3 |
return true;
|
|
|
b579b3 |
}
|
|
|
b579b3 |
|
|
|
b579b3 |
|
|
|
b579b3 |
bool loadImages() {
|
|
|
b579b3 |
for(int i = 0; i < imagesInMemory; ++i) {
|
|
|
b579b3 |
int j = rand()%imagesInFile;
|
|
|
b579b3 |
if (i != j) std::swap(shuffle[i], shuffle[j]);
|
|
|
b579b3 |
}
|
|
|
b579b3 |
|
|
|
b579b3 |
typedef std::pair<int, int=""> Pair;</int,>
|
|
|
b579b3 |
typedef std::set<pair> Set;</pair>
|
|
|
b579b3 |
Set set;
|
|
|
b579b3 |
for(int i = 0; i < imagesInMemory; ++i)
|
|
|
b579b3 |
set.insert(Pair(shuffle[i], i));
|
|
|
b579b3 |
for(Set::iterator i = set.begin(); i != set.end(); ++i)
|
|
|
b579b3 |
loadImage(i->first, i->second);
|
|
|
b579b3 |
|
|
|
b579b3 |
return true;
|
|
|
b579b3 |
}
|
|
|
b579b3 |
|
|
|
b579b3 |
|
|
|
b579b3 |
void prepareMeasure() {
|
|
|
b579b3 |
if (measuresPerBlock <= 0) return;
|
|
|
b579b3 |
int sy = segment->sy;
|
|
|
b579b3 |
int sx = segment->sx;
|
|
|
b579b3 |
int sz = segment->sz;
|
|
|
b579b3 |
int sxz = sx*sz;
|
|
|
b579b3 |
int w = (layerPre ? layerPre : layerFull)->layout.getW();
|
|
|
b579b3 |
int h = (layerPre ? layerPre : layerFull)->layout.getH();
|
|
|
b579b3 |
int rowstride = w*sz;
|
|
|
b579b3 |
NeuronReal *dst = valuesMeasure.data();
|
|
|
b579b3 |
for(int i = 0; i < measuresPerBlock; ++i) {
|
|
|
b579b3 |
int index = rand()%imagesInMemory;
|
|
|
b579b3 |
int x = rand()%(w - sx + 1);
|
|
|
b579b3 |
int y = rand()%(h - sy + 1);
|
|
|
b579b3 |
if (layerPre) {
|
|
|
b579b3 |
const NeuronReal *src = values.data() + index*preparedImageSize + y*rowstride + x*sz;
|
|
|
b579b3 |
for(int j = 0; j < sy; ++j, src += rowstride, dst += sxz)
|
|
|
b579b3 |
memcpy(dst, src, sxz*sizeof(*dst));
|
|
|
b579b3 |
} else {
|
|
|
b579b3 |
const unsigned char *src = data.data() + index*preparedImageSize + y*rowstride + x*sz;
|
|
|
b579b3 |
for(int j = 0; j < sy; ++j, src += rowstride - sxz)
|
|
|
b579b3 |
for(int k = 0; k < sxz; ++k, ++src, ++dst)
|
|
|
b579b3 |
*dst = *src/(NeuronReal)255;
|
|
|
b579b3 |
}
|
|
|
b579b3 |
}
|
|
|
b579b3 |
}
|
|
|
b579b3 |
|
|
|
b579b3 |
|
|
|
b579b3 |
bool prepare() override {
|
|
|
b579b3 |
assert(infile);
|
|
|
b579b3 |
assert(layerFull);
|
|
|
b579b3 |
assert(loadImagesCount > 0);
|
|
|
b579b3 |
|
|
|
b579b3 |
Layer &fl = layerFull->front();
|
|
|
b579b3 |
Layer &bl = layerFull->back();
|
|
|
b579b3 |
|
|
|
b579b3 |
imageSize = fl.layout.getActiveCount();
|
|
|
b579b3 |
f = fopen(infile, "rb");
|
|
|
b579b3 |
if (!f) return false;
|
|
|
b579b3 |
fseeko64(f, 0, SEEK_END);
|
|
|
b579b3 |
imagesInFile = ftello64(f)/imageSize;
|
|
|
b579b3 |
if (imagesInFile < 1) return fclose(f), f = nullptr, false;
|
|
|
b579b3 |
imagesInMemory = loadImagesCount > imagesInFile ? imagesInFile : loadImagesCount;
|
|
|
b579b3 |
|
|
|
b579b3 |
|
|
|
b579b3 |
Layout l = layerPre ? layerPre->layout : layerFull->layout;
|
|
|
b579b3 |
assert(l.getW() >= segment->sx);
|
|
|
b579b3 |
assert(l.getH() >= segment->sy);
|
|
|
b579b3 |
assert(l.getD() == segment->sz);
|
|
|
b579b3 |
|
|
|
b579b3 |
measureLayout = Layout(segment->sx, segment->sy, segment->sz);
|
|
|
b579b3 |
valuesMeasure.resize(measuresPerBlock * measureLayout.getActiveCount());
|
|
|
b579b3 |
if (layerPre) {
|
|
|
b579b3 |
assert(l);
|
|
|
b579b3 |
preparedImageSize = layerPre->layout.getActiveCount();
|
|
|
b579b3 |
trainLayout = Layout(l.getW(), l.getH(), l.getD());
|
|
|
b579b3 |
data.resize(imageSize);
|
|
|
b579b3 |
values.resize(imagesInMemory * preparedImageSize);
|
|
|
b579b3 |
} else {
|
|
|
b579b3 |
trainLayout = measureLayout;
|
|
|
b579b3 |
data.resize(imagesInMemory * imageSize);
|
|
|
b579b3 |
values.resize(segment->sx * segment->sy * segment->sz);
|
|
|
b579b3 |
}
|
|
|
b579b3 |
|
|
|
b579b3 |
segment->f_values = values.data();
|
|
|
b579b3 |
segment->layout = trainLayout;
|
|
|
b579b3 |
tmpdata.resize(bl.layout.getActiveCount());
|
|
|
b579b3 |
if (tmpdata.size() < imageSize) tmpdata.resize(imageSize);
|
|
|
b579b3 |
|
|
|
b579b3 |
size_t memsize = data.size()*sizeof(data.front())
|
|
|
b579b3 |
+ values.size()*sizeof(values.front())
|
|
|
b579b3 |
+ valuesMeasure.size()*sizeof(valuesMeasure.front())
|
|
|
b579b3 |
+ tmpdata.size()*sizeof(tmpdata.front());
|
|
|
b579b3 |
printf("allocated size: %lld\n", (long long)(memsize));
|
|
|
b579b3 |
|
|
|
b579b3 |
shuffle.resize(imagesInFile);
|
|
|
b579b3 |
for(int i = 0; i < imagesInFile; ++i)
|
|
|
b579b3 |
shuffle[i] = i;
|
|
|
b579b3 |
|
|
|
b579b3 |
if (!loadImages()) return false;
|
|
|
b579b3 |
prepareMeasure();
|
|
|
b579b3 |
return true;
|
|
|
b579b3 |
}
|
|
|
b579b3 |
|
|
|
b579b3 |
|
|
|
b579b3 |
void finish() override
|
|
|
b579b3 |
{ if (f) fclose(f), f = nullptr; }
|
|
|
b579b3 |
|
|
|
b579b3 |
|
|
|
b579b3 |
bool prepareBlock(int block, bool measureOnly) override {
|
|
|
b579b3 |
if (block > 0 && blocksPerLoading > 0 && (block % blocksPerLoading) == 0 && !loadImages())
|
|
|
b579b3 |
return false;
|
|
|
b579b3 |
seed = rand();
|
|
|
b579b3 |
return true;
|
|
|
b579b3 |
}
|
|
|
b579b3 |
|
|
|
b579b3 |
|
|
|
b579b3 |
void finishBlock(int block) override {
|
|
|
b579b3 |
if (outfile) {
|
|
|
b579b3 |
struct IL: public Iter {
|
|
|
b579b3 |
typedef const unsigned char* DataType;
|
|
|
b579b3 |
static inline void iter4(Neuron &n, DataType d, DataAccumType&) { n.v = *d/(NeuronReal)255; }
|
|
|
b579b3 |
};
|
|
|
b579b3 |
struct IS: public Iter {
|
|
|
b579b3 |
typedef unsigned char* DataType;
|
|
|
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); }
|
|
|
b579b3 |
};
|
|
|
b579b3 |
|
|
|
b579b3 |
Layer &fl = *layerFull;
|
|
|
b579b3 |
Layer &bl = fl.back();
|
|
|
b579b3 |
|
|
|
b579b3 |
std::string outfile0(outfile);
|
|
|
b579b3 |
std::string outfile1 = outfile0 + ".1.tga";
|
|
|
b579b3 |
outfile0 += ".0.tga";
|
|
|
b579b3 |
|
|
|
b579b3 |
int index = rand()%imagesInFile;
|
|
|
b579b3 |
fseeko64(f, index*imageSize, SEEK_SET);
|
|
|
b579b3 |
fread(tmpdata.data(), imageSize, 1, f);
|
|
|
b579b3 |
tgaSave(outfile0.c_str(), tmpdata.data(), fl.layout.getW(), fl.layout.getH(), fl.layout.getD());
|
|
|
b579b3 |
|
|
|
b579b3 |
iterateNeurons2<il>(fl.layout, fl.layout, fl.neurons, tmpdata.data());</il>
|
|
|
b579b3 |
fl.passFull(&bl, threadsCount);
|
|
|
b579b3 |
|
|
|
b579b3 |
iterateNeurons2<is>(bl.layout, bl.layout, bl.neurons, tmpdata.data());</is>
|
|
|
b579b3 |
tgaSave(outfile1.c_str(), tmpdata.data(), bl.layout.getW(), bl.layout.getH(), bl.layout.getD());
|
|
|
b579b3 |
|
|
|
b579b3 |
segment->saveDemo();
|
|
|
b579b3 |
}
|
|
|
b579b3 |
}
|
|
|
b579b3 |
|
|
|
b579b3 |
|
|
|
b579b3 |
void loadData(Barrier &barrier, int block, int iter, bool measureOnly) override {
|
|
|
b579b3 |
int tid = barrier.tid;
|
|
|
b579b3 |
int threads = barrier.threads;
|
|
|
b579b3 |
int sx = segment->sx;
|
|
|
b579b3 |
int sy = segment->sy;
|
|
|
b579b3 |
int sz = segment->sz;
|
|
|
b579b3 |
int sxz = sx*sz;
|
|
|
b579b3 |
|
|
|
b579b3 |
if (measureOnly) {
|
|
|
b579b3 |
if (!tid) {
|
|
|
b579b3 |
segment->layout = measureLayout;
|
|
|
b579b3 |
segment->f_values = valuesMeasure.data() + iter*sy*sxz;
|
|
|
b579b3 |
x = y = z = 0;
|
|
|
b579b3 |
}
|
|
|
b579b3 |
} else
|
|
|
b579b3 |
if (layerPre) {
|
|
|
b579b3 |
if (!tid) {
|
|
|
b579b3 |
unsigned int s = randomNext(seed & iter);
|
|
|
b579b3 |
int index = (s = randomNext(s))%imagesInMemory;
|
|
|
b579b3 |
x = (s = randomNext(s)) % (layerPre->layout.getW() - sx + 1);
|
|
|
b579b3 |
y = (s = randomNext(s)) % (layerPre->layout.getH() - sy + 1);
|
|
|
b579b3 |
z = 0;
|
|
|
b579b3 |
segment->layout = trainLayout;
|
|
|
b579b3 |
segment->f_values = values.data() + index*preparedImageSize;
|
|
|
b579b3 |
}
|
|
|
b579b3 |
} else {
|
|
|
b579b3 |
int w = layerFull->layout.getW();
|
|
|
b579b3 |
int h = layerFull->layout.getH();
|
|
|
b579b3 |
|
|
|
b579b3 |
unsigned int s = randomNext(seed & iter);
|
|
|
b579b3 |
int index = (s = randomNext(s))%imagesInMemory;
|
|
|
b579b3 |
int x0 = (s = randomNext(s))%(w - sx + 1);
|
|
|
b579b3 |
int y0 = (s = randomNext(s))%(h - sy + 1);
|
|
|
b579b3 |
|
|
|
b579b3 |
int rowstride = w*sz;
|
|
|
b579b3 |
int dr = rowstride*threads - sxz;
|
|
|
b579b3 |
int vdr = sxz*(threads - 1);
|
|
|
b579b3 |
|
|
|
b579b3 |
const unsigned char *id0 = data.data() + index*imageSize + y0*rowstride + x0*sz;
|
|
|
b579b3 |
const unsigned char *id = id0 + tid*rowstride;
|
|
|
b579b3 |
NeuronReal *iv = values.data() + tid*sxz;
|
|
|
b579b3 |
|
|
|
b579b3 |
for(const unsigned char *e = id0 + sy*rowstride; id < e; id += dr, iv += vdr)
|
|
|
b579b3 |
for(const unsigned char *e = id + sxz; id < e; ++id, ++iv)
|
|
|
b579b3 |
*iv = *id/(NeuronReal)255;
|
|
|
b579b3 |
|
|
|
b579b3 |
if (!tid) {
|
|
|
b579b3 |
segment->layout = trainLayout;
|
|
|
b579b3 |
segment->f_values = values.data();
|
|
|
b579b3 |
x = 0, y = 0, z = 0;
|
|
|
b579b3 |
}
|
|
|
b579b3 |
}
|
|
|
b579b3 |
}
|
|
|
b579b3 |
};
|
|
|
b579b3 |
|
|
|
b579b3 |
|
|
|
b579b3 |
#endif
|