--- license: mit tags: - pharmaceutical-supply-chain - traceability - anomaly-detection - tabular-classification - logistic-regression pipeline_tag: tabular-classification --- # ZigoTrace Pharma — Diversion Anomaly Model A locked, validated logistic model that scores **grey-market diversion** on a pharmaceutical serialization graph — engine: [zigo-pharma](https://github.com/Davedave001/zigo-pharma). ## Intended use — read this first - **Advisory only.** This model outputs a suspicion score that is fused as **one reliability-capped evidence source** into a larger Dempster-Shafer authenticity confidence, alongside deterministic rule-based gaps. **It never gates a dispense/release decision by itself** — the deterministic layer (recall, expiry, cold-chain, cloned-serial, aggregation, mass-balance) is the authoritative safety path, always. - **Scope: diversion only.** Trained to catch route/ring diversion — units that are *individually* unremarkable but statistically anomalous in their custody path or their aggregation-case neighbourhood. It is **not** trained to catch expired, recalled, or cold-chain-excursion stock; those are deterministic gaps, on purpose (rules validate cleanly; this model is the layer for what rules cannot express). - **Abstains under uncertainty.** Low model certainty collapses its contribution toward "unknown" rather than guessing — see `uncertainty` in the output. - **Not (yet) validated on real data.** Trained and evaluated on the synthetic dataset `zigotrace/pharma-serialized-events`. See Limitations. ## How to use Input is an **already-extracted 8-feature vector** — this model does not accept or parse a raw event graph. Feature extraction is intentionally single-sourced in the TS engine (`packages/intelligence/src/features.ts`) to avoid two implementations of graph traversal silently drifting apart; see `docs/huggingface-model-plan.md` §0. ```python from huggingface_hub import hf_hub_download import json, sys sys.path.insert(0, ".") # scorer.py ships alongside model.json in this repo from scorer import load_model, score_features model = load_model(hf_hub_download("zigotrace/pharma-authenticity-model", "model.json")) features = [0.83, 1, 1, 1, 1, 1, 4, 0.0] # route_rarity, num_receives, num_dispenses, # distinct_receive_locations, aggregation_consistent, # attestation_ok, hop_count, case_dispense_anomaly out = score_features(model, features) print(out) # AnomalyOutput(score=..., uncertainty=..., explanation="...") ``` Or via an Inference Endpoint running `handler.py`: ```json POST / {"inputs": {"features": [0.83, 1, 1, 1, 1, 1, 4, 0.0]}} ``` ## Training - **Algorithm:** logistic regression, full-batch gradient descent, fixed initialization and iteration count → **deterministic** (same events produce an identical artifact — required for GxP change control; see `packages/intelligence/src/train.ts`). - **Labels:** **weak supervision** — labeling functions over model-observable signals (rare custody route, duplicate dispense, weak attestation, case-sibling funnelling), not ground truth. Realistic for a domain where confirmed-counterfeit labels are scarce. - **Data:** `zigotrace/pharma-serialized-events` (synthetic, seed 7, 420 train / 180 test rows). ## Evaluation (this artifact, `test.jsonl`, standalone at a raw 0.5 threshold) | Metric | Value | |---|---| | Diversion detection (route + ring) | 7/7 — **100%** | | Brier score | **0.021** | | False-positive rate (standalone, 0.5 threshold) | 2.3% (4/173) | Reproduce: `python hf/local_dry_run.py` (after `node hf/generate_fixtures.mjs`). > **The false-positive rate above is a property of this model scored in isolation.** > In the shipped engine it is capped by a reliability weight inside the > Dempster-Shafer fusion and can only ever *add suspicion*, never override a > deterministic "authentic" verdict — so it does not translate into a real > false-quarantine rate. The shipped engine's actual false-quarantine rate (with this > model fused in, evaluated by `intel-validate`) is **0%**. See > `validation/model-card.md` in the source repo for the fused-system numbers. ## Model internals (inspectable — this is why logistic-first) ``` featureNames: route_rarity, num_receives, num_dispenses, distinct_receive_locations, aggregation_consistent, attestation_ok, hop_count, case_dispense_anomaly weights: [1.596, 0.026, 0.567, 0.026, 2.117, -0.567, 0.2, 1.095] bias: -2.329 ``` Weights act on **standardized** features (`(x - mean) / std`, per-feature `mean`/`std` shipped in `model.json`). `case_dispense_anomaly` (the relational feature) and `route_rarity` carry meaningful weight, consistent with the model's diversion-specific training signal. ## Limitations - Synthetic training/eval data only — real-world generalization is unverified pending a lighthouse distributor dataset (planned, gated dataset repo). - Linear model — cannot capture more complex relational patterns (e.g. multi-hop laundering rings); a GNN track exists (`ml/` in the source repo) for that, not yet outperforming this baseline on available data. - `aggregation_consistent`'s weight sign should not be over-interpreted causally — it has low variance in the synthetic generator (aggregation mismatches are a separate, rare injected pattern), so its fitted coefficient is not strongly constrained by this dataset. ## Governance - **Change control:** training is deterministic; any retrain is a new artifact with a new sha256, which is the locked version id (anchored on Hedera in the deployed engine). No silent model updates. - **Human authority:** a pharmacist/QP/auditor retains override, with recorded provenance, regardless of this model's output. - Full GxP validation pack: `validation/` in the [source repo](https://github.com/Davedave001/zigo-pharma). ## License MIT (this model + code). The synthetic dataset it's trained on is MIT-licensed generated data — see the dataset card for details.