--- 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`.