# Attribution R1 · PCL encoder + OT-CFM, 10k benign

**Date**: 2026-04-20
**Checkpoint**: `checkpoints/attrib_10k/flownids_full.pt`
**Config**: `--n-train 10000 --train-subsample random --seed 42`, full pipeline
(PCL phase-1 + OT-CFM phase-2), `flow_latent_dim=32`, `n_services=10`.

## Setup

Fit density baselines on the **same PCL latent** (32-d) the CFM was trained
on. Score 50k val-benign + 50k attack (random subsample, fixed seed).
Compare against CFM's native channels (NLL + 4 trajectory metrics).

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

| rank | scorer | AUROC | 95% CI | AUPRC |
|---:|---|---:|---|---:|
|  1 | **B4_gmm_K32** (sklearn GaussianMixture, 32 comp.) | **0.9814** | [0.981, 0.982] | 0.965 |
|  2 | B4_gmm_K16 | 0.9595 | [0.958, 0.961] | 0.933 |
|  3 | B4_gmm_K8  | 0.9557 | [0.954, 0.957] | 0.934 |
|  4 | B5_knn_k10 | 0.9400 | [0.939, 0.941] | 0.917 |
|  5 | B5_knn_k5  | 0.9350 | [0.934, 0.936] | 0.916 |
|  6 | **C2 terminal_norm** (CFM)  | 0.9341 | [0.932, 0.936] | 0.918 |
|  7 | C3 kinetic_energy (CFM)     | 0.9330 | [0.932, 0.935] | 0.916 |
|  8 | C4 arc_length (CFM)         | 0.9314 | [0.930, 0.933] | 0.914 |
|  9 | C5 velocity_score (CFM)     | 0.9215 | [0.920, 0.923] | 0.875 |
| 10 | B3_mahalanobis              | 0.8121 | [0.809, 0.815] | 0.683 |
| 11 | **C1 NLL (CFM)**            | 0.8058 | [0.803, 0.809] | 0.809 |
| 12 | B1_isotropic                | 0.5518 | - | 0.491 |
| 13 | B2_diag_gaussian            | 0.5241 | - | 0.476 |

## Verdict

1. **GMM-32 on PCL latent beats every CFM channel by ≥ 4.7 AUROC pp.** The
   best density baseline outscores the best CFM signal (terminal_norm) by
   0.0473. CIs of order 0.002 make this difference statistically emphatic.
2. **CFM NLL is a poor density estimator here** (0.806 < Mahalanobis 0.812
   on the same latent). CNF-derived log-prob on a 32-d PCL latent does
   not match a properly fit mixture.
3. **CFM trajectory signals ARE stronger than CFM NLL** (+0.13 AUROC),
   which validates the sub-claim that trajectory ≠ density. But neither
   channel beats GMM on the same latent.
4. **Rank-ensemble gain over GMM-32**: +0.0085 from C3, +0.0018 from C2,
   total top-of-ladder AUROC 0.9943. CFM contributes ~0.005 worth of new
   ranking information beyond what GMM already extracts.

## Interpretation

The PCL encoder compresses benign traffic into a latent with **near-mixture-
of-Gaussians structure**, to the point that the density estimation problem
becomes trivial. CFM is not the differentiator; the encoder is.

Next step: **R2** — ablate the encoder (`--skip-flow-encoder`), train CFM
directly on the 61-d quantile-transformed raw features, and re-run the same
attribution. This tests whether CFM's value appears when the data is NOT
pre-compressed into near-Gaussian modes.

## Files

- `attribution_report.json` — full T1/T2/T3/T4 + CI
- `attribution.log` — run output
- `T1_auroc.png` — per-channel AUROC bar
- `T2_corr.png`  — Spearman ρ across channels
- `T3_ensemble.png` — greedy rank-ensemble increments
- `T4_per_attack.png` — per-attack-class heatmap
- `F1_nll_calibration.png` — benign NLL vs isotropic target

Raw artifacts also live at `checkpoints/attrib_10k/` alongside the model.
