spec: Phase 3 dynamic inference brain — feature gating + temporal routing

7 adaptive pathways modulated by ISV at inference: feature gating
(WHICH features matter), temporal routing (HOW MUCH history per
feature), branch gating, gamma mod, risk budget, Mamba2 decay,
branch confidence. Model adapts to unseen regimes in 2-3 bars.

Pearls: P6 feature-level ISV gating.
Gems: G6 per-feature temporal routing.
Novels: N8 dynamic inference adaptation, N9 graceful cold start.
4 new weight tensors (78-81), 4608 params. Tasks 14-16.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-04-16 23:11:39 +02:00
parent ffc8c1c46a
commit 2acaaeaacd

View File

@@ -809,6 +809,175 @@ Note: This requires passing `states_buf` pointer and `state_dim` to the kernel.
---
## Phase 3: Dynamic Inference Brain — Feature Gating + Temporal Routing
Phases 1-2 give the model self-awareness (ISV) and market awareness (regime signals). Phase 3 uses the ISV embedding to dynamically modulate **what the model attends to** and **how much history it uses** — creating a model whose computational behavior adapts at inference without weight updates.
### The Complete Adaptive Pathway
At inference, without any gradient updates, the model dynamically adjusts 7 pathways:
```
ISV Embedding [8]
┌───────┬───────┼───────┬───────┬──────────┬──────────┐
│ │ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼ ▼
Feature Temporal Branch Gamma Risk Mamba2 Branch
Gating Routing Gating Mod Budget Decay Confidence
│ │ │ │ │ │ │
WHICH HOW WHICH HOW HOW HOW HOW
features much branches FAR MUCH MUCH CERTAIN
matter history matter plan risk memory each
to use ahead to take to keep branch is
```
**Critical insight:** At inference, training dynamics signals (grad_norm, td_error, loss) freeze at their last training EMA values. But market signals (regime_velocity, regime_disagreement, Q-drift, ensemble_var) are LIVE — they're computed from the current market state. So the model adapts to unseen regimes through the live signals while retaining training-learned behavior through the frozen signals.
### PEARL: Feature-Level ISV Gating (P6)
The ISV embedding modulates WHICH features in h_s2 the branches should attend to. A single projection produces a per-feature gate:
```
feature_gate [SH2] = sigmoid(w_feature_gate @ isv_embedding + b_feature_gate)
h_s2_gated = h_s2 * feature_gate // element-wise
```
Applied AFTER Mamba2 enrichment, BEFORE branch heads. During trends, momentum features (OFI signals) get amplified. During mean-reversion, depth imbalance features get amplified. The model learns the mapping.
This piggybacks on the existing Variable Selection Network (VSN, indices 26-33) which already does per-branch feature selection. ISV feature gating acts as a **pre-VSN filter** — it modulates which features reach the VSN at all.
```cuda
extern "C" __global__ void isv_feature_gate(
float* __restrict__ h_s2, /* [B, SH2] in-place */
const float* __restrict__ isv_embedding, /* [8] shared */
const float* __restrict__ w_feature_gate, /* [SH2, 8] */
const float* __restrict__ b_feature_gate, /* [SH2] */
int B, int SH2
) {
int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i >= B) return;
for (int j = 0; j < SH2; j++) {
float gate_val = b_feature_gate[j];
for (int k = 0; k < 8; k++)
gate_val += w_feature_gate[(long long)j * 8 + k] * isv_embedding[k];
float gate = 1.0f / (1.0f + expf(-gate_val));
h_s2[(long long)i * SH2 + j] *= gate;
}
}
```
**Init:** b_feature_gate = 2.0 (sigmoid(2)≈0.88 — near pass-through at start). The model only deviates when it helps. No feature is aggressively gated initially.
### GEM: Per-Feature Temporal Routing (G6)
Different features need different amounts of history. Momentum (OFI) is autocorrelated in trends but noise in ranges. Mean-reversion signals are the opposite. The ISV embedding controls how much Mamba2 temporal context each feature gets:
```
temporal_weight [SH2] = sigmoid(w_temporal_route @ isv_embedding + b_temporal_route)
h_enriched[j] = h_s2[j] + temporal_weight[j] * temporal_context[j]
```
This replaces the current fixed residual `h_enriched = h_s2 + temporal_context` in `mamba2_temporal_scan` with a per-feature weighted residual. Some features get full temporal enrichment, others get none — controlled by ISV.
Implementation: modify `mamba2_temporal_scan` to accept `temporal_weight [SH2]` buffer. The final line (59) changes:
```cuda
/* Current: */
out[j] = h_current[j] + ctx;
/* With temporal routing: */
out[j] = h_current[j] + temporal_weight[j] * ctx;
```
Where `temporal_weight` is pre-computed by a separate `isv_temporal_route` kernel:
```cuda
extern "C" __global__ void isv_temporal_route(
const float* __restrict__ isv_embedding, /* [8] shared */
const float* __restrict__ w_temporal_route, /* [SH2, 8] */
const float* __restrict__ b_temporal_route, /* [SH2] */
float* __restrict__ temporal_weight, /* [SH2] output */
int SH2
) {
if (threadIdx.x != 0) return;
for (int j = 0; j < SH2; j++) {
float val = b_temporal_route[j];
for (int k = 0; k < 8; k++)
val += w_temporal_route[(long long)j * 8 + k] * isv_embedding[k];
temporal_weight[j] = 1.0f / (1.0f + expf(-val));
}
}
```
**Init:** b_temporal_route = 2.0 (≈0.88 — mostly use temporal context at start, learn to suppress when appropriate).
### NOVEL: Dynamic Inference Adaptation to Unseen Data (N8)
The combination of all pathways creates a model that handles unseen market conditions through a principled cascade:
1. **Unseen regime appears** → regime_velocity spikes, regime_stability drops
2. **Mamba2 decay shortens** (N6) → model forgets old-regime patterns within 2-3 bars
3. **Feature gate shifts** (P6) → model amplifies features relevant to the new dynamics
4. **Temporal routing changes** (G6) → momentum features lose history weight, stable features keep it
5. **Branch gating shifts** → branches re-weight based on ISV's response to new signals
6. **Gamma shortens** → model focuses on near-term (doesn't extrapolate stale Q-values)
7. **Risk budget drops** → position size reduces until the model "understands" the new regime
All 7 steps happen within 2-3 bars of the regime change, without any weight updates. The model's INFERENCE BEHAVIOR adapts in real-time. This is the "dynamic brain" — not just a policy network but a **self-modifying inference system**.
### NOVEL: Inference Cold Start Graceful Degradation (N9)
At inference start, ISV history is empty (all zeros). The model gracefully handles this:
- Feature gate: sigmoid(b=2.0) ≈ 0.88 → near pass-through (no gating)
- Temporal routing: sigmoid(b=2.0) ≈ 0.88 → full temporal context
- Branch gate: softmax(0,0,0,0) = [0.25, 0.25, 0.25, 0.25] → uniform
- Gamma mod: 0.5 + 0.5*sigmoid(0) = 0.75 → slightly conservative horizon
- Risk budget: neutral ISV → moderate risk
Within 4-8 bars, ISV accumulates enough signal to start meaningful adaptation. The cold-start behavior is conservative-by-default — the model doesn't take large positions until it has enough self-awareness to justify them. This is the correct behavior for a trading system encountering new data.
### Phase 3 Weight Tensors
NUM_WEIGHT_TENSORS: 78 → 82 (4 new tensors).
| Index | Name | Shape | Purpose |
|-------|------|-------|---------|
| 78 | `w_feature_gate` | [SH2, 8] | ISV → per-feature amplitude gate |
| 79 | `b_feature_gate` | [SH2] | Feature gate bias (init=2.0) |
| 80 | `w_temporal_route` | [SH2, 8] | ISV → per-feature temporal depth |
| 81 | `b_temporal_route` | [SH2] | Temporal route bias (init=2.0) |
With SH2=256: 2048 + 256 + 2048 + 256 = **4608 new params**.
### Phase 3 Forward Pass
```
1. trunk forward (cuBLAS) → h_s2 [B, SH2]
2. isv_temporal_route() → temporal_weight [SH2]
3. mamba2_temporal_scan(temporal_weight) → h_enriched [B, SH2] (weighted residual)
4. isv_forward() → embedding, gate, gamma_mod
5. isv_feature_gate() → h_s2_gated [B, SH2] (applied to h_enriched)
6. recursive_confidence_forward() → predicted_error [B]
7. fill_gamma_buf() → gamma_buf [B]
8. risk_budget_forward() → risk_budget [B]
9. branch heads (cuBLAS) → Q values
10. branch_confidence_routing() → gated Q
11. apply_risk_budget() → scaled Q
12. action selection
```
Steps 2, 5 are new in Phase 3. Step 3 is modified (adds temporal_weight parameter).
### Implementation Order (Phase 3)
15. **ISV feature gating** — write `isv_feature_gate` kernel. Add w_feature_gate [SH2,8] + b_feature_gate [SH2] at indices 78-79. Wire after Mamba2, before branch heads. NUM_WEIGHT_TENSORS: 78→82 (add all 4 at once).
16. **Per-feature temporal routing** — write `isv_temporal_route` kernel. Add w_temporal_route [SH2,8] + b_temporal_route [SH2] at indices 80-81. Modify `mamba2_temporal_scan` to accept + use temporal_weight buffer.
17. **Final verification (Phase 3)** — compute-sanitizer 0 errors, smoke test, full suite.
---
## Risks and Mitigations
| Risk | Mitigation |
@@ -828,3 +997,8 @@ Note: This requires passing `states_buf` pointer and `state_dim` to the kernel.
| Regime signals from sample 0 only (not batch mean) | Sample 0 is representative for ADX/CUSUM which are market-level (same for all samples in a time window). For per-sample variation, the regime flows through h_s2 → branches already. |
| Regime-conditioned Mamba2 decay changes temporal context | Bounded by regime_stability ∈ [0, 1]. Stable regime: no change. Transition: faster decay (recent bars weighted more). Gradual — never drops to 0. |
| Risk branch input grows again SH2+9→SH2+13 | Same atomic update pattern as Phase 1. All offset callers updated together. |
| Feature gate collapse (all 1s or all 0s) | Init b_feature_gate=2.0 → sigmoid≈0.88 (near pass-through). Model only deviates when it helps. |
| Temporal routing interference with Mamba2 | Init b_temporal_route=2.0 → ≈0.88 (mostly use temporal). Soft start, model adjusts gradually. |
| Too many ISV-conditioned pathways → single "ISV mode" | Each pathway has own learned projection (different W matrices). They CAN respond differently to same ISV state. |
| Inference cold start (no ISV history) | All gates initialize to near pass-through. Model starts conservative, adapts in 4-8 bars as ISV accumulates. |
| Phase 3 adds 4608 params → overfitting risk | 4608 / ~580K existing = 0.8%. Feature gate and temporal route are regularized by near-pass-through init. |