Files
include/MatrixNetStore.mqh
2025-02-07 19:17:11 +03:30

117 lines
3.7 KiB
Plaintext

//+------------------------------------------------------------------+
//| MatrixNetStore.mqh |
//| Copyright (c) 2023, Marketeer |
//| https://www.mql5.com/ru/articles/12187/ |
//+------------------------------------------------------------------+
#include "MatrixNet.mqh"
//+------------------------------------------------------------------+
//| General storage interface for custom data |
//+------------------------------------------------------------------+
class Storage
{
public:
virtual bool store(const int h) = 0;
virtual bool restore(const int h) = 0;
};
//+-----------------------------------------------------------------------+
//| MatrixNet writer/reader with the storage interface invocation. |
//| By default handles all internal data of NN (structure, size, weights) |
//+-----------------------------------------------------------------------+
class MatrixNetStore
{
static string signature;
public:
void static setSignature(const string s)
{
signature = s;
}
string static getSignature()
{
return signature;
}
template<typename M> // M is a MatrixNet
static M *load(const string filename, Storage *storage = NULL, const int flags = 0)
{
int h = FileOpen(filename, FILE_READ | FILE_BIN | FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_ANSI | flags);
if(h == INVALID_HANDLE) return NULL;
const string header = FileReadString(h, StringLen(signature));
if(header != signature)
{
FileClose(h);
Print("Incorrect file header");
return NULL;
}
const ENUM_ACTIVATION_FUNCTION f1 = (ENUM_ACTIVATION_FUNCTION)FileReadInteger(h);
const ENUM_ACTIVATION_FUNCTION f2 = (ENUM_ACTIVATION_FUNCTION)FileReadInteger(h);
const int size = FileReadInteger(h);
matrix w[];
ArrayResize(w, size);
for(int i = 0; i < size; ++i)
{
const int rows = FileReadInteger(h);
const int cols = FileReadInteger(h);
double a[];
FileReadArray(h, a, 0, rows * cols);
w[i].Swap(a);
w[i].Reshape(rows, cols);
}
if(storage)
{
if(!storage.restore(h)) Print("External info wasn't read");
}
M *m = new M(w, f1, f2);
FileClose(h);
return m;
}
template<typename M> // M is a MatrixNet
static bool save(const string filename, const M &net, Storage *storage = NULL, const int flags = 0)
{
matrix w[];
if(!net.getBestWeights(w))
{
if(!net.getWeights(w))
{
return false;
}
}
int h = FileOpen(filename, FILE_WRITE | FILE_BIN | FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_ANSI | flags);
if(h == INVALID_HANDLE) return false;
FileWriteString(h, signature);
FileWriteInteger(h, net.getActivationFunction());
FileWriteInteger(h, net.getActivationFunction(true));
FileWriteInteger(h, ArraySize(w));
for(int i = 0; i < ArraySize(w); ++i)
{
matrix m = w[i];
FileWriteInteger(h, (int)m.Rows());
FileWriteInteger(h, (int)m.Cols());
double a[];
m.Swap(a);
FileWriteArray(h, a);
}
if(storage)
{
if(!storage.store(h)) Print("External info wasn't saved");
}
FileClose(h);
return true;
}
};
static string MatrixNetStore::signature = "BPNNMS/1.0";
//+-----------------------------------------------------------------------+