kronos-mql5/Scripts/Kronos/KronosVerifyDecoder.mq5

139 lines
5.4 KiB
MQL5
Raw Permalink Normal View History

2026-07-05 05:06:39 +00:00
//+------------------------------------------------------------------+
//| KronosVerifyDecoder.mq5 |
//| MMQ — Muhammad Minhas Qamar |
//| www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "MMQ — Muhammad Minhas Qamar"
#property link "https://www.mql5.com"
#property version "1.00"
#property script_show_inputs
#property strict
#include <Kronos\KronosDecoder.mqh> // pulls in TokenizerMath + TransformerCore + loaders
//--- tokenizer config (config_tokenizer.json); decoder shares d_model/n_heads/ff_dim
#define KR_TOK_D_MODEL 256
#define KR_TOK_N_HEADS 4
#define KR_TOK_N_DEC_LAYERS 4 // BLOCKS = this - 1 = 3
#define KR_TOK_FF_DIM 512
#define KR_TOK_WEIGHT_DIR_D "kronos_weights\\tokenizer\\"
input string InpRefDir = "kronos_refs\\";
input int InpLookback = 256;
input double InpTol = 1e-4; // max-abs-error pass threshold
//+------------------------------------------------------------------+
//| Read a [rows,cols] float32 .bin into a matrix(double). |
//+------------------------------------------------------------------+
bool LoadF32Matrix(const string fname, ulong rows, ulong cols, matrix &out)
{
int h = FileOpen(fname, FILE_READ | FILE_BIN);
if(h == INVALID_HANDLE)
{ PrintFormat("LoadF32Matrix: cannot open %s (err %d)", fname, GetLastError()); return false; }
ulong n = rows * cols;
float buf[];
ArrayResize(buf, (int)n);
uint got = FileReadArray(h, buf, 0, (int)n);
FileClose(h);
if(got != n)
{ PrintFormat("LoadF32Matrix: short read %s (%u of %I64u)", fname, got, n); return false; }
out = matrix::Zeros(rows, cols);
for(ulong r = 0; r < rows; r++)
for(ulong c = 0; c < cols; c++)
out[r][c] = (double)buf[r * cols + c];
return true;
}
//+------------------------------------------------------------------+
//| Read N int32 values from a .bin into an int[]. |
//+------------------------------------------------------------------+
bool LoadI32Array(const string fname, int n, int &out[])
{
int h = FileOpen(fname, FILE_READ | FILE_BIN);
if(h == INVALID_HANDLE)
{ PrintFormat("LoadI32Array: cannot open %s (err %d)", fname, GetLastError()); return false; }
ArrayResize(out, n);
uint got = FileReadArray(h, out, 0, n);
FileClose(h);
if(got != (uint)n)
{ PrintFormat("LoadI32Array: short read %s (%u of %d)", fname, got, n); return false; }
return true;
}
//+------------------------------------------------------------------+
//| Script entry point. |
//+------------------------------------------------------------------+
void OnStart()
{
Print("================ Kronos decoder verification ================");
const int L = InpLookback;
//--- golden token ids
int s1[], s2[];
if(!LoadI32Array(InpRefDir + "s1_ids.bin", L, s1))
{
Print("ABORT: s1_ids.bin");
return;
}
if(!LoadI32Array(InpRefDir + "s2_ids.bin", L, s2))
{
Print("ABORT: s2_ids.bin");
return;
}
//--- golden reconstruction (normalized)
matrix ref;
if(!LoadF32Matrix(InpRefDir + "recon_norm.bin", (ulong)L, KR_NFEAT, ref))
{ Print("ABORT: recon_norm.bin"); return; }
//--- build + load decoder, run it
CKronosDecoder dec;
if(!dec.Init(KR_TOK_WEIGHT_DIR_D, KR_TOK_N_DEC_LAYERS, KR_TOK_D_MODEL, KR_TOK_N_HEADS, KR_TOK_FF_DIM))
{ Print("ABORT: decoder Init failed (weights/paths)"); return; }
Print("Decoder weights loaded.");
matrix mine;
if(!dec.Decode(s1, s2, mine))
{ Print("ABORT: Decode() failed"); return; }
PrintFormat("Decode produced %I64u x %I64u", mine.Rows(), mine.Cols());
if(mine.Rows() != (ulong)L || mine.Cols() != KR_NFEAT)
{ Print("ABORT: output shape mismatch"); return; }
//--- float comparison: max-abs and mean-abs error, plus worst cell
double maxerr = 0.0, sumerr = 0.0;
int wr = -1, wc = -1;
for(int i = 0; i < L; i++)
for(int j = 0; j < KR_NFEAT; j++)
{
double e = MathAbs(mine[i][j] - ref[i][j]);
sumerr += e;
if(e > maxerr)
{
maxerr = e;
wr = i;
wc = j;
}
}
double meanerr = sumerr / (double)(L * KR_NFEAT);
PrintFormat("max abs error = %.3e (at row %d, col %d)", maxerr, wr, wc);
PrintFormat("mean abs error = %.3e", meanerr);
if(wr >= 0)
PrintFormat("worst cell: mql=%.8f ref=%.8f", mine[wr][wc], ref[wr][wc]);
//--- show first row side by side as a sanity glance
string a = "", b = "";
for(int j = 0; j < KR_NFEAT; j++)
{ a += StringFormat("%9.5f ", mine[0][j]); b += StringFormat("%9.5f ", ref[0][j]); }
PrintFormat("row0 mql: %s", a);
PrintFormat("row0 ref: %s", b);
if(maxerr <= InpTol)
PrintFormat(">>> DECODER VERIFIED: max abs error %.3e <= tol %.3e. <<<", maxerr, InpTol);
else
PrintFormat(">>> DECODER MISMATCH: max abs error %.3e > tol %.3e. "
"Check post_quant_embed shape, block count, or head transpose. <<<", maxerr, InpTol);
Print("=============================================================");
}
//+------------------------------------------------------------------+