| --- |
| title: PINO |
| emoji: 🧪 |
| colorFrom: purple |
| colorTo: blue |
| sdk: docker |
| pinned: false |
| license: mit |
| --- |
| |
| # PINO — Physics-Informed Neural Olfaction |
|
|
| End-to-end fragrance intelligence: from molecular structure and Dortmund-UNIFAC thermodynamics to a multi-task transformer that predicts time-resolved odor trajectories. |
|
|
| ## What it does |
|
|
| PINO combines a first-principles evaporation engine with a Physics-Informed Mixture Transformer (PIMT): |
|
|
| 1. **Thermodynamic simulation** — Dortmund-Modified UNIFAC activity coefficients, stiff ODE evaporation, and headspace concentration profiles. |
| 2. **Empirical bootstrap dataset** — 5,600+ real-world records (single-molecule controls + multi-component blends), all cut with a commercial 15% concentrate / 85% ethanol solvent envelope and padded to a fixed 49-step temporal grid. |
| 3. **Multi-task transformer** — predicts objective odor trajectories, seasonality, gender/wearability profiles, and continuous alignment to the Principal Odor Map using an adaptive loss balancer. |
| 4. **Formula generation** — CMA-ES-based inverse-design composer that evolves blends against a sensory brief while respecting IFRA limits. |
|
|
| ## Quick start |
|
|
| ```bash |
| # Install |
| python -m venv .venv |
| source .venv/bin/activate |
| pip install -e . |
| |
| # Run tests (112 passed, 4 skipped) |
| python -m pytest tests/ -q |
| |
| # Train the two-arm representation A/B locally (Morgan vs genuine OpenPOM) |
| python src/pino/train.py --structural-source morgan --epochs 6 --checkpoint-name pimt_ab_morgan.pt |
| python src/pino/train.py --structural-source openpom_256 --epochs 6 --checkpoint-name pimt_ab_openpom.pt |
| |
| # Single preregistered readout on the frozen benchmarks (once per arm) |
| python scripts/evaluate_frozen_benchmarks.py --checkpoint models/pimt_ab_openpom.pt \ |
| --structural-source openpom_256 --arm-label openpom_256 --output artifacts/frozen_eval_openpom_256.json |
| |
| # Paper artifacts: canonical data macros + figures (from on-disk artifacts only) |
| python scripts/export_paper_data.py # -> artifacts/paper_data.yaml |
| python scripts/generate_paper_figures.py # -> figures/*.pdf |
| ``` |
|
|
| GPU training runs on Hugging Face Jobs against the published |
| `mattbitzesty/pino-source-code` model repo (`scripts/hf_gpu_ab_job.py`, |
| `scripts/hf_stats_job.py`); the legacy substantivity-GBM path is |
| `scripts/pimt_v9_train_publish.py`. |
|
|
| ## Repository layout |
|
|
| | Path | Purpose | |
| |------|---------| |
| | `src/pino/thermo/` | VLE, evaporation, IFRA, natural-oil profiles, OAV semantics | |
| | `src/pino/pimt_model.py` | `FragranceTrajectoryDataset` and `PhysicsInformedMixtureTransformer` | |
| | `src/pino/train.py` | Training loop with `AdaptiveLossBalancer` and molecule-disjoint split | |
| | `src/pino/heads.py` | PIMT output heads: objective, subjective, continuous alignment | |
| | `src/pino/optimizer.py` / `cli.py` | Generative inverse-design composer | |
| | `scripts/` | Dataset generation, HF job entrypoint, diagnostic scripts | |
| | `data/` | Registry, empirical dataset, literature formulas, Pyrfume annotations | |
| | `tests/` | Pytest suite for the thermodynamic engine | |
|
|
| ## Key design decisions |
|
|
| - **Natural oils are expanded** into pure constituent CASes before VLE so the engine runs real Dortmund-UNIFAC instead of falling back to Raoult's law. |
| - **All formulas are treated as 15% perfume oil concentrate + 85% ethanol**, mirroring real commercial fragrance products. |
| - **Molecule-disjoint train/validation split** prevents data leakage: if a molecule appears in a training formula, it never appears in validation. |
| - **Pure single-molecule controls follow the same molecule-disjoint split** as blends, so held-out compounds are not reintroduced through anchor records. |
| - **Adaptive loss balancing** (4 tasks: objective MSE, seasonality, wearability, continuous alignment) removes hand-tuned loss coefficients. |
| - **Continuous alignment head** replaces the legacy InfoNCE contrastive head with dense cosine similarity on the Principal Odor Map. |
|
|
| ## Open design decisions |
|
|
| - **Representation (RESOLVED by ablation, 2026-07-17):** genuine 256-dim OpenPOM v1.0.0 beats the 138-dim Morgan fallback on every frozen predictive task (substantivity, odor-threshold, descriptor). See `artifacts/representation_ablation/`. Training now supports both via `--structural-source morgan|openpom_256` (input dim 151 vs 269); a two-arm A/B trains each once and evaluates on the frozen benchmarks head-to-head. |
| - **Objective target space (OPEN):** the curated 138-dim Pyrfume single-label basis vs the full molequles multi-tag vocabulary (575 tags at ≥10 occurrences, ~10 tags/CAS, mined from Arctander/Goodscents/TGSC monograph text). The richer space may be more insightful but changes the objective head, loss, and metrics. The 575-dim multi-hot target matrix is built (`data/molequles_tag_matrix.json`) and held as an ablation arm; attribution is cleaner if it lands after the representation A/B is read out. |
| - **Prospective formula benchmark:** 40 in-silico preregistered formulas from a 51-material hobbyist palette (option held open for a community physical-compounding arm). Intended family-profile labels are sequestered (`labels.sequestered.json`, `access=evaluation_only`) and forbidden in training/model selection. |
|
|
| ## Representation A/B (two-arm, single readout) |
|
|
| Trained and evaluated **once per arm** on the frozen benchmarks. Authoritative |
| run: **20 epochs on T4 GPU** against the expanded **20-triplet** benchmark. |
| Results live in `mattbitzesty/pino-pimt-representation-ab` (public model repo). |
|
|
| | Metric | Morgan (151-d) | Genuine OpenPOM (269-d) | |
| |---|---|---| |
| | Final validation total loss (best epoch) | 0.3959 | **0.3600** | |
| | Substitution triplets (n=20, chance=0.5) | 0.30 | **0.45** | |
| | Prospective family cosine (n=40) | 0.5378 | **0.6121** | |
|
|
| - **Genuine OpenPOM ahead on all three metrics.** Largest margin on prospective |
| family-profile agreement (+0.074), most pronounced in citrus-cologne (0.56 vs |
| 0.26, where Morgan collapses). Honest caveat: both arms are below chance on |
| triplets (0.30/0.45) — a reported negative, not a win. |
| - **Model-free ablation** (`artifacts/representation_ablation/`): OpenPOM beats |
| Morgan on every frozen predictive task (5-fold paired bootstrap CIs) — the |
| statistically strongest case. |
| - **CPU run (6 epochs, n=8)** was directional only and is superseded by the GPU run. |
| - Triplet benchmark expanded 8 → 20 by mining `material_profiles` (molequles) for |
| trade-name → SMILES in `scripts/build_substitution_triplets.py`, resolving |
| proprietary trade materials (Isobutavan, Canthoxal, Neofolione, Indocolore, |
| Centifolether, Romandolide, …). All 12 new triplets carry authoritative |
| Fraterworks preference provenance + verified structural discordance. |
|
|
| ## Paper package |
|
|
| The paper build pulls facts from a single canonical source and renders figures |
| from on-disk artifacts — no retraining, no HF calls: |
|
|
| - `scripts/export_paper_data.py` → `artifacts/paper_data.yaml`: 49 lowerCamel |
| `data_macros` for the autopaper pipeline (builder prefixes `D`, digits→words; |
| e.g. `pomThreshRho` → `\DPomThreshRho`). Sourced verbatim from the frozen |
| ablation, the v10_line_drawn substantivity GBM, and the A/B frozen readout, |
| plus dataset curation stats and honest negatives. |
| - `scripts/generate_paper_figures.py` → `figures/*.pdf`: (a) ablation grouped |
| bars + 95% CI, (b) UMAP of genuine OpenPOM embeddings by odor family, |
| (c) objective-head trajectory pred-vs-target (sparsity annotated). |
|
|
| ## Training-readiness gate |
|
|
| Training is gated by `scripts/freeze_representation_validation.py`, which inspects on-disk artifacts and reports `READY_FOR_TRAINING` only when all five checks pass: genuine-POM asset present, representation ablation complete, ≥1 discordant substitution triplet admitted, 30–50 prospective formulas frozen, and prospective labels sequestered. Current status: `artifacts/training_readiness.json`. |
|
|
| ## Telemetry to verify on first HF training run |
|
|
| - **Step 1:** `AdaptiveLossBalancer` weights should be uniform (~0.25 each). |
| - **Step 10:** weights should shift dynamically as tasks progress at different rates. |
| - **Alignment loss:** starts near 1.0 and trends downward as the backbone organizes odor descriptors. |
| - **Validation loss:** reflects formulas whose active molecules are absent from training; mixed-boundary formulas are excluded to preserve isolation. |
|
|
| ## Relation to the Principal Odor Map (Lee et al., Science 2023) |
|
|
| PINO does not compete with Google's Principal Odor Map — it **builds on it** and |
| extends it to a harder problem: |
|
|
| | | POM (Lee et al. 2023) | PINO | |
| |---|---|---| |
| | Object | single molecule | multi-component blend | |
| | Output | static odor descriptors | time-resolved odor trajectory (49 steps) | |
| | Physics | none | Dortmund-UNIFAC evaporation | |
| | Validation | human panel, 400 novel odorants | frozen in-silico benchmarks | |
| | Human validation | yes (n=15 panel) | not yet (future work) | |
| | Formulation / IFRA | no | yes | |
|
|
| POM validated odor *description* for single molecules against a trained human |
| panel. PINO consumes that map as an input representation (the OpenPOM arm) and |
| shows, in a controlled two-arm A/B plus a model-free ablation, that the perceptual |
| representation is also the right foundation for **blend-trajectory** modeling — |
| a task POM did not address. The controlled comparison (paired bootstrap CIs + |
| identical-corpus two-arm training) is methodologically tighter than POM's |
| transfer-study baselines. The acknowledged gap vs POM is human-panel prospective |
| validation; PINO's prospective eval is in-silico against sequestered intended |
| profiles. |
|
|
| ## License |
|
|
| MIT — see `LICENSE`. |
|
|