Experiments · E27

Could the fly's odour circuit learn to rank alloys it had not seen?

Partly. Once its code was made sparse it learned (rank correlation −0.23 to +0.15), but only about a quarter of a straight-line fit's +0.56.

In the log: The fly could not learn, because its odour code was not sparse

recordedDate 2026-09-12, as written in the loggenerator · fly brain0 predictions · 0 result paragraphsEXPERIMENTS.md lines 1260–1325
exp E27 diagram
What E27 did and how it came out, drawn from this record and the files it names (book/assets/diagrams/exp/E27.svg).

Results

No result paragraph for this entry was found in the log.

The full record

EXPERIMENTS.md · lines 1260–1325

E27 — The fly could not learn, because its odour code was not sparse

Date 2026-09-12 · Question The environment is built; can the fly search it? · Provenance forager/mushroom.py, tests/test_mushroom.py, …/{fly_build,fly_diag,fly_why,fly_learn}.py

Method. Mushroom body extracted with its olfactory input (type regex ^(KC|MBON|PAM|PPL|APL)|PN): 5,311 cells, 1,066,603 edges - 4,064 Kenyon cells, 97 output neurons, 316 PAM, 24 PPL1, 2 APL, 595 projection neurons, 61,210 plastic KC->MBON synapses. A composition enters as an odour, one element per channel. Reward is the free energy from E25. Trained online over 200 compositions, scored on 60 held out, against ridge regression on the composition vector.

First result: the circuit was deaf. Every composition scored the same to within 0.0001, and the compartments disagreed identically about all of them. Three measurements found why:

  • The odour arrived at the Kenyon cells as a current of 0.0040 against a random bias of 0.048 - twelve times larger. The cells were responding to their own noise.
  • 97.8% of Kenyon cells were active for every composition. The 9.7% "sparse code" reported by the sparsity measure was the tail of that bias noise.
  • With a dense code every update touches all 61,210 synapses alike, so learning one composition overwrites every other. Measured directly: after 40 strong updates the weights moved 18% and the spread of scores went down, 2.39e-4 to 1.77e-4. It was unlearning.

Three causes, all in what was left unspecified rather than in the anatomy.

  1. Two scales had no measured value and were never set. Contact counts are not conductances, so the gain from an odour to the Kenyon cells is arbitrary; a Kenyon cell's threshold is not in a connectome at all. Left at 1 and at random noise, the odour lands below the noise. Both are now fixed by properties of real flies - an odour drives the Kenyon cells, and the code it evokes is a few percent sparse.
  2. tanh does not rectify. Raising a threshold under tanh does not silence a cell, it drives it strongly negative - and a cell that votes while silent leaves the code dense. Kenyon cells now rectify, as a firing rate must. Sparsity 97.8% -> 4.0%.
  3. Dopamine was global. One teaching signal was applied to all 97 output neurons though 40 are appetitive and 57 aversive, so the two halves cancelled. Each plastic synapse now carries the valence of the compartment it ends in.

Second result: it learns, and it is not good enough. With the sparse code, training moves the ranking reliably - Spearman -0.226 -> +0.151 on held-out compositions, and the same swing at every sparsity target tried (-0.302 -> +0.143 at 3%, -0.134 -> +0.147 at 10%). Before the fix, training moved it the wrong way or not at all.

held-out Spearman
fly, before training -0.23
fly, after training +0.15
ridge on the composition vector +0.56

The circuit learns about a quarter of what a linear model gets from the composition alone. That is the honest position, and it matches the earlier finding on a different task (0.755 against 0.948). The mechanisms are now right; the performance is not.

What is now in place: a genuinely sparse odour code, compartment-specific dopamine, calibrated gain and threshold, and evaluate() returning the spread across compartments

  • the circuit's own uncertainty, from anatomy rather than an ensemble bolted beside it. The module had no tests at all; it now has six, on a synthetic connectome so they check mechanism rather than one asset's numbers.

Not yet done. The search loop itself - proposing under a budget and measuring regret against random - is not worth running until the ranking is better than a linear model's. The next thing to test is the APL feedback inhibition, which is in the circuit (2 cells) and is what actually normalises the code in a fly; here sparsity is imposed by a fitted threshold instead, which is a stand-in for it.

Related entries

Built with PRISMWebsite and visualizations made using Claude