|
|
53488e |
|
|
|
53488e |
#include <ctime></ctime>
|
|
|
53488e |
#include <cstdlib></cstdlib>
|
|
|
53488e |
|
|
|
53488e |
#include "nnlayer2.inc.cpp"
|
|
|
53488e |
#include "nnlayer2.conv.inc.cpp"
|
|
|
53488e |
#include "nnlayer2.mt.inc.cpp"
|
|
|
53488e |
|
|
|
53488e |
|
|
|
53488e |
bool train(const char *infile, const char *outfile, Layer &l, int blockSize, int totalCount, Real trainRatio) {
|
|
|
53488e |
assert(blockSize > 0);
|
|
|
53488e |
int blockCount = totalCount/blockSize;
|
|
|
53488e |
assert(blockCount > 0);
|
|
|
53488e |
assert(!l.prev);
|
|
|
53488e |
assert(l.size && l.back().size);
|
|
|
53488e |
|
|
|
53488e |
printf("load training data\n");
|
|
|
53488e |
|
|
|
53488e |
FILE *f = fopen(infile, "rb");
|
|
|
53488e |
if (!f)
|
|
|
53488e |
return printf("cannot open file '%s' for read\n", infile), false;
|
|
|
53488e |
fseek(f, 0, SEEK_END);
|
|
|
53488e |
int fs = ftell(f);
|
|
|
53488e |
fseek(f, 0, SEEK_SET);
|
|
|
53488e |
|
|
|
53488e |
int sizeX = l.size;
|
|
|
53488e |
int sizeY = l.back().size;
|
|
|
53488e |
int count = fs/(sizeX+1);
|
|
|
53488e |
if (count < blockSize)
|
|
|
53488e |
return printf("file '%s' is lesser minimal size\n", infile), fclose(f), false;
|
|
|
53488e |
|
|
|
53488e |
unsigned char *data = new unsigned char[(sizeX + sizeY)*count];
|
|
|
53488e |
memset(data, 0, (sizeX + sizeY)*count);
|
|
|
53488e |
for(int i = 0; i < count; ++i) {
|
|
|
53488e |
unsigned char *d = data + (sizeX + sizeY)*i;
|
|
|
53488e |
if (!fread(d, sizeX+1, 1, f) || d[sizeX] >= sizeY)
|
|
|
53488e |
return printf("cannot read from file '%s'\n", infile), delete[] data, fclose(f), false;
|
|
|
53488e |
d += sizeX;
|
|
|
53488e |
unsigned char c = *d;
|
|
|
53488e |
*d = 0;
|
|
|
53488e |
d[c] = 255;
|
|
|
53488e |
}
|
|
|
53488e |
fclose(f);
|
|
|
53488e |
|
|
|
53488e |
printf("train %d x %d = %d, ratio: %f\n", blockCount, blockSize, blockCount*blockSize, trainRatio);
|
|
|
53488e |
|
|
|
53488e |
int *shuffle = new int[blockSize];
|
|
|
53488e |
TrainMT tmt;
|
|
|
53488e |
tmt.layer = &l;
|
|
|
53488e |
tmt.dataX = data;
|
|
|
53488e |
tmt.dataY = data + sizeX;
|
|
|
53488e |
tmt.strideX = tmt.strideY = sizeX + sizeY;
|
|
|
53488e |
tmt.shuffle = shuffle;
|
|
|
53488e |
tmt.count = blockSize;
|
|
|
53488e |
tmt.trainRatio = trainRatio;
|
|
|
53488e |
for(int i = 0; i < blockCount; ++i) {
|
|
|
53488e |
for(int j = 0; j < blockSize; ++j)
|
|
|
53488e |
shuffle[j] = rand()%count;
|
|
|
53488e |
Real res = tmt.train(8);
|
|
|
53488e |
printf("%4d, total %7d, avg.result %f\n", i+1, (i+1)*blockSize, res);
|
|
|
53488e |
if ( ((i+1)%10) == 0 || i+1 == blockCount ) {
|
|
|
53488e |
if (!l.saveAll(outfile)) return delete[] data, delete[] shuffle, false;
|
|
|
53488e |
printf(" saved\n");
|
|
|
53488e |
}
|
|
|
53488e |
}
|
|
|
53488e |
|
|
|
53488e |
delete[] shuffle;
|
|
|
53488e |
delete[] data;
|
|
|
53488e |
return true;
|
|
|
53488e |
}
|
|
|
53488e |
|
|
|
53488e |
|
|
|
53488e |
int main() {
|
|
|
53488e |
srand(time(NULL));
|
|
|
53488e |
|
|
|
53488e |
const char *infile = "data/symbols-data.bin"; // 28x28
|
|
|
53488e |
const char *outfile = "data/output/weights.bin";
|
|
|
53488e |
|
|
|
53488e |
printf("create neural network\n");
|
|
|
53488e |
Layer l(nullptr, 784);
|
|
|
53488e |
createConv(l, 28, 28, 1, 22, 22, 1, 60);
|
|
|
53488e |
createConv(l, 22, 22, 1, 14, 14, 1, 100);
|
|
|
53488e |
createConv(l, 14, 14, 1, 4, 4, 1, 140);
|
|
|
53488e |
createConv(l, 4, 4, 1, 1, 1, 10, 16);
|
|
|
53488e |
|
|
|
53488e |
printf(" neurons: %d, links %d, memSize: %llu\n", l.totalNeurons(), l.totalLinks(), (unsigned long long)l.totalMemSize());
|
|
|
53488e |
|
|
|
53488e |
//printf("try load previously saved network\n");
|
|
|
53488e |
//l.loadAll(outfile);
|
|
|
53488e |
|
|
|
53488e |
printf("train\n");
|
|
|
53488e |
train(infile, outfile, l, 10000, 2000000, 0.1);
|
|
|
53488e |
|
|
|
53488e |
return 0;
|
|
|
53488e |
}
|
|
|
53488e |
|