Broaden the memorizing aroma heads, and measure whether it worked - #258
Merged
Merged
Conversation
A cross-validated AUROC only ever asks about molecules inside the labelled set, so it cannot see the failure that matters most for the thin heads: a head fit on twelve molecules sharing one scaffold scores 0.99 by recognising that scaffold, fires on exactly its own training molecules, and discovers nothing. audit_generalization.py fires every head over the whole corpus and counts the hits that were NOT trained on. Scoring at a single threshold turned out to conflate two opposite problems. A head with 13 positives against 2400 negatives is calibrated conservatively even with balanced class weights, so "0 novel at 0.5" covers both "learned nothing" and "learned the class but is shy about saying so" — and those want opposite fixes. The audit therefore also probes at 0.35 and returns a three-way verdict: generalizes / under-confident / memorizing. That distinction is not hypothetical. Of the aroma roster, 153 generalize, 12 are merely under-confident (pine finds 8 unlabelled molecules at 0.35, rosemary 9, freesia 9), and only turmeric and celery memorize at any threshold — both genuinely narrow single-scaffold classes where more molecules will not help. Read at 0.5 alone, all 14 looked like the same problem. Also corrects METHODS.md, which still described the aroma model as deferred to licensed data several hundred heads after it shipped. The gated piece is depth, not vocabulary. Signed-off-by: Austin L. <86896075+rvnminers-A-and-N@users.noreply.github.com>
…es (#256) Each of these heads was drawing its positives solely from the weak-labelled HSDB odor corpus, with no entry in CURATED at all — which is why they were thin and narrow enough to memorize. Adds well-established character-impact chemistry for each, chosen for structural spread rather than volume, the same way #247 moved tingling off zero: pinenes/camphene/carene/bornyl esters for pine, cineole/terpinen-4-ol/aromadendrene for eucalyptus, phthalides for celery, indole/cresol/benzyl esters/cinnamyl alcohol for narcissus. Honest result: five moved off zero at the 0.5 threshold — narcissus 0 to 4 novel discoveries, frankincense and costus to 2, fennel and allspice to 1. Another five (pine, eucalyptus, rosemary, freesia, elemi) turned out to be under-confident rather than memorizing once probed at 0.35, so the extra positives sharpened heads that had already learned their class. Turmeric and celery did not move at any threshold and are tracked separately; a single-scaffold class that thin is a model problem, not a data problem. AUROC fell for several heads (pine 0.965 to 0.905, frankincense 0.916 to 0.829). That is the right direction — a broader class is genuinely harder to fit, and a score dropping while discovery rises is what learning instead of memorizing looks like. Corpus now trains 167 aroma heads, up from 164. Signed-off-by: Austin L. <86896075+rvnminers-A-and-N@users.noreply.github.com>
This was referenced Jul 29, 2026
rvnminers-A-and-N
added a commit
that referenced
this pull request
Jul 29, 2026
) The notes picker groups heads into perceptual families and sweeps anything unlisted into an Other bucket so no head is silently dropped. The aroma `sweet` head was never listed, so it landed in Other alongside `odorless` — reading as an uncategorised leftover rather than the deliberate note it is, and sitting oddly far from vanilla/caramel/honey where a flavorist would look for it. `odorless` stays in Other on purpose: it is the absence of a percept, so it has no perceptual family to belong to, and Other is the honest home for it. Found while reconciling the chip pickers against the head roster after the retrain in #258 (164 -> 167 heads). The three heads that newly cleared the AUROC bar — blackberry, fig, magnolia — were already covered by the Fruity and Floral families, so nothing else moved. Signed-off-by: Austin L. <86896075+rvnminers-A-and-N@users.noreply.github.com>
rvnminers-A-and-N
added a commit
that referenced
this pull request
Jul 29, 2026
The retrain in #258 took the aroma roster from 164 to 167, which moved three numbers that were quoted in nineteen places across the README, five docs, the workbench UI, the MCP server, the e2e conftest and the pipeline comments in predict.py and app.py. Several were already stale before this — the profile vector had been described as 170-dimensional since before mouthfeel shipped, and one workbench card claimed 167 heads in its title while still saying 164 survive in its body. The three canonical numbers, so future drift is easy to spot: 190 trained heads in all — 6 taste + 167 aroma + 5 mouthfeel + 12 safety 178 dimensions in the flavor-profile vector — taste + aroma + mouthfeel, tox deliberately excluded because safety is not a flavor-match dimension 167 aroma descriptor heads clearing CV-AUROC >= 0.70 (The loader reports 191 artifacts: the 190 heads plus the sweetness-intensity regressor, which is a regressor rather than a head and so is not counted as one.) Also corrects the aroma training corpus size in AROMA.md, which still read 1994 molecules against an actual 2403 after the supplement work. Signed-off-by: Austin L. <86896075+rvnminers-A-and-N@users.noreply.github.com>
This was referenced Jul 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #256.
Two things here: a measurement instrument, and the data work it made possible.
The instrument
training/audit_generalization.pyfires every head over the whole corpus and counts the hits that were not in its training set. That count is the head's discovery power, and a cross-validated AUROC cannot substitute for it — CV only ever asks about molecules inside the labelled set, so a head fit on twelve molecules sharing one scaffold scores 0.99 while discovering nothing.Scoring at one threshold turned out to be wrong, and this is the part worth reading. A head with 13 positives against 2400 negatives is calibrated conservatively even with balanced class weights, so
novel@0.5 = 0conflates two opposite problems:The audit now probes at 0.35 as well and returns a three-way verdict. The distinction changed the answer materially:
turmeric,celery— nothing at any thresholdRead at 0.5 alone, all 14 looked like the same problem.
pinefinds 8 unlabelled molecules at 0.35,rosemary9,freesia9 — those heads had learned their class all along.The data
All twelve heads named in #256 had no entry in
CURATEDat all — their positives came solely from the weak-labelled HSDB odor corpus, which is exactly why they were thin enough to memorize. Added well-established character-impact chemistry for each, chosen for structural spread rather than volume (the #247 method): pinenes/camphene/carene/bornyl esters forpine, cineole/terpinen-4-ol/aromadendrene foreucalyptus, phthalides forcelery, indole/cresol/benzyl esters/cinnamyl alcohol fornarcissus.Result, stated honestly:
narcissus0→4,frankincense0→2,costus0→2,fennel0→1,allspice0→1pine,eucalyptus,rosemary,freesia,elemiturmeric,celery. Both are genuinely narrow single-scaffold classes (bisabolanes, phthalides). More molecules will not fix that; it needs a better model, not a longer list.AUROC fell for several heads (
pine0.965→0.905,frankincense0.916→0.829). That is the right direction — a broader class is harder to fit, and a score dropping while discovery rises is what learning instead of memorizing looks like.Corpus now trains 167 aroma heads, up from 164; no head was dropped.
Also
docs/METHODS.mdstill described the aroma model as deferred to licensed odor data, several hundred heads after it shipped. Corrected — what remains gated is depth, not vocabulary — and documented the two-threshold method alongside it.Provenance
All added associations are public-domain flavour/essential-oil chemistry resolved to canonical SMILES via PubChem, consistent with the existing supplement. No restricted compilation was consulted; the excluded-sources list in
docs/DATA-SOURCES.mdis unchanged.Verification
ruff check training/ tests/cleanmaster_enrichment(8,855 rows),profile_index(8,836 × 178 dims — 167 aroma + 6 taste + 5 mouthfeel),flavor_map(8,836 points)sudo systemctl restart flavormancerto deploy — the running app still holds the old 164 heads in memoryFiled #257 separately: reading
pine's raw positives surfaced chlorinated pesticides, and 105 industrial organohalogens are training flavor heads corpus-wide. Not touched here.