Experiments · E153

Do the extra neurons weaken the brain's composition code before learning happens?

No. Input gain was identical and Kenyon-cell input grew only 3 %; a one-third weaker drive is absorbed by the threshold.

In the log: Where the whole brain's extra 159,195 neurons enter a computation that does not read them

falsifiedDate not stated in the log; it was written between the commit of 2026-09-16 19:06 and the first commit that contains it, 2026-09-19 08:35generator · fly brain0 predictions · 2 result paragraphsEXPERIMENTS.md lines 9418–9456, lines 9458–9500, lines 9502–9529
exp E153 diagram
What E153 did and how it came out, drawn from this record and the files it names (book/assets/diagrams/exp/E153.svg).

Results

EXPERIMENTS.md · line 9458

E153 result — both mechanisms falsified. Nothing in MushroomBody differs between the two substrates, and the 10x has to be somewhere else.

Prediction 1 FALSIFIED — Kenyon-cell in-degree barely moves.

asset               n         KC     in-degree            from PN    PN share
malecns_mushroom    5,311   4,064   mean 198.3  max 581   5.6        2.80%
malecns_full      164,506   4,064   mean 204.3  max 670   5.6        2.72%
                                    x1.03                 x1.00

The induced subgraph already captured 97% of every Kenyon cell's input. Adding 159,195 neurons and ~24 million edges adds three per cent to what a KC receives, and nothing at all to what it receives from projection neurons. The dilution story I expected to dominate is wrong: there is almost nothing to dilute with, because the mushroom body is that self-contained.

Prediction 2 FALSIFIED, and on the code rather than on a measurement. mushroom.py:84-86:

rng = np.random.default_rng(seed)        # nothing consumes rng between these two lines
self.B = np.zeros((circuit.n, input_dim))
self.B[pn] = rng.normal(0, 0.9 / np.sqrt(input_dim), (len(pn), input_dim))

The draw is shaped by len(pn), which is 595 on both assets, and it is the first draw from a freshly seeded generator. B[PN] is therefore bit-identical on the two substrates, so typical = mean|B[PN] @ probe| is identical, so input_gain is identical. I predicted a factor of two or more. There is no factor. B differs only in its number of all-zero rows.

Prediction 3 is not separately answerable and should not have been stated as if it were. With the in-degree, the populations, the plastic edge set and B[PN] all identical, the KC drive is a function of the same inputs through the same weights; the across-composition share cannot collapse when nothing feeding it changed. A confirming measurement on the whole brain is chained to run when rhea_labels.py releases memory (it was OOM-killed twice this hour at ~70 MB free), but the code already settles it.

The falsification branch I named is now the live one. From the prediction: "the 10x has no mechanism in MushroomBody at all, and the next place to look is FlyGenerator's walk — the run-and-tumble over a 164,506-node graph rather than a 5,311-node one." That is where E154 goes.

One false alarm withdrawn before it spread. Both runs emit overflow encountered in matmul, divide by zero and invalid value from B @ features. Checked rather than reported: B is float64 and finite with |B|max 20.70, features is uniformly 0.05, the resulting drive is finite with zero non-finite entries and absmax 4.10. The warnings are a vectorised-kernel artefact, not a numerical failure, and nothing downstream is affected.

EXPERIMENTS.md · line 9502

E153 correction and confirmation — the "OOM-killed twice" claim is withdrawn. Both full-brain instrumentation runs completed. I checked for the process with a pgrep pattern that did not match a heredoc-fed interpreter, saw the log end at "loading", and declared a kill that never happened. The chained re-run has been disarmed before it could overwrite the finished log. The measured numbers, mushroom body against whole brain, seed 0:

quantity                        mushroom (5,311)   whole brain (164,506)   ratio
input_gain                      26.0679            26.0679                 1.000  (bit-identical, as the code said)
KC in-degree, mean              198.3              204.3                   1.03
KC drive |mean|                 0.008514           0.005751                0.68
sparsity threshold              0.0167209          0.0112872               0.68
sd/|mean| per cell, median      0.9644             0.9644                  1.000
non-finite drive entries        0                  0 of 130,048

So one thing does differ, and E153's "nothing in MushroomBody differs" was 32% too strong. The Kenyon-cell drive is a third weaker on the whole brain. Not through the gain and not through edge count — those are identical and ×1.03 — but through _project_weights' per-row budget, which divides a fixed sum across a cell's inputs weighted by measured contact count: the three per cent of extra edges the whole brain adds to each KC carry a disproportionate share of contacts, and the PN→KC weights shrink to make room. The sparsity calibration then lowers the threshold by exactly the same 0.68, and the composition-dependent share of the drive — the number that says whether the code still distinguishes alloys — is unchanged to four figures. The encoding is the same up to a scale factor the calibration was designed to absorb. Prediction 3's quantity did not move; it just should not have been listed as an independent test.

A 32% scale absorbed by calibration is not a 10x search loss. The conclusion stands: the mechanism is not in the encoder, and FlyGenerator's walk is where E154 goes.


The full record

This entry is written in 3 separate places in the log, shown here in log order.

EXPERIMENTS.md · lines 9418–9456

E153 — Where the whole brain's extra 159,195 neurons enter a computation that does not read them

E152 measured the whole brain searching ~10x worse than the mushroom body alone, with every population the learner reads identical (KC 4064, MBON 97, PAM 316, PPL 24, APL 2, PN 595, 61,210 plastic edges in both). So the extra neurons cannot carry information to the decision, and yet they cost an order of magnitude. This finds the path.

Reading _calibrate, there are exactly three ways a node outside the read populations can touch the answer:

  • the gain — input_gain="auto" sets 1/mean|B[PN] @ probe|. If B is drawn over all circuit.n rows, growing the node count changes which draws the PNs receive, so the same 595 PNs get a different random projection on the two assets.
  • the KC drive — _kc_input sums over incoming edges. In the induced subset a Kenyon cell receives only from the 5,311 selected nodes; in the whole brain it also receives from the other 159,195, which no odour drives.
  • the threshold — set from a quantile of that drive, so it inherits whatever the drive does.

Predicted:

  1. Kenyon-cell in-degree is much larger on the whole brain — several times the subset's. This is the mechanism I expect to dominate: the odour-driven component of the KC drive is diluted by a large composition-independent background, and the sparsity threshold then selects cells by how loudly they are wired rather than by what arrived. That is the same failure mode already named in this project's record for a different cause (a shared threshold sorting cells by wiring, not by input), which is why per_cell_threshold exists.
  2. input_gain differs between the two assets by more than a factor of two.
  3. The composition-dependent share of the KC drive collapses on the whole brain. Measured as the across-composition standard deviation of each cell's drive divided by its mean, this falls by an order of magnitude — matching the order of magnitude E152 lost.

Falsified if KC in-degree and input_gain are both the same on the two assets. Then nothing outside the read populations reaches the computation through the paths above, the 10x has no mechanism in MushroomBody at all, and the next place to look is FlyGenerator's walk — the run-and-tumble over a 164,506-node graph rather than a 5,311-node one.

Prediction 3 is the one that would be most useful to see fail. If the composition-dependent share is unchanged while performance is not, the encoding is fine and the loss is downstream in learning, which is a different repair entirely.

EXPERIMENTS.md · lines 9458–9500

E153 result — both mechanisms falsified. Nothing in MushroomBody differs between the two substrates, and the 10x has to be somewhere else.

Prediction 1 FALSIFIED — Kenyon-cell in-degree barely moves.

asset               n         KC     in-degree            from PN    PN share
malecns_mushroom    5,311   4,064   mean 198.3  max 581   5.6        2.80%
malecns_full      164,506   4,064   mean 204.3  max 670   5.6        2.72%
                                    x1.03                 x1.00

The induced subgraph already captured 97% of every Kenyon cell's input. Adding 159,195 neurons and ~24 million edges adds three per cent to what a KC receives, and nothing at all to what it receives from projection neurons. The dilution story I expected to dominate is wrong: there is almost nothing to dilute with, because the mushroom body is that self-contained.

Prediction 2 FALSIFIED, and on the code rather than on a measurement. mushroom.py:84-86:

rng = np.random.default_rng(seed)        # nothing consumes rng between these two lines
self.B = np.zeros((circuit.n, input_dim))
self.B[pn] = rng.normal(0, 0.9 / np.sqrt(input_dim), (len(pn), input_dim))

The draw is shaped by len(pn), which is 595 on both assets, and it is the first draw from a freshly seeded generator. B[PN] is therefore bit-identical on the two substrates, so typical = mean|B[PN] @ probe| is identical, so input_gain is identical. I predicted a factor of two or more. There is no factor. B differs only in its number of all-zero rows.

Prediction 3 is not separately answerable and should not have been stated as if it were. With the in-degree, the populations, the plastic edge set and B[PN] all identical, the KC drive is a function of the same inputs through the same weights; the across-composition share cannot collapse when nothing feeding it changed. A confirming measurement on the whole brain is chained to run when rhea_labels.py releases memory (it was OOM-killed twice this hour at ~70 MB free), but the code already settles it.

The falsification branch I named is now the live one. From the prediction: "the 10x has no mechanism in MushroomBody at all, and the next place to look is FlyGenerator's walk — the run-and-tumble over a 164,506-node graph rather than a 5,311-node one." That is where E154 goes.

One false alarm withdrawn before it spread. Both runs emit overflow encountered in matmul, divide by zero and invalid value from B @ features. Checked rather than reported: B is float64 and finite with |B|max 20.70, features is uniformly 0.05, the resulting drive is finite with zero non-finite entries and absmax 4.10. The warnings are a vectorised-kernel artefact, not a numerical failure, and nothing downstream is affected.

EXPERIMENTS.md · lines 9502–9529

E153 correction and confirmation — the "OOM-killed twice" claim is withdrawn. Both full-brain instrumentation runs completed. I checked for the process with a pgrep pattern that did not match a heredoc-fed interpreter, saw the log end at "loading", and declared a kill that never happened. The chained re-run has been disarmed before it could overwrite the finished log. The measured numbers, mushroom body against whole brain, seed 0:

quantity                        mushroom (5,311)   whole brain (164,506)   ratio
input_gain                      26.0679            26.0679                 1.000  (bit-identical, as the code said)
KC in-degree, mean              198.3              204.3                   1.03
KC drive |mean|                 0.008514           0.005751                0.68
sparsity threshold              0.0167209          0.0112872               0.68
sd/|mean| per cell, median      0.9644             0.9644                  1.000
non-finite drive entries        0                  0 of 130,048

So one thing does differ, and E153's "nothing in MushroomBody differs" was 32% too strong. The Kenyon-cell drive is a third weaker on the whole brain. Not through the gain and not through edge count — those are identical and ×1.03 — but through _project_weights' per-row budget, which divides a fixed sum across a cell's inputs weighted by measured contact count: the three per cent of extra edges the whole brain adds to each KC carry a disproportionate share of contacts, and the PN→KC weights shrink to make room. The sparsity calibration then lowers the threshold by exactly the same 0.68, and the composition-dependent share of the drive — the number that says whether the code still distinguishes alloys — is unchanged to four figures. The encoding is the same up to a scale factor the calibration was designed to absorb. Prediction 3's quantity did not move; it just should not have been listed as an independent test.

A 32% scale absorbed by calibration is not a 10x search loss. The conclusion stands: the mechanism is not in the encoder, and FlyGenerator's walk is where E154 goes.

Related entries

Built with PRISMWebsite and visualizations made using Claude