Warrior_EA/DirectML/build_accum_check.bat
AnimateDread 0c01dc279b feat: mini-batch gradient accumulation (F4), front-end-aware capacity budget (F6), split Wyckoff categoricals (N1)
Completes the 2026-08-09 training audit. FORCES A RETRAIN of every
Wyckoff-enabled config (N1 re-keys the fingerprint), and BOTH DLLs must be
redeployed alongside the .ex5 - they carry new exports.

F4 - mini-batch accumulation, TRAIN_BATCH_SIZE=32. Training was pure online
SGD (one weight update per bar), which is the mechanical source of the
era-to-era whipsaw every downstream guard was built to cope with. The O(n^2)
outer product is native - AccumulateWeightGrad / AccumulateWeightGradConv /
AccumulateBufferInto in Network.cl, WarriorCPU and WarriorDML - while the
optimizer step is host-side MQL5 shared by all tiers (ApplyAccumToBlock), so
there is one Adam/SGD implementation instead of four that can drift.
  - the LSTM needs no outer-product kernel (WeightsGradient already holds the
    sample's full dW) but could NOT simply be left un-zeroed between samples:
    CPU_LSTMSeqBackward/DML_LSTMSeqBackward memset it on entry. Hence a
    separate accumulator plus an elementwise add.
  - batch-norm gamma/beta accumulate in host arrays, not new BatchOptions
    slots - BN_OPT_STRIDE is baked into every persisted .nnw.
  - scoped to pass 2; online learning keeps immediate updates. Every save /
    checkpoint / scoring boundary flushes, scaling by the real sample count.
  - degrades to per-sample updates (one log line) on a tier that cannot
    accumulate, so old devices and DLL-free builds are unaffected.
  - verified offline: DirectML/batch_accum_check.cpp drives the real exports
    against an independent reference; at B=1 the accumulator matches the
    shipped unbatched kernel's own gradient to 1.1e-16. Math only - the
    in-situ check remains the per-layer dW/W report on a real era.

F6 - ComputeFirstLayerWidth budgeted against the RAW input width even where a
conv/LSTM front end had already reduced it, so an LSTM's dense stack was
charged for 1,280 inputs when it receives 64. Confirmed from the deployed
.cfg files: CONV, LSTM and HYBRID were all pinned at the 16-unit floor. Now
budgeted against the front-end output and capped at it (never fan out), with
the derivation reordered so both stages settle first.

N1 - EventCode/EventPhase/StructuralPhase are signed categoricals packing
direction and Wyckoff stage into one scalar across a sign discontinuity. Split
into direction + [0,1] magnitude, the same convention the base OHLC block uses.
Information-preserving; 13 readings now occupy 16 inputs.

Compiled clean (0 errors, 0 warnings); both DLLs rebuilt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-09 11:48:03 -04:00

35 lines
1.2 KiB
Batchfile

@echo off
REM Builds and runs batch_accum_check.exe - the offline math check for the
REM mini-batch accumulation exports (2026-08-09 audit, F4). Locates the VS
REM build environment itself, exactly like build_cpu.bat beside it.
REM Run build_cpu.bat FIRST so WarriorCPU.lib/.dll match the current source.
setlocal
set VSWHERE="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"
if not exist %VSWHERE% (
echo Could not find vswhere.exe - is Visual Studio / Build Tools installed?
exit /b 1
)
for /f "usebackq tokens=*" %%i in (`%VSWHERE% -latest -products * -property installationPath`) do (
set VSINSTALL=%%i
)
if not defined VSINSTALL (
echo Could not find any Visual Studio / Build Tools installation.
exit /b 1
)
call "%VSINSTALL%\VC\Auxiliary\Build\vcvars64.bat"
if errorlevel 1 exit /b 1
cd /d "%~dp0"
cl.exe /nologo /EHsc /O2 /std:c++17 batch_accum_check.cpp WarriorCPU.lib /Fe:batch_accum_check.exe
if errorlevel 1 (
echo Build failed.
exit /b 1
)
REM ".\" prefix on purpose - some shells refuse to launch an executable by bare
REM relative name, and the failure reads as "build produced nothing".
.\batch_accum_check.exe
exit /b %errorlevel%