/ Модель

Характеристики

Лицензия
Apache 2.0
Базовая модель
SpikeWhale-SNN-216M
Библиотека
pytorch
Опубликована
18 сен 2026

MaleCNS-SpikeWhale-Anatomy-LM

Генерация текстаТекст → текст3 профессии

Экспериментальная спайковая языковая модель на симулированной нейронной схеме мушки для генерации текста и изучения обучения в биологически мотивированных сетях.

4 687скачиваний за 30 дней2лайкавеса обновлены24 сен 2026

Бенчмарки

Как модель справилась с задачами пользователей ailist и что о ней публикуют открытые лидерборды

Публичные оценки

Из открытых лидербордов. Сравнивайте результаты одного теста при одинаковых условиях — отсутствие оценки не значит, что модель хуже.

В подключённых источниках результатов для этой модели пока нет.

Что умеет модель

Описание составлено по карточке модели и метаданным Hugging Face

MaleCNS-SpikeWhale-Anatomy-LM — экспериментальная языковая модель на основе разреженной спайковой нейронной сети, созданная автором репозитория Quazim0t0. Она дообучена на базе Quazim0t0/SpikeWhale-SNN-216M и использует схему связей мужской центральной нервной системы плодовой мушки MaleCNS v1.0, опубликованную Janelia и Google. В модели около 167 565 нейронов и 25,6 млн связей; обучение изменяло веса синапсов, а текст поступает через неспецифические сенсорные клетки. README также описывает экспериментальный зрительный тракт, совместное обучение на тексте и подписях к изображениям и тестирование рефлексов в симуляции целого мозга.

Модель предназначена для генерации текста и исследования того, как языковые закономерности могут возникать в спайковой нейронной сети с биологически мотивированной проводкой. Автор приводит улучшение кросс-энтропии на тестовых предложениях до 2,76, однако генерация остаётся неграмотной и неестественной, а подписи к изображениям ненадёжны. В экспериментах восстановление нейронной активности гомеостатической пластичностью нарушало языковые способности; модель является симуляцией и не воспроизводит полноценную биологию мушки. Репозиторий распространяется по лицензии Apache-2.0.

Сценарии применения

  • исследование генерации языка в спайковых нейронных сетях
  • изучение связи нейронной активности с усвоением языковых закономерностей
  • эксперименты с языковыми моделями на коннектоме плодовой мушки
  • сравнение языкового обучения с сохранением сенсорных рефлексов

Ограничения

Генерация остаётся неграмотной и неестественной, а подписи к изображениям ненадёжны; восстановление активности пластичностью в описанных экспериментах нарушало языковые способности. Это симуляция с упрощёнными нейронами, а не точная биологическая модель.

Для каких профессий подходит3

Разделы каталога профессий, в задачах которых используется эта модель

Все профессии

Карточка модели

README от автора на Hugging Face, как он его опубликовал

Открыть на Hugging Face

MaleCNS x SpikeWhale anatomy LM

Research artifact. Undertrained. Not a usable language model.

This run of the project is done for now. I answered most of the questions I had. I may pick it up later. At the last saved step (14580) it can speak English fragments - not fluent, but not the the the either. The curiosity benchmark on the network is in the card now (ARC / PIQA / ArithMark / WikiText-2).

Read this before you ask for a scrambled graph

A scramble would ask whether junk wiring of the same size also drops language CE. That is one question. It is not a stamp you put on everything below. These measurements were already in this card. They are not waiting on a scramble.

What was already measuredNumberWhy a scramble is not the missing piece
PAM / PPL1 looking-rewardimage_gain ~0 (58% of saves > 0) through VPN tokens, DINOv2, Daisy, decoder. PAM 316 / PPL1 16 on at step 10761, real DAN synapses onto 8,615 cells (4,061 / 4,064 Kenyon). Mean image_gain +0.047 (96% of saves > 0), then +0.114 by 14580 (100% of saves).Before/after on this brain. Random 316+16 blobs is a different paper. Leftover split: eye coupling 0.63 -> 0.85 (dopamine off at 0.85), not "delete MaleCNS."
Trained W is usedStep 1000: trained CE 5.07 vs shuffle-values 16.3 vs rec_scale=0 33.7Destroy the synapses, CE dies. Already an eval scramble of this W.
Language lives in the brain statebrain_gain 4.3 -> 5.3-5.8Swap another sequence's hidden state and CE blows up. Decoder made that dependence larger, not smaller.
Wrong cells vs right cellsHead-input visual tokens: 0.19% image-specific variance, image_gain ~0. VPN tokens: 14%Same trainer. Diagnosed and fixed. Within-fly lesion.
Neuromodulators took the weight changeOA: 99.6% of those synapses moved (73% sign-flipped). 5HT 82%. DA 44%Not uniform noise across the graph.
Credit on modulatory targetsCells that receive DA / OA / 5HT hold 98.8% of dLoss/d membraneAnatomical coverage, already counted.
Mushroom body is the real circuit4,064 Kenyon, 97 MBONs, 340 DANs. PPL1-gamma1pedc -> MBON11 recovered. Odour task, frozen 2948: none 0.47, backprop 0.71, real DAN -> MBON 0.67, global reward 0.64Biology vs a blob, already run.
Frozen trained synapses30 simulated days, trained W frozen: language CE 2.7627 bit-identical. Untouched synapses +17.9%Unbounded scaling wrecks language while activity can look healthy. Rate is not computation.
Sugar vs bitterOriginal MN9: sugar 222 Hz, bitter 21 Hz. After training: sugar fires, bitter 0 HzCircuit-specific.
Eight transmitter types, wiring frozenFit 24 numbers on frozen 14580: val CE 3.03 -> 2.86. Glu/histamine thr 0.82 / 0.84. DA most excitable (thr 0.808, gain 1.286)Nobody labeled inhibitory. Wiring untouched.
Phase 0 already scrambled the optic lobeFly vs degree-preserving rewired twin: twin wins MNIST; fly wins parallax 0.42 vs pixels <= 0.35 vs motion-removed 0.31The scramble that belongs on vision was already done.
Dale costIllegal-sign projection: +0.22 nats at 2948, +1.70 at 3440Constraint cost is measured.
Generate-path bugs I caughtGrey-field visual tokens on plain text; prompt not in attention. Same weights, test CE 4.44 -> 3.18 and 4.16 -> 2.80Fake-bad generations were a decoder bug, not the brain.
The decoder cannot read text without the brainThe decoder head (32.7M, 4 blocks) never sees the tokens: its only input is the brain's 4,320 read-out cells. Every token reaches it through the fly's trained synapses."The decoder does the work" is ruled out by construction. With no brain signal the decoder has no text to read.
Language lives in the brain state, at the last stepsbrain_gain at 14520 / 14540 / 14560 / 14580: +8.15 / +7.09 / +7.04 / +7.35. Held-out caption CE with the right brain 3.16-3.50; with another sequence's brain 10.20-11.66Give the decoder the wrong fly and it collapses by ~7 nats. The decoder is useless without this brain's activity.
Trained W is used, at 2855 tooTrained CE 5.00 vs shuffled synapses 26.96, random signs 21.82, original conversion W under the trained head 21.53, rec_scale=0 90.37 (logs/eval_w_ablation_step2855.json, verdict W_matters)Every corruption costs more than at step 1000: the head specialised to the trained synapse values. Caveat in the file: the ablations also silence the network ~7x, so part of the damage is the brain going quiet.

If you still want a language-CE scramble, say so as that question. Do not use it to wave away PAM/PPL1, MBON dopamine, frozen synapses, sugar/bitter, or the 8-type fit. Those are in the logs.

Hard-LIF language SNN from scratch. Recurrent matrix is the Janelia / Google MaleCNS v1.0 fruit-fly CNS, not a dense 4x1488 SpikeWhale stack. LIF cell is the SpikeWhale primitive (lif.py: hard spikes, fast-sigmoid slope 20, soft reset, DERF clamp 30). Synapse values train with nnz-only autograd through the sparse CSR.

The trained fly as a connectome: exports/connectome-weights-male-cns-v1.0-fly14580.feather - step 14580 (frozen, 30 simulated days) written in the exact format of Janelia's connectome-weights-male-cns-v1.0-minconf-0.5.feather: three int64 columns body_pre, body_post, weight, same sort, same body IDs, so it drops straight into anything that reads the original. 23,970,332 connections (1,653,146 of the original's are gone, none added), 177.9M synapses against the original's 124.2M, 36.2% of connection counts changed, no sign violations (Dale holds, and signs live in the separate transmitter file as in the original). Written by analysis/export_malecns_native.py; exports/malecns_*.feather keep the exact fractional weights plus the original counts and signs.

CheckpointWhat it is
checkpoints/vision_v4_step14580_frozen_day30.ptNewest frozen fly. Step 14580, 30 simulated days, trained synapses frozen. Language CE 2.76, identical text/captions after freeze. Space also has 14260.
checkpoints/vision_v3_step14260_frozen_day30.ptFrozen fly at 14260.
checkpoints/vision_v2_step12669.ptVision + language at 12669. VPN tokens, decoder, dopamine, eyes at 0.85. image_gain +0.079.
checkpoints/vision_v2_step12040_frozen_day30.ptFrozen fly at 12040. Language, captions, feeding reflex intact.
vision run, step 11920VPN tokens + decoder head + dopamine reward. First consistent image_gain above zero.
vision run, step 10225VPN-token diagnose / fix. Decoder and dopamine start from here.
checkpoints/real_seq2048_b4_step3440.ptNewest language-only ckpt. Spike-cap ramp, cap 600, seq 512 / batch 16
checkpoints/real_seq2048_b4_step3180.ptSpike cap 400, seq 512 / batch 16
checkpoints/real_seq2048_b4_step2855.ptSeq-2048 / batch-4 continuation of 2500. Generations below.
checkpoints/step2500.ptSeq 256. Curve + older generations.
checkpoints/step1000.ptW-ablation snapshot

Language still latches. Greedy at 2500 was the the the. At 2855 it was a longer repeated clause ("It is after the ...). Different failure. Not a fix. This is a measurement. Not SpikeWhale-216M quality.

Connectome export / Dale numbers: step 2948.

I put the eyes first because language barely uses them. Joint vision + language ran 2948 -> 14580 (Dale on). Visual tokens were the wrong cells until 10225. After VPN tokens, a decoder, dopamine "looking" reward, then SmolLM2 judge + looped decoder / HRM / JEPA / MTP, image_gain is +0.114. Captions still don't tell two photos apart. Sugar still works in the body. Bitter does not. Generation used to feed grey-field visual tokens on plain text; that was a generate-path bug, not training.


Summary: the MaleCNS SNN that learned broken English

I wanted to know if I could take MaleCNS v1.0 as Janelia / Google shipped it - no extra neurons, no invented wiring - and get a spiking net that learns language. And what that does to the fly.

It works, sort of. Broken English. Captions through the actual eyes. 167,565 neurons, 25.6M connections, all the fly's. Training only moved synapse strengths (37% of them by step 12040). Text goes in through non-visual sensory cells. A trained head reads it out. The language is in the activity: swap in another sentence's brain state and CE jumps ~3.2 -> ~8.6 (brain_gain ~5.7). Sugar -> proboscis still fires. Still a fly.

Once upon a time, there was a girl smiled .          (step 10225, greedy)
A dog runs in the skateboard .                       (photo on the eyes, sampled)
A dog runnings through a green grasss dog is playing (green image, step 12040, greedy)

Those samples were worse than the model. Text with no picture was being generated with "visual tokens" of the grey field, while training never gives text any visual tokens (only captions have images). Fixed; the same brains, run the way they were trained:

, there was a little girl who loved to play with her mommy and daddy. S   (step 14580, greedy)
, there was a little girl named Sally. He loved to play with her and wa   (step 14260, greedy)
 she was very happy. Then, she went down in the sky and started to go home
                                    ("...saw a big red ball on the grass and", 14260, greedy)
A girl of a yellow field .                              (green image, 14580, greedy caption)

Test-sentence CE dropped from 4.44 to 3.18 (step 12040) and from 4.16 to 2.80 (step 14260) with that one fix. Bug was in the generation path only. Training metrics were always the real ones.

Tokens seen (step 0 -> 14580):

legstepstokens
language, seq 2560 - 25002.56M
language, seq 20482501 - 28552.87M
language, seq 5122856 - 2948~0.76M
vision + language (text rehearsal), 48-token windows2949 - 12669~7.47M
vision + language (captions)2949 - 12669~2.5M real caption tokens (7.47M caption slots incl. padding)
text rehearsal at 256-token windows12670 - 14260~6.5M
text rehearsal at 256-token windows, batch 6414261 - 14580~5.2M
captions over both of those legs12670 - 14580~0.7M real (2.2M slots)
total~28.7M real tokens (~35.1M token positions)

Side branches that did not lead to this checkpoint add ~7.8M positions (the 2948 -> 3440 spike-cap leg, ~4.0M; the first vision leg, ~3.8M).

startnow
text CE (chance ~9.7)9.71 (step 0), 4.88 (step 2948)3.30 (step 14580, 256-token windows)
test-sentence CE--2.76 (step 14580)
gap to the Daisy-Base teacher (KL)5.37 (step 5481)1.92
held-out caption CE5.58 (step 2948)~3.25
image_gain (right vs wrong picture)~0 until 10225+0.114 (steps 14261 - 14580, positive on 100% of saves)
sugar -> MN9 (original fly 222 Hz)--235 Hz (step 12040), 217 Hz (step 14580)

The Space serves the frozen flies of steps 14580, 14260 and 12040.

What I actually did, in order.

Hard-LIF SNN, sparse synapse training, language from scratch to CE ~4.8. Then Dale's law (keep transmitter signs), spike-cap schedules, a MaleCNS export that round-trips exactly. Then the eyes: photoreceptors placed from their own synapses, colour by opsin, both eyes, tonic lamina, joint caption + text.

A lot of it broke. Full-strength eye flooded the head and exploded gradients. A hinge loss killed caption learning. Visual tokens were read from the wrong cells. A prompt bug made generation look worse than the model.

What made the picture count: tokens from the optic lobe's output neurons, DINOv2 on the eye, Daisy-Base on language, a small decoder, and a dopamine reward for looking through the fly's own PAM / PPL1 cells. After that, image use stayed above zero and kept climbing.

Then I put the trained brain back in a whole-brain LIF fly model. Sugar still fires the proboscis. Bitter does not (0 Hz at 14580; original 21 Hz). 30 simulated days of homeostatic plasticity bring activity back. Freeze the trained synapses and the original biology adapts around them. Language and captions stay. Unbounded scaling wrecks the language even when activity looks right.

It is not fluent. Captions get dog / grass / snow. They do not describe two photos correctly. The fly model's neurons are simplified. This is a simulation of the released wiring. That's it.

Space: Quazim0t0/MaleCNS-Fly. Frozen flies at steps 14580, 14260 and 12040. Talk to one, show it pictures, sugar test, or let it live 1-30 days. Runs get saved to a dataset.


Vision (next phase): the fly's eyes

The visual system is ~103,000 of the 167,565 neurons (62% of the CNS): 89,392 optic-lobe intrinsic cells, 9,201 visual projection neurons (the optic lobes' outputs, 346 types), 4,115 photoreceptors, 563 centrifugal cells. Language training barely touches it: at step 3180 only 6.2% of optic-lobe cells and 1.4% of visual projection neurons had ever been trained, against 33% of the rest of the brain.

Phase 1 trace. Rows: ship, truck, cat. Left to right: 32x32 input; both-eye photoreceptor mosaic; R8y (green, Rh6); R8p (blue, Rh5); R7 (UV, blue proxy); firing rate per stage (photoreceptors, lamina, medulla, T4/T5, lobula / lobula plate, VPN output). Colour-calibrated, both eyes. File: vision/trace/phase1_photoreceptor_channels.png.

The eye, built from the connectome's own metadata (vision/eye.py)

  • Retinotopy. assignedOlHex1/2 give each column a hex coordinate: 892 columns (right eye), 879 (left). One transform turns them into a true hexagonal lattice (88% of columns have 6 equidistant neighbours; the rest are the rim).
  • Photoreceptors placed from their own synapses. 4,108 photoreceptors carry no soma side (their cell bodies are outside the reconstructed volume), so each is assigned an eye and a column from the cells it synapses onto (vision/photoreceptor_placement.csv). Right eye: R7 (UV) in 651 columns, R8 (blue/green) in 698. Their targets match known fly wiring: R7 -> Dm8a/b, Tm5a/b; R8 -> Mi4, Mi15, Tm20, Mi1; R1-R6 -> L1, L2, L3.
  • Colour by opsin. Green -> R8y (Rh6); blue -> R8p (Rh5); green+blue -> R1-R6 (broadband Rh1); red -> nothing (flies are red-blind). RGB carries no ultraviolet, so R7 (UV) gets a blue proxy by default, or can be left silent. Dorsal-rim receptors (polarisation) are left undriven.
  • Orientation from anatomy. The dorsal-rim receptors sit at the top edge of each eye (98 and 104 degrees from the eye centre, at 0.89 of its radius), so each lattice is rotated until they point up; the left eye is mirrored. Check: in all three test images the top of the image lands on the dorsal receptors (e.g. ship: top half 0.733 / dorsal receptors 0.747). An earlier mapping had up and down swapped; the Phase 0 numbers below were run with it (linear probes are orientation-blind, so they stand).
  • Resolution without inventing neurons. Both eyes (1,771 columns) plus fixation scanning (a larger image shown as a sequence of windows, as a fly scans with saccades). No columns are interpolated.
  • Tonic lamina. Every photoreceptor synapse here is histaminergic and inhibitory (R1-R6 -> L1/L2 mean weight -0.38/-0.39), so without a resting drive nothing downstream of the photoreceptors fires at all. Lamina monopolar cells get the tonic depolarisation they have in the fly; light then suppresses them. Calibrated on 6 images x 20 settings (vision/trace/calibration.json): tonic 0.7 with recurrent gain 10 gives L2 firing that tracks the light at its column with r = -0.19 (correct sign, but weak), outputs that differ ~22% between images, 33% of cells active. Higher gain saturates (61% active, images indistinguishable).

Signal flow. Activity moves through the hierarchy one stage per tick -- lamina (tick 1), medulla (3), T4/T5 (4), lobula / lobula plate and outputs (4-5) -- then settles. From the lamina, 98% of the visual projection neurons are 2 synapses away; from the photoreceptors, every Kenyon cell and the whole language readout is within 3. Light can reach what the language head reads inside one token's 4 ticks.

Phase 0: the untrained optic lobe as an encoder

Right eye, conversion weights, linear probe on the 4,612 output neurons. The twin keeps every cell's degrees and outgoing weights and signs, and shuffles only who connects to whom.

MNIST (3k/1k, gain 10)MNIST (gain 20)Parallax speed (chance 0.25)Looming time-to-contact (chance 0.25)
Raw pixels, linear0.8820.8820.3260.840
Random projection0.8990.8990.3460.838
Fly optic lobe0.8660.8740.4180.290
Rewired twin0.9000.9050.6000.536
Fly, motion removed----0.3140.329
  • General images: the fly loses to its own rewired twin by ~3 points, at both gains. The twin pools from random places across the eye -- effectively a random projection, which suits a linear MNIST probe; the real optic lobe stays local and specialised.
  • Parallax: a small real positive. The fly decodes speed (standing in for nearness) at 0.42, above both pixel baselines (<= 0.35), and the motion-removed control falls to 0.31, so it comes from motion.
  • Looming: nothing. The fly sits at chance; the task is linearly solvable across frames, so pixels win.
  • Caveats. The twin's outputs are 2-4x more active in the depth tasks (92% vs 45% ever fire), so that comparison is not activity-matched. Every neuron shares one leak and threshold, so motion circuitry that relies on fast vs delayed pathways cannot behave as in the fly; only the wiring is biological. There is no stereo and no range sensing here -- flies have essentially neither. Stimuli were validated so no single frame gives the class away (an earlier looming version leaked it at 68% from the first frame and was rebuilt).

Text is currently fed into the eyes. The atlas "visual" text-entry group is 4,115 cells, 3,937 of which are the placed photoreceptors. Joint image + text training has to move text to the other four sensory groups and the hubs.

Joint vision + language (built; first run from step 2948, Dale on)

One brain, two streams, one readout. Images through both eyes' photoreceptors. Text through olfactory / mechanosensory / gustatory / other sensory groups and the hubs. Same Kenyon + hub next-token head. Every Kenyon cell and the whole readout is within 3 synapses of the photoreceptors, so an image can shape the next token inside one token's 4 ticks. Each step: caption micro-batch (Flickr8k, image held on the eyes for the whole caption) plus a text micro-batch (eyes on a grey field) so the language it already has is rehearsed. Text rehearsal from step 2949 on is 40% FineWeb-Edu / 40% TinyStories / 20% FinePhrase, not the language-only phase's FineWeb-Edu / DCLM / IFM mix.

Turning the eyes on at full strength wrecks the language model. Step-3440 weights, first step with the calibrated eye at full strength: logit_rms 11 -> 40, text CE 4.76 -> 12.3 after one update. Cause: 174 of the head's 256 hub readout cells are optic-lobe cells (CT1, Am1, Li, LPi, Pm, LT, ...). The head has been reading the optic lobe the whole time. Lighting the eye changes its input immediately, whatever the eye-to-brain connection does.

Fix is one dial, alpha, ramped 0 -> 1 over 2,000 steps (anchored to an absolute step, so it continues across relaunches instead of restarting). Cross-fades everything eye-related:

alpha = 0 (the step-3440 language model)alpha = 1 (calibrated eye)
Text into the photoreceptors100%0%
Light into the photoreceptors0%100%
Tonic lamina drive00.7
Optic-lobe recurrent gain1x2x
Spike capglobal, as trainedper region (central keeps its trained cap, visual uncapped)
Visual -> central input0full

Check from step 3440 (unconstrained, cap 600; tiny batch, one step per alpha):

alphatext CEcaption CElogit_rmsrate_allvisual cells ever fired
0.04.125.3013.00.00649.5%
0.56.555.6714.80.019318.7%
1.09.806.8543.60.036328.8%

At alpha = 0 it sits in its own language regime. Caption CE is already well below chance (9.71). Jumping to alpha = 1 in two steps still breaks it. The real run moves alpha by 0.0005 per step.

Start point: step 2948, Dale constraint on. 2948 and 3440 are the same language model within noise (CE 4.875 vs 4.80), but making them Dale-compliant costs +0.22 at 2948 against +1.70 at 3440 (see Dale's law). Vision run starts from 2948: 1,090,918 sign-violating synapses zeroed at load, synapse signs held to the connectome's neurotransmitter signs after every update, central spike cap stays at 80 (what 2948 was trained at). Check from step 2948:

alphatext CEcaption CElogit_rmsrate_allvisual cells ever fired
0.04.915.5821.20.00099.4%
0.57.766.9539.00.017218.6%
1.010.396.0732.70.0309--

Text CE at alpha = 0 is 2948's 4.875 plus the Dale cost, as expected. logit_rms starts near 21 rather than 11 because zeroing a million synapses shifts the head's inputs. Guard: abort only if logit_rms stays above 35 for 10 consecutive steps (abrupt eye-opening above gave 33-44; real divergence has been 128-315). Saves skipped above that so a bad state never overwrites a good checkpoint. Step 3440 is still a valid start: resume from it with central cap 600, ramp anchored at 3441, Dale off unless you accept the +1.70 cost.


Vision training: what happened (steps 2949 - 10225)

Two vision legs from step 2948, Dale on. Each optimizer step: one caption micro-batch (Flickr8k, 16 x 48 tokens, image held on the eyes) plus one text-rehearsal micro-batch (16 x 48 tokens, eyes on a grey field). About 1,536 token positions per step. ~4.6M token positions for the second leg (2949 -> 5920), half captions. Text rehearsal (the mix for every vision leg, 2949 - 14580): FineWeb-Edu 40%, TinyStories 40%, FinePhrase (faq / tutorial / math / table) 5% each.

Leg 1: eyes opened to full strength -- failed

Alpha ramped 0 -> 1 over 2,000 steps. Up to alpha ~0.7 (step ~4360) it looked healthy: caption CE 5.5 -> 3.0, text CE ~4.7, logit_rms 10-13. Past alpha ~0.95 (step ~4880) it broke:

  • Gradient explosions with a finite loss. grad_norm 10^11 - 10^14 and repeated non-finite gradients. Uncapped, 2x-gain optic lobe amplified the gradient tick after tick on the way back through time. I first blamed a spike-cap increase at step 5000. Logs: explosions started at cap 80, before that.
  • Language collapsed to The / A line loops (step 5160 generations). Caption CE 3.0 -> 5.3.
  • Images became worse than a blank field (caption CE 0.4-0.7 nats higher with the real image than with grey).
  • Single rolling checkpoint. Good states between 3400 and 4800 got overwritten. Only 5060 and 5160 survive (both after the break). Later legs keep a numbered checkpoint every 100 steps.

Fixes that came out of it: per-tick cap on the membrane gradient (membrane_grad_clip 1.0: typical per-tick norm 0.07, worst normal tick 0.15-1.3), skip (don't crash on) a non-finite gradient step, linear spike-cap schedule instead of +100/+120 jumps, alpha capped at 0.5.

Leg 2: alpha 0.5, and what I tried

stepschangeresult
2949 - 4660alpha ramps to 0.5 over 1,000 steps; text loss x2; wrong-image hinge losstext CE held 4.5-4.8; caption CE rose to 5.8-6.9
4561 -head attention (below)no effect while the hinge was on
4661 -hinge loss removedcaption CE 6.6 -> 4.0 within 350 steps
~5060 - 5480DINOv2 teacher for the eye (below)dino_cos 0 -> 0.28; held-out caption CE 4.8 -> 3.87
5481 - 5920Daisy-Base language teacher (below)gap to teacher (kd_text) 5.37 -> 2.9; text CE 4.2-5.0

The wrong-image hinge was a design error. It pushed caption CE under a wrong image up, treating right-image CE as a constant. The model could not yet tell images apart, so raising wrong-image CE meant raising all caption CE. Weight 1 cancelled the caption loss. Caption learning stopped for ~1,700 steps.

Why the images are not used: optic-lobe outputs are silent

A trace of each visual stage for the same images (step 4300, and step 2948, at alpha 0.5 and 1.0):

stagespikes per imagecells activevaries with the image
photoreceptors12k - 25kall 3,748strongly (2.2 - 3.1)
lamina (tonic cells)12k - 26k~8,800yes (0.23 - 0.74)
whole optic lobe25k - 66k12k - 24kweakly (0.11 - 0.21)
visual projection neurons (outputs to the central brain)20 - 733 - 71 of 9,201no (0.000 - 0.002)

Picture enters the eye and the lamina, then fades through the medulla. Neurons that carry vision to the central brain are nearly silent for every image. Some image information still reaches the language head through the 174 optic-lobe cells among its 256 hub readout cells. Linear probe for caption words (presence of dog, grass, snow, beach, ball, ...; held-out AUC, 0.5 = chance, shuffled-label controls 0.47 - 0.53), 640 Flickr8k images:

featuresalpha 0.5alpha 1.0best words (alpha 0.5)
raw pixels (48 x 64, reference)0.630.63grass .89, snow .84, beach .79
photoreceptors0.550.57grass .79, ball .69
lamina0.590.55grass .83, snow .76
whole optic lobe0.570.57grass .82, ball .70
language head input0.600.56snow .79, beach .77, running .73

So the head receives scene-level information (as much as the pixels carry at this resolution). Opening the eye further adds noise, not information. What the head never does is use it: the image-use check stayed at zero throughout.

Image-use check (logged at every save): 32 held-out image / caption pairs scored with the right image, a wrong image, and a grey field. image_gain = CE(wrong) - CE(right). Over the whole of leg 2 it sat between -0.03 and +0.03 nats, including after attention, DINO, and Daisy. Greedy captions are the same for different images (A man girl., there was a time to the girk .).

Additions to the head and the training signal

  • Head attention. Base head reads each token's brain state alone through an MLP. Two pre-norm residual blocks at the head's 128-d width, zero-initialised outputs (loaded model unchanged at step 0), 695k parameters: causal self-attention over earlier head states, and cross-attention from every caption token to 4 visual tokens (the head's input features after each of 4 image-only steps before the caption).
  • DINOv2 teacher for the eye (facebook/dinov2-base, frozen, training only). Each caption image also goes through DINOv2 at 224 x 224. The fly's 9,201 visual projection neurons (tanh membrane, averaged over the image-only steps) pass through a trainable linear map. Loss is 1 - cosine to DINO's CLS embedding. Gradient runs back through the fly's own synapses. Match rose from 0 to 0.28 by step 5480, then held at 0.19 - 0.27: optic-lobe outputs now carry part of what DINO sees. The head still did not use it for words.
  • Daisy-Base language teacher (DaisyChainAI/Daisy-Base, 106M SpikeWhale transformer, frozen). Tokenizer is byte-for-byte the SNN's (16,512 tokens), so distillation is on the full next-token distribution: on text batches, loss += 1.0 x T^2 x KL(teacher / T || SNN / T), T = 2. On the SNN's own token stream Daisy scores CE 2.57 against ~4.9 for step 2948. In 440 steps the KL gap fell 5.37 -> 2.9. Text CE (4.2 - 5.0, batch-dependent; teacher's own CE on the same batches swings 2.4 - 2.9) had not yet clearly moved when the leg ended at 5920.

State at step 5920

step 2948 (start)step 5920
text CE4.884.2 - 5.0 (last save 4.97)
caption CE (held-out pairs)5.58~3.7 - 3.9
image_gain--~0
DINO match (dino_cos)--0.19 - 0.27
gap to Daisy (KL)--~2.9

The SNN moved towards the language teacher (KL gap nearly halved). Text CE itself had not yet improved on step 2948 by the end of the leg. Vision side did not produce image-dependent captions. Caption CE fell by learning how Flickr captions are phrased, not what is in each picture.

Steps 5921 - 10225 (both teachers, alpha 0.5)

Same setup for 4,305 more steps (~6.6M token positions, half captions): DINOv2 eye teacher and Daisy-Base language teacher on, head attention on, central spike cap ramping 80 -> 400 by step ~7200 and held there. Stable: no skipped steps, grad_norm ~5, logit_rms ~15. Averages over each tenth of the run (logs/vision_v2_train_5921_10225.log):

stepstext CEgap to Daisy (KL)caption CE (train)DINO match
5921 - 63204.522.673.550.27
7600 - 80004.542.293.040.30
8860 - 92604.422.222.810.34
9700 - 101004.362.182.740.37

Held-out caption CE (image-use check) 4.31 -> 2.87; image_gain stayed at +0.00 to +0.03 the whole run (last: right image 2.865, wrong image 2.873, grey 3.038). Text CE improved only 0.16 over the leg.

Generations at step 10225 (trained eye setup, spike cap 400, greedy; logs/generate_vision_step10225.log):

eyes: grey field     A man in a red shirt -> "y, the the snowy."
eyes: photo 1        A dogs -> " is a rock and the snowy in the air and a girl snow"
eyes: photo 2        A man in a red shirt -> " ack ack ack ack ack ack ack ack ack ack cle ack"
any                  Once upon a time -> "er ack ack ack ..." / "iting."

With a photo the words shift towards caption vocabulary (dog, rock, snow, air, girl). The two photos are not described differently. Greedy falls into ack ack ack loops. Plain-text prompts come out broken. Language is weaker than the training CE suggests.

Why the head does not use the image (diagnosed at step 10225)

Each link from the picture to the words, tested on 64 caption images (--diagnose, logs/vision_diagnose_step10225.json):

linkresult
optic-lobe outputs (VPNs) -> DINO student: which image is this?the right image is picked out of 64 41% of the time (chance 1.6%); cosine 0.36 to its own DINO embedding vs 0.15 to others
visual tokens the cross-attention reads: do they differ between images?no: 99.8% identical; image-specific share of their variance 0.19%
does the head use cross-attention?yes, heavily: its output is 2.1x the size of its input
caption CE: right tokens / wrong tokens / no tokens2.551 / 2.549 / 2.748
caption CE: right tokens but wrong image on the eyes2.561

Cause: a design error in the visual tokens. The DINO teacher trained the optic lobe's output neurons (VPNs). They learned to carry the image. Visual tokens were built from the language head's input cells - a different set, almost the same for every image. Cross-attention learned to use those tokens as a constant (worth 0.2 nats) while the image sat in cells it never read.

Fix (visual_tokens_from: "vpn"): visual tokens are now the VPNs' tanh membrane, averaged per image-only step (4 tokens x 9,201 cells). In training the caption loss also flows back into the eye through them. Measured on the same step-10225 weights, before any training with it (32 images, logs/vision_diagnose_step10225_vpn_tokens.json): image-specific share of the token variance 0.19% -> 14% (~70x), mean similarity between two images' tokens 0.998 -> 0.858. Token input layer starts untrained, so caption CE does not depend on the image yet (right 2.652 / wrong 2.647). A training run has to learn to read them. Next leg started from step 10225 with this change.

Steps 10226 - 11920: eye-output tokens, a decoder head, and a dopamine reward

Same setup (DINOv2 eye teacher, Daisy-Base language teacher, Dale on), now with visual tokens from the optic-lobe outputs, plus three additions:

  • Eye coupling 0.5 -> 0.85 over 1,500 steps from step 10226 (reached at 11726).
  • Decoder head. Small modern transformer on top of the brain's read features: width 512, 4 layers, 8 heads, each with causal self-attention with RoPE, cross-attention to the visual tokens and an MLP, final norm; 32M parameters. Its logits add to the original head's through a zero-initialised output layer, so the loaded checkpoint is unchanged at the first step (text CE identical, 3.618 on the CPU check). It does not see the token embedding. Everything it knows comes through the brain. A brain check is logged at every save: same held-out captions scored with another sequence's brain state; brain_gain = CE(wrong brain state) - CE(right). It was 4.3 at 10225 and rose to 5.3 - 5.8 with the decoder: the head leans more on the brain, not less.
  • Dopamine reward for looking (from step 10761). For every caption image: reward = CE(caption | wrong image) - CE(caption | right image); reward prediction error = (reward - running mean) / running std. Delivered through the fly's own dopamine neurons: a positive error drives the 316 PAM (reward) cells, a negative one the 16 PPL1 (punishment) cells, while the image is shown again. Their spikes reach 8,615 cells (4,061 of the 4,064 Kenyon cells) through the real 149,070 DAN synapses. A three-factor rule then changes the 2.6M synapses onto those cells: d|W| = lr x (dopamine at the post cell - its running baseline) x pre rate x post rate (PAM input +, PPL1 input -; magnitudes only, Dale-safe; lr 1e-4, capped at 1e-3 per step), applied next to the gradient update.

image_gain averaged over each period (a single save scores only 32 pairs and swings +-0.02 - 0.03 on its own, so averages are what matter):

stepssetupmean image_gainsaves above 0
5921 - 10225old visual tokens+0.003 +- 0.001 (216 saves)58%
10421 - 10760eye-output tokens + decoder+0.017 +- 0.006 (17)76%
10761 - 11920+ dopamine reward+0.047 +- 0.003 (57)96%

By quarter of the dopamine period: +0.040, +0.045, +0.043, +0.058. Per-batch training reward stayed positive throughout (+0.040 -> +0.067). First period where image use was consistently above zero. Language improved at the same time: text CE 4.28 -> 4.07, gap to Daisy (KL) 2.30 -> 2.04; brain_gain held at 5.6. No skipped steps. That before/after is the result. You do not need a scrambled MaleCNS to believe it. The leftover control is not "delete the fly": eye coupling also rose 0.63 -> 0.85 in the same window, so a run at 0.85 with dopamine off would split dopamine from a stronger eye. grad_norm rose from 4 - 8 to 17 - 48 in this period (clipped, stable so far).

Generation fix. Generation code did not put the prompt into the head's attention history (training always sees every earlier token), so attention effectively forgot the prompt. With the prompt fed in, greedy text at 10225 went from Once upon a timeer ack ack ack ... to Once upon a time, there was a girl smiled ., and with a photo on the eyes A dog runs in the skateboard . (sampled). Generation now prints greedy and sampled text (temperature 0.7, top-k 40, repetition penalty 1.3).

Where the time goes (CPU profile of one step, full setup, logs/profile_cpu_step10225.json): backward pass 49.8%, brain ticks forward 40.6%, text data 4.1%, optimizer 2.8%, DINO 1.1%, Daisy 0.5%, head + attention + decoder 0.1%. On the logged runs a step went from 3.24 s to 3.99 s as the spike cap rose 200 -> 400. The brain simulation is the whole cost.

Steps 11921 - 14580: SmolLM2 judge, looped decoder, HRM, JEPA, MTP, and a cheaper step

Added on copies (vision/train_anatomy_vision_v3.py, _v4.py). Older scripts left alone. Each new part starts at exactly zero effect so a checkpoint resumes unchanged.

A second teacher that judges, and tastes. HuggingFaceTB/SmolLM2-360M scores the fly's own continuations (8 text prompts per step, 24 new tokens): reward = mean log p(continuation | prompt) + 2.0 x (share of distinct tokens - 1). The second term is because a judge finds ack ack ack very predictable. Reward prediction error (reward minus a running mean, over its running std) drives the fly's PAM dopamine cells when better than expected and PPL1 when worse, and at the same time the sugar-like taste neurons (reward) or bitter-like ones (punishment), while the fly's own words are replayed. Three-factor rule then changes the 2.6M synapses onto dopamine-receiving cells. Daisy-Base still teaches the full next-token distribution next to it (different tokenizer, so SmolLM2 can only judge whole sentences).

Byrne pieces in the head (from Byrne70M-GatedFlow-HRM-JEPA): a looped decoder (the 4 blocks run 3x with shared weights, per-pass embeddings, zero-init gate per extra pass), HRM refinement with deep supervision, MTP (predict the token after next), and JEPA on the fly's own brain state (predict the next token's read-cell activity).

Two of those were dead on arrival. I measured the gradients and fixed them:

symptomcausefix
loop gatesstuck at +-0.006, both passes identicalper-pass embeddings zero behind zero gates: both ends of one product at zero, so neither could move (the same trap Byrne's HRM note describes)random per-pass embeddings (still a no-op at step 0 thanks to the zero gate), 10x learning rate for the gates
JEPAloss 0.0065 and flat, gradient ~3e-4consecutive brain states are ~98% alike, so "predict the next state" was "copy this one", best minimised by making the brain uniformpredict what is NEW: both sides minus the sequence mean. Loss 0.58 - 0.64, gradient ~0.12 (400x)

Also added: document masking in the packed 256-token text (attention and JEPA stay inside one document; the brain itself runs on, as a fly's does) and 256-token text windows for the rehearsal half (captions stay at 48), so the head's attention sees multi-sentence context instead of 1-2 sentences.

Throughput. Benchmark (analysis/ + logs/profile_cpu_step10225.json): batch 16 -> 64 gives 1.75x more text per hour and saturates there (128 gives no more). Brain ticks are 72% of a step. Census of 40 real batches: 129,273 of 167,565 neurons (77%) never spiked, and 100,962 of them never rose above half of their threshold and are not read / visual-output / eye / Kenyon / dopamine / taste cells. Skip the synapses into those (10.1M of 25.6M kept, 39%): captions bit-identical (CE 2.93761 vs 2.93762), ~43% less brain work. Every 500 steps one batch runs through the FULL brain so anything that wakes up rejoins (530 rejoined in the first refresh). Batch 64 + the cut + background text loading: a step went 15.5 s -> 34.4 s for 4x the text. ~1.8x more tokens per hour.

DEER does not work here (analysis/deer_test.py). Parallel-in-time solving (Lim et al. 2023, quasi-DEER with per-neuron scans) reproduces the sequential trajectory exactly, but needs 57 iterations for 64 ticks. Spikes are discrete, so correct information spreads only ~1 tick per iteration. ~50x slower than just running the ticks. Parallel hardware does not rescue it: each iteration still has a full sequential scan.

Results over the leg (steps 11921 - 14580, ~2,700 steps):

11921 - 12669v4 (14261 - 14580, batch 64 + cut)
text CE4.043.30 (256-token windows)
gap to Daisy (KL)2.021.92
image_gain+0.079+0.114, positive on 100% of saves
brain_gain5.76.7
held-out caption CE~3.23.25
MTP--5.89
loop gates00.031 / 0.009 (open, and the passes differ)
judge reward---5.9, token variety 0.91

grad_norm spikes to 200 - 1600 on some steps. Measured: w_grad ~1.0 on those steps (the synapses, not the new head parts). Caption half. Happens with the neuron cut ON and OFF alike (67.5 vs 64.6 on the same step). Particular caption batches, not the cut or the batch size. Clipped. No skipped steps.

Interruptions. v4 leg interrupted three times (restarts from 14260, 14452, 14580). Each lost up to 20 steps plus startup.

The newest fly: step 14580

step 12040step 14260step 14580
test-sentence CE3.182.792.76
"Once upon a time" (greedy), there was a little girl named ". She sat, "I'm wa, there was a little girl named Sally. He loved to play with her, there was a little girl who loved to play with her mommy and daddy. S
green image captionA dog runnings through a green grasssA girl in a grass .A girl of a yellow field .

Frozen the same way (30 simulated days as a fly, trained synapses frozen): brain responding to sugar 2.6% -> 4.1%, sugar -> MN9 217 -> 177 Hz, bitter 0 Hz throughout, untouched synapses changed 17.9%, and language exactly unchanged (CE 2.7627 before and after, identical text and captions). MaleCNS edge table round-trips exactly (max difference 0.0; 52.9% of edges changed from the original fly, 0 sign flips). checkpoints/vision_v4_step14580_frozen_day30.pt.

Put back in the body at 14580: sugar still works. Bitter is gone. Original fly: bitter-like taste -> MN9 21 Hz. This checkpoint: 0 Hz. Sugar still drives the proboscis. The aversive arm of the feeding circuit did not survive this far. (Bitter -> MN9 was already 0 Hz on every trained brain from 2948 on, including 12040. Original 21 Hz leak never came back.)


What training changed in the fly (analyses on steps 2948 / 3440)

Where the weights moved (analysis/delta_map.py, trained minus connectome, by presynaptic transmitter and pathway). Training hit the neuromodulators hardest:

presynapticsynapses changedof those, sign flippedshare of all change
octopamine99.6%73%8.9%
serotonin82%72%--
dopamine44%53%--

Visual centrifugal -> optic lobe: 71% changed, 14.8% of all change. Kenyon -> Kenyon: 45.5% changed at 2948, 56.6% at 3440.

Could a local rule explain it? (analysis/local_rule_fit.py) Presynaptic firing rate alone predicts how much a synapse moved (held-out R^2 0.33, Spearman 0.65). Adding Hebbian co-firing barely helps (R^2 0.35). 61% of changed synapses grew. The pre factor is local. The post factor (the credit) is not Hebbian.

Could the modulatory neurons deliver the credit? (analysis/credit_signal_test.py) Cells that receive dopamine / octopamine / serotonin input hold 98.8% of all credit (dLoss / d membrane), so the coverage is there. Moment-to-moment modulatory input does not track it (within-cell r -0.06, vs -0.11 for matched cholinergic input and -0.03 for a time-shuffled null; signed r 0.001).

Mushroom body test (analysis/mushroom_body_test.py). Connectome mushroom body is complete: 4,064 Kenyon cells, 97 MBONs (37 types), 340 DANs (PAM / PPL1 / PPL2), 61,210 Kenyon -> MBON synapses, every MBON has a direct DAN input (textbook pairings recovered, e.g. PPL1-gamma1pedc -> MBON11). Only Kenyon -> MBON synapses learn. Odour-conditioning task (64 tokens presented alone as "odours", random valence; frozen step-2948 brain; 5 seeds; held-out accuracy, majority class 0.58):

learning ruleaccuracy
none0.47
backprop0.71
dopamine, one teacher per MBON0.69
dopamine through the real DAN -> MBON wiring0.67
one global reward (reward-prediction error x node noise)0.64
backprop + dopamine (real wiring)0.675
backprop + global reward0.675

Every dopamine rule learns, ordered by how precise the teaching signal is. None beats backprop. Adding dopamine to backprop made it worse. Cheaper, blurrier route to the same credit - useful for learning without backprop, not as an add-on to it. (Harder in-context version of the task: nothing, not even an unconstrained readout, beat the majority class.)


Back to the original connectome format

export_to_malecns.py inverts the MaleCNS -> SpikeWhale conversion (W = sign(transmitter) x synapse count x 0.01) and writes a flat edge table in MaleCNS terms: body_pre, body_post, weight (effective synapse count) plus the original count and both signs. Untouched artifact round-trips exactly (0 of 25,623,478 edges differ; 124,174,455 synapses). At step 5160: 34.9% of edges changed, 564,241 trained to zero, 0 sign flips (Dale on), ~143.7M effective synapses (+16%); counts are no longer whole numbers. Converting that table back into the SNN reproduces the step-5160 weights exactly (max difference 0.0) and identical generations. Neuron-class parameters (threshold, leak, input gain), the language head, and the eye settings have no MaleCNS equivalent. They stay in the training checkpoint.


The trained brain as a fly again (repair tests)

Once the connectome has learned language, does it still work as a fly? If it lives as a fly again, learning only with biological rules, can the untouched biology repair the trained parts?

Simulation. Whole-brain leaky integrate-and-fire in the style of the community models (Shiu et al. 2024, Nature): dt 1 ms, v_rest / v_reset -52 mV, threshold -45 mV, tau_m 20 ms, tau_syn 5 ms, 2 ms refractory, 0.275 mV per synapse (signed by transmitter), taste neurons driven with 150 Hz Poisson spikes. Every brain gets the same neuron model; only the synapses differ (no language head, no trained per-class gains, no spike cap). analysis/fly_circuit_test.py, analysis/fly_repair_sim.py.

Taste groups. MaleCNS labellar taste neurons carry no receptor labels (types LB1a - LB4b), so the groups come from the original wiring: labellar types that excite the proboscis motor neuron MN9 within three synapses are the appetitive (sugar-like) group, LB2b, LB3a-d, LB4b (86 cells); those that inhibit it are the aversive (bitter-like) group, LB1c, LB2a, LB2c (26 cells).

Stage 1: the feeding reflex after training

MN9 firing, 1 s, 4 trials (logs/fly_circuit_sugar_mn9.json):

brainsynapses changedno stimulussugar-like -> MN9bitter-like -> MN9brain active (sugar)
original connectome0%0 Hz222 Hz21 Hz13.8%
step 2948 (language)22.1%0 Hz228 Hz0 Hz3.6%
step 3440 (language, cap 600)22.6%0 Hz231 Hz0 Hz3.5%
step 5920 (vision + language, Dale)26.5%0 Hz225 Hz0 Hz3.9%
step 10225 (vision + language, Dale)29.4%0 Hz236 Hz0 Hz3.0%

The original validates the model: sugar-like taste drives the proboscis strongly, bitter-like barely. Sugar survives. Bitter does not. The small bitter leak into MN9 is gone in every trained brain (21 Hz -> 0 Hz). Taste responses spread through far less of the brain (13.8% -> 3 - 4% of cells): activity reaches its target without spilling, matching the training's biggest changes (to the widely broadcasting neuromodulator synapses).

Stage 2: 30 simulated days of repair

The step-2948 brain lives through "days": each day sugar-like taste, bitter-like taste, and two fixed sets of other sensory neurons (150 ms each). After each day every neuron applies homeostatic synaptic scaling: excitatory input synapses scale up if it fired below its set point, down if above. Signs never change. Set points are the original connectome's firing rates for the same experiences - the untouched biology is what pulls the brain back. Language CE is measured with the step-2948 head on 4 fixed FineWeb-Edu batches (original synapses 9.25, trained 4.99).

rulebrain active (sugar), day 0 -> 15 -> 30sugar -> MN9, day 30trained synapses' distance from the original, day 30language CE, day 15 / 30
unbounded scaling (eta 0.2)3.4% -> 8.1% -> 10.5%67 Hz26x (still growing)-- / 110.5
bounded scaling (eta 0.05, each synapse within 0.5 - 2x of day 0)3.4% -> 5.5% -> 6.0%190 Hz1.29x (settled)5.75 / 6.04
bounded, trained synapses frozen (only the 78% training never touched adapt)3.4% -> 5.2% -> 5.8%190 Hz1.0x (frozen)4.99 / 4.99

Controls: original brain under the unbounded rule stays stable for 30 days (12.1 - 13.1% active, MN9 187 - 207 Hz), so the rule itself does not damage a healthy brain. Trained brain without plasticity does not change.

  • Activity comes back. The synapses do not. Under every rule the trained brain's response spread moves back towards the original's. Only ~7 - 10% of the trained synapses move back towards their original values. Neurons that training had quietened scale up their other inputs instead. The brain finds a different wiring with similar activity (degeneracy) rather than undoing the training.
  • Unbounded, that compensation runs away and destroys both the reflex (MN9 67 Hz) and the language (CE 110.5, far worse than chance).
  • Bounded, it settles (activity doubles, reflex intact) but still slowly erodes the language, because the language synapses are rewritten too.
  • With the trained synapses frozen, the rest of the fly adapts around them. Activity recovers almost as much (3.4% -> 5.8%), the reflex holds, and language CE does not move at all (4.9852 on every day), although the untouched synapses changed by 15% on average. The synapses training never touched are exactly those whose presynaptic cells are silent during language (the trainer only changes a synapse when its presynaptic cell fires). Original biology can rewire all of them without touching what was learned.

Day 15 of the bounded run, converted to MaleCNS and back. export_to_malecns.py -> MaleCNS edge table (38.8% of edges changed from the original fly) -> rebuilt by body IDs -> identical to the day-15 brain (max difference 0.0). Its 1,090,918 sign flips are the ones step 2948 already had from before Dale's law was switched on. Generations at spike cap 80 (logs/generate_repair_bounded_day15_from_malecns.log; baseline logs/generate_step2948_baseline_for_repair.log):

                      DAY 15 (repaired, round-tripped)       STEP 2948 (no repair)
The                   The the the the the the the |          The to the |----------
Once upon a time      Once upon a time the |-------           Once upon a times.
The fruit fly brain   The fruit fly brains.                   The fruit fly brain.

Both are the weak early step-2948 language model. Day 15 is slightly more repetitive, in line with its higher CE (5.75 vs 4.99). The frozen run's language CE equals step 2948 exactly, so its text would be the same.

The same tests on step 12040 (vision + language + dopamine, Dale on)

Stage 1 (logs/fly_circuit_sugar_mn9_step12040.json): 37.2% of synapses changed; sugar -> MN9 235 Hz (original 222), bitter -> MN9 0 Hz, 2.7% of the brain responding (original 13.8%). Sugar still works after more training. Bitter is already gone.

Stage 2, 30 days (brain responding to sugar, day 0 -> 15 -> 30; sugar -> MN9 at day 30), with language and captions measured in the full vision model (decoder and eye included) on six fixed test sentences and a green test image:

rulestep 2948step 12040step-12040 language CE, day 30step-12040 greedy, day 30
no repair--2.6%4.439Once upon a time of a large green a black down a sit in a snow
unbounded3.4 -> 8.1 -> 10.5%, 67 Hz2.6 -> 10.3 -> 12.0%, 63 Hz7.078Once upon a timeongferferacferacferongong...
bounded3.4 -> 5.5 -> 6.0%, 190 Hz2.6 -> 7.4 -> 7.5%, 207 Hz6.578Once upon a timewoAAAAAAAngAAAAAAAngAAA
frozen trained synapses3.4 -> 5.2 -> 5.8%, 190 Hz2.6 -> 3.6 -> 4.3%, 187 Hz4.439 (identical)identical to no repair
  • Unbounded repair now brings activity all the way back to the original fly's level (12.0%), but the reflex collapses and the language turns into letter loops.
  • Bounded repair keeps the reflex (207 Hz) and moves the trained synapses little (1.06x), yet still breaks the language.
  • Frozen: the fly's untouched 63% adapted for 30 days (mean change 17.6%) while language, the green-image caption (A dog runnings through a green grasss) and the reflex stayed exactly the same. It recovers less activity than at step 2948 (4.3% vs 5.8%) because 37% of the brain is now frozen instead of 22%. This frozen fly (checkpoints/vision_v2_step12040_frozen_day30.pt) is the one the Space runs.

The same tests on step 14580 (the newest fly)

Frozen and unbounded, the two ends of the range, on the newest checkpoint (logs/fly_repair_frozen_step14580.*, logs/fly_repair_unbounded_step14580.*, logs/fly_repair_unbounded_step14580_language.json). 39.6% of synapses changed by training; set point 17.2% of cells active.

brain active (sugar), day 0 -> 15 -> 30sugar -> MN9, day 30bitter -> MN9trained synapses' distance from the originaltest-sentence CE, day 30
no repair2.6%217 Hz0 Hz1.0x2.7627
unbounded scaling (eta 0.2)2.6 -> 10.1 -> 12.0%157 Hz3 Hz1.18x6.61
frozen trained synapses2.6 -> ~3.5 -> 4.1%177 Hz0 Hz1.0x (frozen)2.7627 (identical)
  • Unbounded repair brings the brain all the way back to the original fly's activity (12.0%, original ~12.5%), and at 14580 it does not wreck the reflex the way it did at 12040 (157 Hz here vs 63 Hz there) - the trained synapses drift only 1.18x from the original, against 26x on the step-2948 brain. More training left the brain closer to something the homeostatic rule is happy with.
  • It still destroys the language: CE 2.76 -> 6.61, and greedy text falls apart (, there was a little girl who loved to play with her mommy and da -> 't wastret thikingstgle tot STNARERSTCO). Activity being right is not the same as the language being right.
  • Frozen is still the only arm that keeps both. The untouched 60% of the fly adapts for 30 days (17.9% mean change), the reflex holds, and the language is bit-identical.

Limits. One circuit family (taste -> proboscis) measured closely. Taste groups inferred from wiring. Synapses only (no per-class neuron parameters). Simulated spike rates run high (compare brains, not absolute Hz). Homeostatic scaling is the only rule tried in stage 2 (a dopamine-reward version during the fly's life is not yet tested).


What went wrong

  1. Opening the eye to full strength flooded the head (174 of its 256 hub cells are optic-lobe cells) and caused the gradient explosions.

  2. A single rolling checkpoint lost the good vision states. Numbered checkpoints now.

  3. Wrong-image hinge loss stopped caption learning for ~1,700 steps.

  4. The fly's own vision pathway to the central brain is almost silent, so the image never reaches the language circuits through the route the fly uses. Neither attention nor a DINO teacher on those outputs made the head use the image in 900 steps.

  5. A bfloat16 teacher cast broke Daisy-Base's n-gram hashing on the first step of one launch (fixed: the teacher stays float32).

  6. Visual tokens for the head's cross-attention were read from the wrong cells (the head's own input cells, 99.8% identical across images) instead of the optic-lobe outputs the DINO teacher trained. ~4,700 steps of vision training could not use the image through them. Fixed: tokens now come from the visual projection neurons.

  7. Greedy text at step 10225 loops (ack ack ack) and breaks on plain prompts, even though text CE with the Daisy teacher is 4.36 - 4.5. The teacher narrowed the distribution gap. It did not fix degenerate greedy decoding.

  8. Much of the ack ack ack was a generation bug: the prompt was never put into the head's attention history. Fixed. With it, greedy text at 10225 reads Once upon a time, there was a girl smiled ..

  9. Two of the Byrne additions were dead on arrival: the loop gates sat at +-0.006 (zero per-pass embeddings behind zero gates) and JEPA had loss 0.0065 (consecutive brain states are ~98% alike, so "predict the next state" was "copy this one"). Both only showed up when the gradients were measured, ~700 steps in.

  10. The run was interrupted three times by the compute being revoked (restarts from 14260, 14452, 14580), each losing up to 20 steps plus startup. That is what ended the run at 14580 rather than a chosen stopping point.

How it ended. The dopamine "looking" reward was the first thing that kept image_gain consistently above zero. That is measured. A scramble is not the missing piece. The leftover split is eye coupling 0.85 with dopamine off, if anyone wants it. The SmolLM2 judge, the looped decoder and JEPA (after the zero-gradient traps were fixed) plus the 39% synapse cut took text CE to 3.30 and test-sentence CE to 2.76 by step 14580. The Daisy KL gap (1.92) was still closing when the run stopped.


Connectome (this graph)

Wiring is MaleCNS v1.0 from FlyEM (HHMI Janelia), the University of Cambridge, the MRC LMB, and Google Research. Hugging Face Papers only auto-tags arXiv IDs. This paper is in Cell, so the Hub will not grow an arxiv: chip.

JournalBerg et al., Sexual dimorphism in the complete Drosophila male central nervous system connectome, Cell 189(18):5504-5526.e15 (3 Sep 2026). DOI 10.1016/j.cell.2026.08.015
Cell / ScienceDirectS0092-8674(26)00942-6
PubMedPMID 42691995
PreprintbioRxiv 10.1101/2025.10.09.680999
Google Research articleA connectomics milestone: mapping the complete male fruit fly brain (3 Sep 2026)
JaneliaMale CNS Connectome · data male-cns.janelia.org
Hub packaging of the same tablesQuixiAI/MaleCNS

Connectome data: CC-BY 4.0.


Architecture (language checkpoint)

token id
  -> embed (64)
  -> current on: 5 sensory-group winners + top-32 of 256 highest-out-degree cells (drive 0.8)
  -> 4 LIF ticks, hold current, rec = (W @ spikes) / sqrt(in_degree) * rec_scale(5)
  -> Kenyon spikes re-enter W (mask_kenyon=false); spike-mass cap 80
  -> tanh(pre-reset)[Kenyon U hubs] -> LayerNorm -> Linear 128 -> vocab 16512
  • kc_drive = 0. NT gains frozen. Trainable: sparse W, embed, hub_in, head.
  • Optimizer: MuonEq-R on 2D except out; AdamW on 1D / embed / out. Peak Adam 1e-3, Muon 5e-3.
  • Data, language-only phase (steps 0 - 3440): 40% FineWeb-Edu / 40% DCLM / 20% IFM (pretraining_config.json; 9 streams - the IFM share is 7 behavior configs at 0.0286 each). From step 2949 (the vision run) the text mix changed to 40% FineWeb-Edu / 40% TinyStories / 20% FinePhrase (faq, tutorial, math, table at 5% each; vision/text_sources_vision.json), replacing DCLM and IFM: short narrative text to rehearse against Flickr8k captions. Everything from 2949 to 14580 used that mix.
  • Tokenizer: SpikeWhale byte-level length-max, vocab 16512.
  • code/sparse_mm_fire.py: fire-only forward (scatter firing cells); d_spikes = W^T @ gout via cuSPARSE (exact LIF). Config checkpoint_every: 0 = no activation checkpoint (full tape).

Language training status

Everything in this section is the language-only phase (steps 0 - 3440), before the eyes were opened. It ends at step 3440; the run that continues to 14580 starts from step 2948 and is described under Vision training above. The tables are kept because they are where the spike cap, coverage and Dale numbers were measured.

Step 3440 (last language-only step) / 3180 - spike-cap ramp

Seq 512 x batch 16 x accum 1 (8192 tokens/step, packed, FineWeb-Edu only), max_spikes ramped 400 -> 500 (step 3281) -> 600 (step 3381). 260 steps, ~2.13M tokens. Every log line now records coverage: which cells have ever fired, and therefore which synapses have ever been reachable by gradient (seeded from what earlier runs had already changed).

at resume (3180)step 3440
Cap400600
Whole-network activity (rate_all)0.00600.0085
w_grad~0.120.163
Cells that have ever fired18.79%18.90%
Synapses ever trainable22.56%22.64%
Train CE (last logged steps)--~4.77, same band

The ramp raised intensity, not reach. The same ~31k cells fired harder; almost no new cells were recruited (+0.08 points of synapse coverage in 260 steps). Text enters through a fixed set of entry points, and it does not reach most of the fly -- above all the visual system. No aborts, no skipped saves.

Step 2855 (seq-2048 continuation)

Runreal_seq2048_b4 (resumed from step 2500)
Steps2500 -> 2855 (350 logged)
Tokens this leg~2.87M (2048 x batch 4 x accum 1 = 8192 tokens/step, no padding)
Tokens total~5.43M
Train CElogged-window mean 4.88 -> 4.82; final single step 4.635. That move is inside the per-step noise band (sd ~ 0.25-0.4) - read it as flat, not as progress.
Readout spike rate0.0202 -> 0.0245, still climbing monotonically (~0.0065 at step 1000)
Step time~30 s median (checkpoint_every: 8)
Data windowsdocuments packed contiguously (eos-separated) instead of one document per window. At seq 2048 ~97% of FineWeb-Edu docs are shorter than the window, so single-doc windows were ~82% pad - and pad costs full LIF compute before ignore_index masks it out.
Optimizerunchanged; moments restart cold on every resume, so CE jumps at the first step after a resume (4.78 -> ~5.1)

Nothing latched and nothing broke. 350 steps at 8x the tokens per step did not move CE out of the band that 1500-2500 already sat in.

Step 2500 (seq 256)

Runreal_seq256_hubs
Step2500 / 50000 (paused)
Train CE4.780 (best logged 3.962 at step 2396; last-50 mean ~4.84)
Tokens seen2,560,000 (seq 256 x batch 2 x accum 2)
Readout spike rate~2.0% at 2500 (was ~0.65% at 1k)
w_gradlive (~0.06-0.10)
Seq / batch256 tokens, batch 2 x accum 2
Ticks / token4, current held all ticks
Step time~75 s (full CSR) -> ~28-32 s (fire-only forward + cuSPARSE d_spikes + ckpt 32) -> ~24 s with checkpointing off (~7.2 GB). Triton fused backward was ~110 s (reverted).

Kenyon/readout did not latch. Language did not leave the weak-unigram / broken-English band. 1.5k extra steps after 1000 moved CE 4.89 -> 4.78. That is not a ceiling proof; it is also not a generation win.


What actually trains

Gradient reaches a synapse only if its presynaptic cell fired (sparse_mm_fire.py computes grad_values for active presynaptic cells only). Measured against the conversion weights at step 2948:

Synapses ever updated5,655,315 / 25,623,478 (22.1%)
Presynaptic cells with any updated edge30,835 (18.4%)
Mean update size on those edges0.0607
Mean magnitude of the original weights0.0485
Correlation, trained vs original W0.896

~78% of the "trainable" synapses have never received a gradient. The edges that did move changed by more than their own original magnitude.

Instantaneous participation is far lower than cumulative. Counting spikes per neuron over a 128-token window (logs/participation_2500_vs_2855.json):

step 2500step 2855
Neurons that ever fire in the window2,474 (1.48%)2,578 (1.54%)
Share of all spikes in the read cells34.3%39.5%
Share of all spikes in the top-100 neurons38.2%37.4%

~1.5% of the connectome is active at any moment, and the spike mass concentrates further into the readout population as training goes on. The effective model is a ~2.5k-neuron subnetwork inside a 167,565-neuron graph.

This is not a reachability limit. From the sensory + hub injection sites, one synaptic hop already reaches 159,113 neurons (95%), and 165,378 (98.7%) are both drivable and able to influence the readout within the 4 ticks. The graph is small-world; the sparsity is dynamics, not wiring.


Spike-mass cap: what pins participation

GradThroughSNN.step rescales every spike by min(1, max_spikes / mass). With ~268 cells firing and max_spikes: 80, the scale is ~0.30 and total spike mass is pinned: recruitment is zero-sum, because a newly firing cell dilutes the ones already carrying signal. Ramping the cap (logs/spike_cap_experiment.json):

max_spikesrate_allreadout rateneurons firingw_gradlogit_rms
800.001610.0264300.06-0.0811.1
4000.005790.1791,2790.13-0.1610.1-11.8
20000.013710.4612,4400.46339.1 -> aborted

The cap was the binding constraint. 80 -> 400 tripled the number of firing neurons, raised whole-network activity 3.6x and doubled the gradient reaching W, at stable logit_rms. 2000 broke training outright: grad_norm 2.4 -> 48.3, CE above uniform. Note 0.461 is close to the 0.45 where failure mode 2 lives.

What it did not buy: CE. Over 150 steps at cap 400 the mean went 5.017 -> 4.939 (best single step 4.468) - back into the pre-cap plateau band, not below it. More of the network participates and more synapses receive gradient; that has not yet become better prediction.


Dale's law and the exported connectome

Training is free to flip a synapse's sign, which makes the graph no longer neurotransmitter-consistent. By step 2948, 1,090,918 synapses had flipped sign (19.3% of the edges that changed, 4.3% of all edges).

export_trained_brain.py recombines a trained checkpoint's synapse vector with the frozen artifact's wiring and writes a plain connectome SNN - same neurons, same edges, same identity matrix, trained synapses, no language-model parts - loadable by ConnectomeSNN.load():

python export_trained_brain.py \
  --ckpt <trained_checkpoint>.pt \
  --out male_cns_spikewhale_trained.pt          # add --dale for the constrained one

--dale clamps every synapse back onto the sign its neurotransmitter gave it (violating ones go to 0), so the exported brain stays Dale-compliant. The trainer also takes dale_constraint: true, which re-projects after every optimizer step. Language-only training had not used that yet. The vision legs from 2948 ran with it on.

as-trainedDale-projected
Synapses zeroed to restore signs01,090,918
Spikes from a 256-cell pulse, 8 ticks12,94514,819

The constrained brain fires more, because zeroing sign-violating synapses removes inhibition that training created by flipping excitatory synapses negative.

Both exports still drive language when paired with the step-2948 head. Greedy, 32 new tokens, same prompts, same decode:

                  AS-TRAINED (0 zeroed)                DALE-PROJECTED (1,090,918 zeroed)
The               The to the |-------------            The therect then them to bet is again,
                                                       them therect then, them to there is after

Once upon a time  Once upon a times.                   Once upon a times, therecting then then
                  (blank lines to the limit)           then thenks.

The fruit fly     The fruit fly brain.                 The fruit fly brain, then then them to
brain             (blank lines to the limit)           because the |------------------

Greedy on the as-trained brain collapses into whitespace or dashes within a few tokens on all three prompts; the Dale-projected one keeps emitting word-shaped tokens for the full 32. Neither is English.

That is not the constrained brain modelling language better. On identical batches (logs/dale_vs_astrained_eval.json):

as-trainedDale-projected
CE4.8755.095 (+0.22, ~4.5% worse)
Readout rate under language input0.02520.0204
logit_rms10.9414.71
Distinct-token ratio (greedy)0.1760.319
Filler chars (whitespace / dashes)0.7630.469

Projection costs 0.22 nats of prediction. What improves is greedy degeneracy only - 1.8x more distinct tokens, far less filler - which is a decoding artifact, not accuracy. Under real language input the constrained brain fires less, not more, so the pulse test above does not explain the generations: an earlier "more excitable" reading of this was wrong.

The likelier mechanism: the head spent 2,948 steps fitting one feature distribution and learned a strong period-then-whitespace attractor; any large perturbation of W knocks the features off that memorised point, breaking the attractor while also hurting accuracy. The control that would settle it - zeroing 1,090,918 randomly chosen synapses of matched magnitude - has not been run.

Sampled (T=0.8, top-k 50) from the Dale-projected brain:

Once upon a time thems are really, and the reven anly to a back that the said, deal, a cleanks i
The fruit fly brain is then a lonk-sing but themss to bet it was bet is a site wasn in if you

The head was trained against unconstrained weights, so all of this measures how a head copes with a brain that shifted under it - not the quality of a model trained with the constraint on. The trainer supports that (dale_constraint); it has not been run. Full text: logs/generate_connectome_step2948.log.

What survives as a result: removing every Dale-violating learned update costs only 0.22 nats. The sign-illegal part of what training learned is real, but small.

At step 3440 that no longer holds. Same projection, same protocol (identical batches, each model at its own training cap -- 600 here), logs/dale_vs_astrained_eval_step3440.json:

step 2948step 3440
Synapses changed from the connectome22.07%22.64%
Sign-violating synapses zeroed1,090,9181,115,852
CE, as-trained4.8754.80
CE, Dale-projected5.0956.50
Cost of Dale+0.22+1.70
logit_rms, Dale-projected14.722.6
Spikes from a 256-cell pulse (as-trained / Dale)12,945 / 14,81913,139 / 15,061

After the spike-cap leg the model depends far more on its sign-flipped synapses. Two readings fit and this data cannot separate them: training at caps 400-600 built more dependence on those synapses, or the higher cap the model runs at amplifies the same perturbation. Step-3440 Dale-projected brain also generates visibly worse (next section). The less-degenerate greedy output at 2948 did not survive.


W ablation (steps 1000 and 2855)

Same 4 batches. Not a trained scramble control. Not re-run at 2500. File logs/eval_w_ablation_step2855.json is in the repo.

conditionCE
trained W5.07
shuffle values16.3
sign-flip10.7
conversion W + trained head6.63
rec_scale=033.7

Trained synapses are used at eval.

Step 2855 (same protocol as step 1000: seq 256, batch 2, 4 batches; logs/eval_w_ablation_step2855.json):

conditionCE
trained W5.00
shuffle values26.96
random signs21.82
conversion W + trained head21.53
rec_scale=090.37

Every corruption costs more than at step 1000 (shuffle 16.3 -> 27.0, signs 10.7 -> 21.8, conversion W 6.63 -> 21.53, rec_scale=0 33.7 -> 90.4). The head specialised to the trained synapses. All ablations also cut the spike rate ~7x (0.024 -> ~0.0035), so part of the damage is the network going quiet, not only lost information.


Generations (still not good)

Oldest first; the last block is the current fly. Everything up to step 3440 is the language-only phase, read with that phase's head.

Step 14580 (current, greedy)

Once upon a time, there was a little girl who loved to play with her mommy and daddy. S
The little girl saw a big red ball on the grass and it was very happy. She wanted to go home, but she didn'
green test image                        A girl of a yellow field .

Test-sentence CE 2.76. Still fragments, still confuses he / she, captions still do not tell two photos apart. Earlier claims of degenerate text at 12040 / 14260 came from a generate-path bug (grey-field visual tokens attached to plain text); the same brains, run the way they were trained, read as above.

Step 2855

Greedy no longer stutters single words. It repeats a clause instead. Two of the five prompts collapse straight into dash / asterisk runs. Sampled text is word-shaped fragments, not English.

PROMPT: The
GREEDY: The, then the "It is the "It is again, the "It is after the "It is after the
SAMPLE: The) and a looking, and graphructs
Socing. Opt-Put, and we'p the entibolor, somethip

PROMPT: Once upon a time
GREEDY: Once upon a times, there are the "It is after the "It is aftly the -derstand and there is a s

PROMPT: In 2020, scientists discovered
GREEDY: In 2020, scientists discovered, the |------------------------------

Against step 2500: the the the and there is there is are gone, and are now agrees after a plural - a longer repeated unit, not a working sentence. Full log: logs/generate_step2855.log.

Step 2500

Greedy still latches. Sampled is slightly more word-like than 1k, still not English.

PROMPT: Once upon a time
GREEDY: Once upon a times, there is the | |---...
SAMPLE: Once upon a time about Artue. It work. ...

PROMPT: The fruit fly brain
GREEDY: The fruit fly brain, there is there is the |---...

Full log: logs/generate_step2500.log. Compare logs/generate_step1000.log.

Step 3440, as-trained vs Dale-projected

Exported brains (export_trained_brain.py) driven by the step-3440 head at spike cap 600. Greedy, 32 new tokens:

                     AS-TRAINED                                  DALE-PROJECTED (1,115,852 zeroed)
The                  The the "The. / The. / The. / The. ...      The to bet thenk...........nnn, epts. �sed to
Once upon a time     Once upon a times, the "It is there are      Once upon a times, �sedn, �sed. �sed to
                     there are the "The. / The. ...              thenn, �sedn the
The fruit fly brain  The fruit fly brains, there are the "It is  The fruit fly brains, �sed. �sed...........
                     after the "It is there are there are there

As-trained still latches. The repeated clause of step 2855 is back, plus a new The. line loop. Dale-projected now emits broken-byte tokens and dot runs: worse, consistent with its +1.70 CE. Full text: logs/generate_connectome_step3440.log.


What this does show

It can learn something. CE 9.71 -> ~4.8 by 2.56M tokens. w_grad live. Rate in band. Step-1000 ablation: destroying W wrecks CE.

Raising the spike cap engages more of the graph but has not moved CE. Cap 400 triples the firing population and doubles w_grad; 150 steps there ended at CE 4.94, inside the same band. The 3180-3440 ramp raised intensity, not reach.

Then it stops. From step ~1500 through 2855 - across an 8x sequence-length change, an 8x tokens-per-step change, and a switch to padding-free packing - CE sits at 4.8-4.9. A fit over 1500-2500 gives -0.0009 CE per 100 steps: flat. Whatever caps this is not step count and not batch size.

That learning is weak language. Greedy at 2500 is still degenerate. Last-50 mean CE ~4.84. Best single batch 3.96 is noise, not a 4-break (need a 100-step mean). 2.56M tokens is a probe, not a pretrain.

Most of the visual system never sees language training. 62% of the CNS. ~6% of optic-lobe cells ever trained. Joint vision (2949-14580): Flickr phrasing first, then VPN tokens + decoder + dopamine, then SmolLM2 judge + looped decoder. image_gain +0.114 on v4, positive on 100% of saves. Still not two-photo-distinct captions. Generate-path used to attach grey-field visual tokens to plain text; that was a bug, not the model.

Sugar survives. Bitter does not. Sugar -> MN9 still fires after language and vision training. Put back in the body at 14580, bitter -> MN9 is 0 Hz (original 21 Hz). Freeze the trained synapses and 30 simulated days of homeostatic scaling recover activity without moving language CE.

  • Shows: sparse MaleCNS + SpikeWhale LIF accepts gradient and beats chance. Untrained optic lobe has a small motion/parallax signal. Daisy KL gap can close. VPNs can match DINO (~0.37). PAM/PPL1 looking-reward is when image_gain left noise and stayed there (table: ~0 then +0.047 then +0.114). That is measured on this brain. A scramble is not required to read it. Skipping never-spiking cells (39% of synapses kept) leaves captions bit-identical. Sugar -> MN9 survives. Bitter -> MN9 does not (0 Hz at 14580 in the body; original 21 Hz). Frozen trained synapses + homeostatic rest-of-fly does not erase language. Step 14580 test-sentence CE 2.76.
  • Does not show: more steps => fluent text, two-photo-distinct captions, that any random 316+16 cells would match PAM/PPL1, fly-as-attention helping a transformer, looming, unbounded scaling as a safe "repair", a preserved bitter/aversive feeding arm at 14580, or dopamine vs eye-coupling 0.85 with dopamine off (that split was not run).

Known failure modes (already hit)

  1. 1 tick/token: sensory atlas does not reach Kenyon. Anatomy is multi-hop.
  2. Seq 512 + strong rec: Kenyon clique latches.
  3. 1.1 current on Kenyon: greedy the the the.
  4. Muon 0.02 on out: logit blowup.
  5. Fly graph as attention (prefix-sum + hub CSR instead of MHA): ~50M Byrne-looped GPT, ~120M tokens, CE stuck ~6.4. Not this checkpoint.
  6. Triton per-neuron d_spikes: ~110 s/step vs ~75 s cuSPARSE. Reverted; fire-only is forward only.
  7. Long windows with one document per window: at seq 2048+ the single-document blocks() pads most windows, and pad tokens cost full LIF compute before being masked out. Pack documents instead.
  8. checkpoint_every: 0 at long seq: the full tape is fine at seq 256, but at seq 8192 the per-token boundary state alone is ~44 GB. Segment it (checkpoint_every: 8).

Files

Path
checkpoints/real_seq2048_b4_step3440.ptNewest language ckpt. Step 3440, spike cap 600, seq 512 / batch 16
checkpoints/real_seq2048_b4_step3180.ptStep 3180, spike cap 400, seq 512 / batch 16
checkpoints/real_seq2048_b4_step2855.ptStep 2855, seq 2048 / batch 4 / accum 1
checkpoints/step2500.ptStep 2500, seq 256 / batch 2 x accum 2
checkpoints/step1000.ptStep 1000 (W-ablation / generations v1)
checkpoints/male_cns_spikewhale.ptFrozen-topology MaleCNS SpikeWhale artifact
checkpoints/progress.jsonLast save metrics
config.jsonTrainer hyperparameters (checkpoint_every: 0)
atlas/Sensory groups + Kenyon index
code/Current trainer: anatomy_model.py, sparse_mm_fire.py, train_anatomy.py, generate.py, ...
code_throughput/Earlier CSR throughput patch
code_fire/Fire-only kernel + CPU equivalence test
code_fly_attn/Byrne-looped GPT + Kenyon expansion (source only; fly-as-attention stalled ~6.4 CE @ ~120M tokens; Kenyon residual not a long train)
export_trained_brain.pyTrained checkpoint + frozen wiring -> plain connectome SNN (--dale for sign-constrained)
logs/train_anatomy_to_2500.jsonlPer-step metrics 1-2500 (stitched across resumes)
logs/train_curve_2500.jsonSummary
logs/generate_step2500.logGreedy + sampled dumps
logs/eval_w_ablation_step1000.jsonW ablation
logs/eval_w_ablation_step2855.jsonW ablation re-run at step 2855
logs/generate_step2855.logGreedy + sampled dumps at step 2855
logs/spike_cap_experiment.jsonmax_spikes 80 / 400 / 2000 ramp
logs/dale_export_step2948.jsonExport stats, weight drift, sign flips
logs/generate_connectome_step2948.logGenerations from both exported brains
logs/participation_2500_vs_2855.jsonHow many neurons actually fire
logs/real_seq2048_b4_step2855_train.logseq-2048 leg, per-10-step lines
logs/real_seq2048_b4_step2855_progress.jsonLast save of that leg (stop_reason: deadline)
logs/real_seq2048_b4_step3180_*, logs/real_seq2048_b4_step3440_*Progress json + train log for those legs (coverage fields included)
vision/eye.pyColour, both eyes, photoreceptor-driven input stage (opsins, orientation, tonic lamina, fixations)
vision/photoreceptor_placement.csvEye + column for every photoreceptor, from its synapses
vision/phase0_probe.py, vision/phase0_depth.pyUntrained encoder probes: MNIST, parallax, looming, with the rewired twin
vision/trace_images.py, vision/trace_color.py, vision/calibrate_eye.pyPer-image traces and the tonic / gain calibration
vision/trace/phase1_photoreceptor_channels.pngPhase 1 figure: ship / truck / cat through opsin channels + firing rates
vision/trace/three_images.png, vision/trace/three_images_color_calibrated.pngEarlier traces
vision/trace/*.jsonCalibration + trace dumps
logs/vision_phase0_*.json, logs/vision_depth_*.jsonPhase 0 results
logs/generate_connectome_step3440.logStep 3440 generations, as-trained and Dale-projected brains
logs/dale_vs_astrained_eval_step3440.jsonStep 3440: CE of both brains on identical batches (+1.70 for Dale)
logs/dale_export_step3440.jsonStep 3440 export stats (both brains)
vision/train_anatomy_vision.pyJoint vision + language trainer: eye cross-fade, head attention, visual tokens, DINO eye teacher, Daisy language teacher, image-use check, --generate, --record-features
vision/config_vision.jsonSettings of the last vision leg (alpha 0.5, teachers on, numbered saves every 100 steps)
export_to_malecns.pyTrained brain -> MaleCNS flat edge table (body_pre, body_post, weight)
analysis/delta_map.py, analysis/local_rule_fit.py, analysis/credit_signal_test.pyWhat training changed; local-rule fit; modulatory credit test
analysis/mushroom_body_test.pyDopamine-gated learning on the Kenyon -> MBON synapses vs backprop
analysis/optic_readout_probe.py, analysis/optic_word_probe.pyWhat each visual stage says about caption words
logs/delta_map.json, logs/local_rule_fit_step2948.json, logs/credit_signal_test_step2948.jsonAnalysis results
logs/mushroom_body_odour_step2948_seed*.jsonMushroom body test, 5 seeds
logs/generate_vision_step5160.logStep 5160 generations in the trained eye setup (leg 1, after the collapse)
logs/vision_v2_train_5921_10225.logPer-step log, steps 5921 - 10225 (both teachers)
logs/generate_vision_step10225.logStep 10225 generations: grey field and two photos, image-use check
logs/vision_diagnose_step10225.jsonLink-by-link test of why the head ignores the image
logs/vision_diagnose_step10225_vpn_tokens.jsonSame test with visual tokens taken from the optic-lobe outputs
vision/dopamine_cells.ptPAM (316) and PPL1 (16) dopamine neuron indices used by the dopamine reward
logs/profile_cpu_step10225.jsonWhere the time of one training step goes
analysis/fly_circuit_test.pyStage 1: whole-brain LIF taste -> MN9 test on original and trained brains
analysis/fly_repair_sim.pyStage 2: simulated days with homeostatic scaling (--bound, --freeze-trained, --save-days)
analysis/malecns_roundtrip_generate.shBrain -> MaleCNS table -> rebuilt SNN -> generations
logs/fly_circuit_sugar_mn9.jsonStage 1 results
logs/fly_repair_sim_step2948.*, logs/fly_repair_bounded_step2948.*, logs/fly_repair_frozen_step2948.*Stage 2: unbounded, bounded and frozen-trained runs
logs/generate_repair_bounded_day15_from_malecns.log, logs/generate_step2948_baseline_for_repair.logDay-15 repaired brain after the MaleCNS round trip, and its baseline
checkpoints/vision_v2_step12669.ptVision + language at 12669
checkpoints/vision_v2_step12040_frozen_day30.ptThe frozen fly (step 12040, 30 simulated days, trained synapses frozen)
logs/fly_circuit_sugar_mn9_step12040.json, logs/fly_repair_*_step12040.*Stage 1 and stage 2 on step 12040
logs/trajectory_5921_now.jsonBinned text / caption CE curves used for the trend fits
checkpoints/vision_v3_step14260_frozen_day30.pt, checkpoints/vision_v4_step14580_frozen_day30.ptFrozen flies (30 simulated days, trained synapses frozen) served by the Space
exports/connectome-weights-male-cns-v1.0-fly14580.featherStep 14580 frozen fly in native Janelia connectome-weights format (body_pre, body_post, weight)
analysis/export_malecns_native.pyWriter for that native feather
exports/malecns_vision_v3_step14260_frozen_day30.feather, ..._v4_step14580_...Their MaleCNS edge tables (round-trip exact)
vision/train_anatomy_vision_v3.py, vision/train_anatomy_vision_v4.pyv3 (judge, loops, HRM, JEPA, MTP) and v4 (neuron cut, batch 64, background text)
vision/config_vision_v3.json, vision/config_vision_v4.json, vision/prune_census.pt, vision/taste_cells.ptTheir configs, the neuron census, and the sugar / bitter / MN9 cell lists
analysis/deer_test.pyParallel-in-time (quasi-DEER) convergence test
analysis/benchmark_lm.py, logs/benchmarks.jsonARC-Easy / PIQA / ArithMark 3.0 / WikiText-2 byte perplexity at step 14580
analysis/fit_neuron_types.py, logs/fit_neuron_types.jsonFitting the 8 per-transmitter neuron types on the frozen brain
checkpoints/vision_v4_step14580_types.pt, logs/neuron_types_generations.jsonThat fly, and its text next to the one-type fly
analysis/neuron_complexity_study.py, logs/neuron_complexity_study.jsonSubthreshold census, graded vs spiking eye readout, memory horizon
vision/train_anatomy_vision_v5.py, vision/config_vision_v5.jsonThe leg with the types trainable (steps 14581 - 14850)
logs/fly_repair_unbounded_step14580.*, ..._language.jsonThe unbounded 30-day repair of the newest fly, and what it did to its language
logs/vision_v4_train_14261_14580.log, logs/fly_repair_frozen_step14580.*The v4 leg and the freeze of step 14580

Load / generate

PYTHONPATH=code python generate.py \
  --ckpt checkpoints/real_seq2048_b4_step3440.pt \
  --device cuda --n-new 64 --temperature 0.8 --top-k 50

generate.py expects male_cns_spikewhale.pt at ../../output/male_cns_spikewhale.pt relative to experiments/anatomy_lm. In this snapshot:

mkdir -p output experiments/anatomy_lm/output/real_seq256_hubs atlas
cp checkpoints/male_cns_spikewhale.pt output/
cp checkpoints/step2500.pt experiments/anatomy_lm/output/real_seq256_hubs/latest.pt
cp -r atlas experiments/anatomy_lm/
cp config.json experiments/anatomy_lm/

Resume training

Same run name loads latest.pt. Optimizer moments are not in the ckpt.

cp checkpoints/real_seq2048_b4_step3440.pt \
   experiments/anatomy_lm/output/real_seq2048_b4/latest.pt
python -u experiments/anatomy_lm/train_anatomy.py \
  --start-training --device cuda --condition real --run-name real_seq2048_b4
# expect {"resume_from": 3440, ...}

The seq-2048 leg ran with sequence_length: 2048, batch_size: 4, gradient_accumulation: 1, checkpoint_every: 8 and contiguous document packing. At seq 256 the old config.json still applies (checkpoint_every: 0, run name real_seq256_hubs, resume from step2500.pt).

Do not copy an older checkpoint over latest.pt unless you intend to rewind.


License

Code: Apache-2.0, consistent with SpikeWhale-SNN-216M.

MaleCNS data: CC-BY 4.0 (Janelia / Cambridge / MRC LMB / Google Research). Cite Berg et al. 2026 if you use the graph.

@article{berg2026malecns,
  title   = {Sexual dimorphism in the complete {Drosophila} male central nervous system connectome},
  author  = {Berg, Stuart and Beckett, Isabella R. and Costa, Marta and Schlegel, Philipp and Januszewski, Micha{\l} and Marin, Elizabeth C. and Nern, Aljoscha and others},
  journal = {Cell},
  volume  = {189},
  number  = {18},
  pages   = {5504--5526.e15},
  year    = {2026},
  doi     = {10.1016/j.cell.2026.08.015}
}

The eight neuron types the model always had

code/model.py gives every cell a threshold, a leak and an input gain derived from its transmitter through three 8-vectors (thr_gain, beta_gain, in_gain). AnatomyLM freezes them, and they had been zero since step 0 - so all 167,565 neurons shared one threshold (1.0), one leak (0.9) and one gain (1.0). Eight possible neuron types, one used. The comment next to the freeze says why: a raised threshold on the cells the sensory hash injects into can silence that hash, because the inject is 1.1.

Fitting those 24 numbers on the frozen step-14580 brain (analysis/fit_neuron_types.py; every synapse, the head, the decoder and the eye held fixed):

one type (as trained)8 types fitted
held-out val CE3.03312.8648
test-sentence CE2.76272.7384
thresholds across the brain1.0 everywhere0.808 - 1.200

Nobody told it which transmitters are inhibitory. It found that anyway:

transmittercellsthresholdleakinput gain
acetylcholine (the excitatory majority)103,7681.0910.8730.867
GABA22,0800.9790.9020.919
glutamate (GluCl, inhibitory in the fly)29,3250.8200.9000.998
histamine5,9120.8400.9120.962
dopamine3920.8080.9051.286
octopamine1011.2000.8800.843
serotonin481.0950.9190.940

Damp the big excitatory population, make the inhibitory ones easier to fire, and make the dopamine cells the most excitable in the brain - an E/I balance, from 24 free parameters, with the wiring untouched. checkpoints/vision_v4_step14580_types.pt, and the Space serves it as "Step 14580 + 8 neuron types" (same synapses as the 14580 fly, different cells).

What it is worth, honestly. The text is different, not plainly better (logs/neuron_types_generations.json, 6 test sentences and 5 prompts, greedy):

Once upon a time     one type : , there was a little girl who loved to play with her mommy and daddy
                     8 types  : , the was a little girl who loved to play with her. She wanted to go
One day, a boy found one type : a little girl in the garden. She was so happy that she had to go back
                     8 types  : a little girl in the garden. She was so excited and she wanted to go

CE fell on 3 of 6 test sentences and all 5 generations changed. So: a real but small gain, bought with 24 numbers and fifteen minutes, against ~29M tokens of training.

Training them further did not help (yet). A leg with the types trainable (vision/train_anatomy_vision_v5.py, batch 32, save every 10, thresholds clamped under the 1.1 inject) ran 270 steps to 14850. Caption CE and the Daisy KL both improved during it (4.28 -> 3.15, 2.04 -> 1.77), but test-sentence CE came out worse: 2.9975, and the spread between types halved (std 0.108 -> 0.051) as every threshold slid downwards together while the firing rate stayed flat at 0.030. Under a fixed spike-mass cap, lowering all thresholds at once is free - the cap renormalises - so that drift may be a degeneracy rather than learning. That leg also changed the text blend at the same time (adding IFM reasoning at 0.10), so it cannot separate the two causes. The clean version - types trainable, blend unchanged, thresholds re-centred each step so the spread can grow without the whole set sliding - has not been run.


Benchmarks at the last step (14580), for curiosity

Scored the usual zero-shot way (analysis/benchmark_lm.py, logs/benchmarks.json): for multiple choice, pick the option with the highest log-likelihood of the continuation, reported raw (acc) and length-normalised per byte (acc_norm), as lm-evaluation-harness does; for WikiText-2, byte perplexity over 40 windows of 256 tokens. 200 items per task, seed 0. Daisy-Base - a conventional small transformer, this fly's language teacher - is the reference column, from its own card.

the fly (step 14580)chanceDaisy-Base
ARC-Easy25.5% (acc_norm 20.5%)25%46.8%
PIQA49.5% (acc_norm 53.0%)50%60.1%
ArithMark 3.029.0% (acc_norm 29.0%)25%46.7%
WikiText-2 byte perplexity7.27 (2.86 bits/byte)--2.55

At chance on knowledge, a few points over chance elsewhere. ARC-Easy is grade-school science. This brain has seen ~29M tokens of children's stories and photo captions. It has no facts to retrieve. 25.5% is what it should score. PIQA acc_norm 53% and ArithMark 29% on 200 items: suggestive at best. Not a claim.

WikiText byte perplexity is the honest number. No knowledge, no multiple-choice. 7.27 against Daisy-Base's 2.55. Wikipedia is only partly in domain (rehearsal is 40% TinyStories, 20% FinePhrase). Its own test-sentence CE is 2.76; byte perplexity there would be far lower.

Expected shape for 29M tokens through a fly's wiring. Here for completeness. Not because these numbers were going to look good.


Conclusion

In order.

  1. The graph is the fly. MaleCNS v1.0 as released (Janelia / Google). 167,565 neurons, 25.6M synapses. Hard-LIF SpikeWhale cells. Train synapse strengths only. Wiring stays the fly's.

  2. Language from scratch. Seq 256 to CE ~4.8 by 2.56M tokens. Ablation at step 1000: destroy W and CE dies. Then it plateaus (4.8-4.9 through 2855). Greedy latches (the the the, then longer repeated clauses). Spike cap 80 pins participation; ramping it recruits more cells but does not break the CE floor. Dale's law: language-only training flipped ~1.1M signs; projecting them back costs +0.22 nats at 2948 and +1.70 at 3440.

  3. The eyes. 62% of the CNS. Language barely trains them. Photoreceptors placed from their own synapses, colour by opsin, both eyes, tonic lamina. Untrained optic lobe: small parallax signal, no looming, loses MNIST to a rewired twin.

  4. Joint vision + language. Start 2948, Dale on. Full-strength eyes explode gradients (174 of 256 head cells are optic lobe). Hinge loss kills caption learning for ~1,700 steps. Visual tokens were the wrong cells until 10225. VPN tokens + DINOv2 + Daisy + decoder still left image_gain at noise. PAM/PPL1 on at 10761: image_gain leaves noise. That is the proof for those cells in this brain. Not a missing scramble. SmolLM2 judge, looped decoder / HRM / JEPA / MTP. Skip never-spiking cells (39% of synapses kept, captions bit-identical). Generate-path used to attach grey-field visual tokens to plain text; that was a bug.

  5. Last saved step (14580). English fragments. Test-sentence CE 2.76. Greedy: , there was a little girl who loved to play with her mommy and daddy. S. image_gain +0.114. Frozen fly: 30 simulated days, trained synapses frozen, language CE identical (2.7627). Native Janelia-format connectome: exports/connectome-weights-male-cns-v1.0-fly14580.feather. Space serves that.

  6. Still a fly, mostly. Sugar -> MN9 still fires after all of this. Bitter does not. Put back in the body at step 14580, sugar still triggers the proboscis; bitter-like taste -> MN9 is 0 Hz (original fly 21 Hz). Freeze the trained synapses and the rest of the brain can adapt around them, with language bit-identical. Unbounded homeostatic scaling brings activity all the way back to the original fly's (12.0%) and, at 14580, mostly spares the reflex (157 Hz) - but it destroys the language every time (CE 2.76 -> 6.61). Right activity is not right language.

  7. Benchmarked, for curiosity. ARC-Easy 25.5% (chance 25), PIQA 49.5% / acc_norm 53.0% (chance 50), ArithMark 3.0 29.0% (chance 25), WikiText-2 byte perplexity 7.27 against Daisy-Base's 2.55. At chance on knowledge, a few points over chance elsewhere. Expected at ~29M tokens.

  8. This is paused here. I answered most of the questions I had, and the benchmark above was the last one on the list. May try more later. Not a chatbot. A simulation of the released wiring that learned broken English and still works as a fly.


Citation

If you use this project, the code, the checkpoints, or the write-up, please cite Dean Byrne (Quazim0t0) and the MaleCNS paper above.

@misc{byrne2026malecns_snn,
  title        = {MaleCNS x SpikeWhale: training language and vision on the Drosophila male CNS connectome},
  author       = {Byrne, Dean},
  year         = {2026},
  howpublished = {Hugging Face},
  url          = {https://huggingface.co/Quazim0t0/MaleCNS-SpikeWhale-Anatomy-LM},
  note         = {Quazim0t0 / Dean Byrne}
}

Space: Quazim0t0/MaleCNS-Fly.

Как запустить

На своей GPU в ailist. Цена — по текущим предложениям провайдеров

GPU в ailist

Универсальный рантайм · pytorch

Нельзя запустить

Архитектура ? неизвестна transformers в образе рантайма.

Ревизия весов
18ee2bd

0 моделей