# Attribution R2 · skip_flow_encoder, 10k benign, OT-CFM on raw 61-d

**Date**: 2026-04-20
**Checkpoint**: `checkpoints/attrib_10k_raw/flownids_full.pt`
**Config**: `--n-train 10000 --train-subsample random --seed 42
--skip-flow-encoder`. Phase 1 (PCL) bypassed. CFM trained directly on the
61-d quantile-transformed raw features.

## Headline numbers (AUROC on 50k / 50k)

| rank | scorer | AUROC | 95% CI | AUPRC |
|---:|---|---:|---|---:|
|  1 | **B4_gmm_K16**              | **0.9935** | [0.993, 0.994] | 0.9871 |
|  2 | **C2 terminal_norm** (CFM)  | **0.9926** | [0.992, 0.993] | 0.9866 |
|  3 | B3_mahalanobis              | 0.9922 | [0.992, 0.993] | 0.9904 |
|  4 | B4_gmm_K32                  | 0.9908 | [0.990, 0.991] | 0.9824 |
|  5 | B4_gmm_K8                   | 0.9905 | [0.990, 0.991] | 0.9848 |
|  6 | B5_knn_k5                   | 0.9882 | [0.988, 0.989] | 0.9784 |
|  7 | **C1 NLL** (CFM)            | 0.9867 | [0.986, 0.987] | 0.9813 |
|  8 | B5_knn_k10                  | 0.9852 | [0.984, 0.986] | 0.9731 |
|  9 | C3 kinetic_energy (CFM)     | 0.9647 | [0.964, 0.966] | 0.9567 |
| 10 | C4 arc_length (CFM)         | 0.9643 | [0.963, 0.965] | 0.9563 |
| 11 | B2_diag_gaussian            | 0.9119 | [0.910, 0.914] | 0.9027 |
| 12 | C5 velocity_score (CFM)     | 0.9157 | [0.914, 0.917] | 0.8890 |
| 13 | B1_isotropic                | 0.8848 | [0.883, 0.887] | 0.8697 |

## Verdict (R1 vs R2)

| | R1 (PCL latent, 32-d) | R2 (raw, 61-d) | Δ |
|---|---:|---:|---:|
| Best baseline | GMM-K32 **0.9814** | GMM-K16 **0.9935** | **+0.012** |
| C1 CFM-NLL | **0.8058** | **0.9867** | **+0.181** |
| C2 terminal_norm | 0.9341 | **0.9926** | +0.059 |
| Best-baseline vs best-CFM gap | CFM loses by 0.047 | CFM loses by 0.001 (ties) | closed |
| Rank-ensemble total gain over best baseline | +0.005 | **+0.005** (GMM+C2 +0.0049 from one channel) | same |

## Interpretation

1. **PCL encoder hurt the density-estimation task.** Dropping it:
   - Raised CFM-NLL AUROC from 0.806 to 0.987 (**+18 pp**) — CNF log-prob
     is well-behaved on the QT-normalized raw features.
   - Raised trajectory `terminal_norm` from 0.934 to 0.993.
   - Closed the baseline-vs-CFM gap from 4.7 pp to effectively zero.
2. **On raw features, everything is near-saturated at 0.99**. The task is
   so easy in this representation that methods are hard to distinguish by
   AUROC alone. Bootstrap CIs all overlap near the top.
3. **CFM's `terminal_norm` ties the best baseline** (0.9926 vs GMM-K16
   0.9935, ΔAUROC 0.0009 within CI). No statistically meaningful win, but
   no loss either.
4. **Rank-ensemble: GMM-K16 + C2 ⇒ 0.9984 (Δ+0.0049)**. This is the same
   magnitude of contribution as C3 added in R1 — the trajectory signal
   brings ~0.005 of genuinely orthogonal ranking information no matter
   which representation you use.
5. **PCL feature attribution diverged**. R1's top features were packet-size
   means; R2's are idle/active timings + flag counts — closer to what
   density-based NIDS papers typically cite. The PCL encoder seems to
   concentrate on different aspects of benign than what separates attacks.

## Paper implications

- The R2 setup (no PCL, CFM + GMM on raw QT features) matches or beats R1
  on detection. **The PCL encoder is not load-bearing for AUROC.**
- The story "OT-CFM trajectory signals are CFM-native anomaly scores" is
  defensible only in the weak sense: they provide ~0.005 AUROC beyond the
  best density baseline via rank-ensemble. Not a standalone pitch.
- **Cleanest honest pitch**: CFM-on-raw-QT + GMM-rank-ensemble, drop PCL.

## Files

- `attribution_report.json`, `attribution.log`
- `T1_auroc.png`, `T2_corr.png`, `T3_ensemble.png`, `T4_per_attack.png`
- `F1_nll_calibration.png`

Companion R1 archive: `results/attribution_pcl_10k/`.
