|
| 1 | +# Cambridge Mimicry: SAE Feature Validation for Heliconius Butterflies |
| 2 | + |
| 3 | +Tools for validating and exploring SAE features that discriminate Heliconius mimic pairs (erato subspecies vs melpomene subspecies), using the Cambridge Butterfly dataset. |
| 4 | + |
| 5 | +## Problem |
| 6 | + |
| 7 | +Current workflow: train sparse linear classifiers on SAE activations, extract selected feature indices, run `visuals.py` to render top-activating images, then manually interpret. |
| 8 | + |
| 9 | +The interpretation step is where things break down. `visuals.py` shows a feature's top-activating images globally with no connection to the classification task. There are no class labels on images, no per-class breakdown, no discrimination stats. You end up switching between the feature visuals, notebook tables, and raw data, trying to hold context across windows. |
| 10 | + |
| 11 | +The unit of analysis is wrong. It's currently "feature N activates on these images." It should be "feature N captures this morphological difference between these two taxa." |
| 12 | + |
| 13 | +## Ideas |
| 14 | + |
| 15 | +### Tier 1: Close the validation loop |
| 16 | + |
| 17 | +#### 1. Per-class activation grids |
| 18 | + |
| 19 | +For a (feature, task) pair, show images split by class: |
| 20 | + |
| 21 | +``` |
| 22 | +FEATURE 2391 (weight +0.034, favors melpomene) |
| 23 | +single-feature AUC: 0.91 | fires on 89% melpomene, 12% erato |
| 24 | +
|
| 25 | + erato (lativitta dorsal) melpomene (malleti dorsal) |
| 26 | +Top [img+overlay] [img] [img] [img+overlay] [img] [img] |
| 27 | +Bottom [img+overlay] [img] [img] [img+overlay] [img] [img] |
| 28 | +``` |
| 29 | + |
| 30 | +Each image gets the SAE activation heatmap overlay and the subspecies/view label. "Top" = highest activation within that class, "Bottom" = lowest. Answers: |
| 31 | + |
| 32 | +- Does the feature fire consistently on one class? |
| 33 | +- Does it fire on the wrong class? |
| 34 | +- When it doesn't fire, what does the specimen look like? |
| 35 | +- Is it always the same wing region? |
| 36 | + |
| 37 | +Highest priority item. |
| 38 | + |
| 39 | +#### 2. Feature discrimination stats |
| 40 | + |
| 41 | +For each (feature, task) pair, compute from existing SAE activations (`token_acts.npz` + class labels, no new inference): |
| 42 | + |
| 43 | +- Activation rate per class: % of images where max patch activation > 0. |
| 44 | +- Mean activation per class: the gap between classes measures effect size. |
| 45 | +- Single-feature AUC: ROC AUC using just this feature. Individual discriminative power. |
| 46 | +- Activation distribution: per-class histograms. |
| 47 | + |
| 48 | +Computable for all features at once. Useful as a triage filter before rendering images. |
| 49 | + |
| 50 | +#### 3. Labels on every image |
| 51 | + |
| 52 | +Stamp `lativitta dorsal` or `malleti ventral` on every rendered image. PIL text overlay. |
| 53 | + |
| 54 | +### Tier 2: Deeper understanding |
| 55 | + |
| 56 | +#### 4. Spatial activation heatmaps |
| 57 | + |
| 58 | +Average SAE activation maps across all specimens of a class for a given feature. Averages out per-specimen noise, reveals consistent spatial signal. Butterflies in the Cambridge dataset are pose-normalized (pinned specimens), so spatial averaging should work. The difference map (melpomene avg minus erato avg) shows where on the wing the feature discriminates. |
| 59 | + |
| 60 | +#### 5. Counter-example explorer |
| 61 | + |
| 62 | +For a feature that should distinguish erato from melpomene, find the hard cases: |
| 63 | + |
| 64 | +- Erato specimens where the feature fires strongly (false positives) |
| 65 | +- Melpomene specimens where the feature is silent (false negatives) |
| 66 | + |
| 67 | +These reveal whether the feature is picking up on something subtler than expected, whether hybrids are confusing it, or whether a subspecies population is unusual. |
| 68 | + |
| 69 | +#### 6. Feature interaction plots |
| 70 | + |
| 71 | +For a classifier with N features, make 2D scatter plots of pairwise feature activations colored by class. Shows whether features contribute independent signal or are redundant. |
| 72 | + |
| 73 | +#### 7. Morphological series |
| 74 | + |
| 75 | +Sort all specimens by a feature's activation value and display as a filmstrip. The morphological trait should vary smoothly. Computational equivalent of a morphological series in taxonomy. Could be a GIF, a marimo slider, or a static strip of 20 images. |
| 76 | + |
| 77 | +### Tier 3: Cross-run and meta-analysis |
| 78 | + |
| 79 | +#### 8. Cross-run feature alignment |
| 80 | + |
| 81 | +Different SAE runs have different latent indices. Feature 2391 in run A and feature 7739 in run B are unrelated by index, but if they activate on the same images, they capture the same trait. |
| 82 | + |
| 83 | +Compute Jaccard similarity of top-K activated image sets across runs. Build a bipartite matching. If a trait appears in 8/10 runs, it's robust. If only 1 run, likely noise. Addresses the question of biological signal vs. SAE training artifacts. |
| 84 | + |
| 85 | +#### 9. Mimicry precision quantification |
| 86 | + |
| 87 | +For each feature, measure how closely the mimic matches the model: |
| 88 | + |
| 89 | +``` |
| 90 | +Feature 2391: |
| 91 | + erato (lativitta): mean activation 0.82 +/- 0.15 |
| 92 | + melpomene (malleti): mean activation 0.31 +/- 0.12 |
| 93 | + mimicry gap: 0.51 |
| 94 | +
|
| 95 | +Feature 48: |
| 96 | + erato: mean 0.44 +/- 0.08 |
| 97 | + melpomene: mean 0.41 +/- 0.09 |
| 98 | + mimicry gap: 0.03 |
| 99 | +``` |
| 100 | + |
| 101 | +Large gaps = mimicry breaks down (what the classifier picks up on). Small gaps = precise mimicry (strong selection pressure). Reframes classifier feature weights as a quantitative map of mimicry imprecision. |
| 102 | + |
| 103 | +#### 10. Feature annotation dictionary |
| 104 | + |
| 105 | +Record annotations as you validate: `{run: "r27w7pmf", feature: 2391, trait: "red forewing band extent", confidence: "high", notes: "consistent across dorsal views"}`. Simple JSON/CSV. Builds a reusable lookup from SAE latents to morphological traits. |
| 106 | + |
| 107 | +#### 11. Batch HTML report |
| 108 | + |
| 109 | +Standalone HTML per checkpoint. Each feature gets a card with the per-class grid (1), stats (2), and annotations (10). Inline images as base64, no server needed. For sharing with collaborators. |
| 110 | + |
| 111 | +### Wild cards |
| 112 | + |
| 113 | +#### 12. Hybrid specimen analysis |
| 114 | + |
| 115 | +Run the classifier's selected features on hybrid specimens. See which parent species they resemble per trait. A hybrid might have erato-like forewing band (feature 2391 low) but melpomene-like hindwing spots (feature 48 high). Per-trait decomposition of hybrid phenotypes. |
| 116 | + |
| 117 | +#### 13. Wing region vocabulary |
| 118 | + |
| 119 | +Map features to named wing regions (forewing costa, hindwing discal cell, etc., standard lepidopteran venation nomenclature). Even a rough partition into 4-6 regions anchors ML features in morphological language. |
| 120 | + |
| 121 | +## Priority |
| 122 | + |
| 123 | +Build idea 1 first (per-class activation grids with labels). Compute idea 2 (discrimination stats) alongside it. Idea 3 (labels) is trivial. |
| 124 | + |
| 125 | +Then idea 4 (spatial heatmaps) and idea 5 (counter-examples). |
| 126 | + |
| 127 | +Ideas 8-9 (cross-run alignment, mimicry precision) are what turn this into a quantitative biology contribution rather than an interpretability exercise. |
0 commit comments