//+------------------------------------------------------------------+ //| KronosVerifyPredictorS2.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 // DecodeS1 -> context, s1_logits #include // DecodeS2 (cross-attn) #define KR_PRED_D_MODEL 512 #define KR_PRED_N_HEADS 8 #define KR_PRED_N_LAYERS 8 #define KR_PRED_FF_DIM 1024 #define KR_PRED_WEIGHT_DIR "kronos_weights\\predictor\\" input string InpRefDir = "kronos_refs\\"; input int InpLookback = 256; input double InpTol = 2e-3; // s2 = s1 pipeline + cross-attn; allow a bit more //+------------------------------------------------------------------+ //| 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("open fail %s (%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("short read %s", fname); 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 float32 values from a .bin into a flat double[]. | //+------------------------------------------------------------------+ bool LoadF32Flat(const string fname, int n, double &out[]) { int h = FileOpen(fname, FILE_READ | FILE_BIN); if(h == INVALID_HANDLE) { PrintFormat("open fail %s (%d)", fname, GetLastError()); return false; } float buf[]; ArrayResize(buf, n); uint got = FileReadArray(h, buf, 0, n); FileClose(h); if(got != (uint)n) { PrintFormat("short read %s", fname); return false; } ArrayResize(out, n); for(int i = 0; i < n; i++) out[i] = (double)buf[i]; 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("open fail %s (%d)", fname, GetLastError()); return false; } ArrayResize(out, n); uint got = FileReadArray(h, out, 0, n); FileClose(h); if(got != (uint)n) { PrintFormat("short read %s", fname); return false; } return true; } //+------------------------------------------------------------------+ //| Script entry point. | //+------------------------------------------------------------------+ void OnStart() { Print("============ Kronos predictor decode_s2 verification ============"); const int L = InpLookback; const int V = KR_PRED_VOCAB; // 1024 int s1[], s2[]; if(!LoadI32Array(InpRefDir + "s1_ids.bin", L, s1)) { Print("ABORT s1_ids"); return; } if(!LoadI32Array(InpRefDir + "s2_ids.bin", L, s2)) { Print("ABORT s2_ids"); return; } matrix stamp; if(!LoadF32Matrix(InpRefDir + "x_stamp.bin", (ulong)L, 5, stamp)) { Print("ABORT x_stamp"); return; } double ref[]; if(!LoadF32Flat(InpRefDir + "s2_logits_last.bin", L * V, ref)) { Print("ABORT s2_logits_last"); return; } //--- decode_s1 to obtain the context (and s1 logits for the pick) CKronosPredictorS1 p1; if(!p1.Init(KR_PRED_WEIGHT_DIR, KR_PRED_N_LAYERS, KR_PRED_D_MODEL, KR_PRED_N_HEADS, KR_PRED_FF_DIM)) { Print("ABORT: p1 Init"); return; } matrix s1_logits, context; if(!p1.DecodeS1(s1, s2, stamp, s1_logits, context)) { Print("ABORT: DecodeS1"); return; } //--- s1_pick = argmax of the LAST step's s1 logits (matches the reference) int last = L - 1, pick = 0; double best = s1_logits[last][0]; for(int j = 1; j < V; j++) if(s1_logits[last][j] > best) { best = s1_logits[last][j]; pick = j; } PrintFormat("s1_pick (argmax last) = %d", pick); //--- decode_s2 with the single picked s1, broadcast across context CKronosPredictorS2 p2; if(!p2.Init(KR_PRED_WEIGHT_DIR, KR_PRED_D_MODEL)) { Print("ABORT: p2 Init"); return; } Print("Predictor (s2) weights loaded."); int pick_arr[]; ArrayResize(pick_arr, 1); pick_arr[0] = pick; matrix s2_logits; if(!p2.DecodeS2(context, pick_arr, s2_logits)) { Print("ABORT: DecodeS2"); return; } PrintFormat("s2_logits %I64u x %I64u", s2_logits.Rows(), s2_logits.Cols()); if(s2_logits.Rows() != (ulong)L || s2_logits.Cols() != (ulong)V) { Print("ABORT: s2 shape mismatch"); return; } //--- full (256,1024) comparison; ref is row-major flattened double maxerr = 0.0, sumerr = 0.0; int wr = -1, wc = -1; for(int i = 0; i < L; i++) for(int j = 0; j < V; j++) { double e = MathAbs(s2_logits[i][j] - ref[i * V + j]); sumerr += e; if(e > maxerr) { maxerr = e; wr = i; wc = j; } } double meanerr = sumerr / (double)(L * V); PrintFormat("s2 logits: max abs err = %.3e (row %d col %d), mean abs err = %.3e", maxerr, wr, wc, meanerr); //--- argmax agreement on the LAST step (the row the AR loop samples) int am = 0, ar = 0; double bm = s2_logits[last][0], brf = ref[last * V + 0]; for(int j = 1; j < V; j++) { if(s2_logits[last][j] > bm) { bm = s2_logits[last][j]; am = j; } if(ref[last * V + j] > brf) { brf = ref[last * V + j]; ar = j; } } PrintFormat("last-step s2 argmax: mql=%d ref=%d %s", am, ar, (am == ar ? "(MATCH)" : "(DIFFER!)")); if(maxerr <= InpTol && am == ar) PrintFormat(">>> DECODE_S2 VERIFIED: max abs err %.3e <= tol %.3e, argmax matches. <<<", maxerr, InpTol); else Print(">>> DECODE_S2 MISMATCH: check cross-attn n_heads (4 not 8), non-causal " "window, q-position broadcast, dep_layer RMSNorm, or proj_s2. <<<"); Print("================================================================"); } //+------------------------------------------------------------------+