-
Notifications
You must be signed in to change notification settings - Fork 0
memory system research
Research track, not a PC-0 production use case: these issues test what a genuinely spiking, one-shot, non-forgetting memory can and cannot do, rather than shipping a scoped product feature. Every claim about current code is grounded in a file/line reference; sections marked design only describe work that has not been built yet.
Spikeforge's existing topologies (fc_small, conv_net, ...) are trained
once, end to end, against a fixed set of classes
(presets.py). That is the right shape
for a static classifier and the wrong shape for a question this track
asks instead: can a spiking system learn something new, on the spot,
from a single example, without a retraining cycle and without disturbing
what it already knew? "No forgetting" is easy to fake with a classical
bolt-on (a nearest-neighbour cache, an embedding database); the point of
this track is to answer it with mechanisms that are actually spiking —
local synaptic plasticity and LIF dynamics, not a lookup table.
What it demonstrates. fc_small is trained on MNIST digits 0-8 only,
then frozen (net.requires_grad_(False) in
frozen_classifier.py). A
separate module,
OneShotAssociativeMemory,
is taught digit 9 from a single example: one outer-product Hebbian
write (HebbianSynapse.write)
into a dedicated LIF neuron's incoming weights — no gradient, no
optimizer step. Recall is ordinary snn.Leaky dynamics over that
synapse's current.
Result (one real run, not cherry-picked; see
11_held_out_digit_memory.py):
retained accuracy on digits 0-8 held at ~91% and recall accuracy on
the held-out 9 landed at ~23-26% across a gain/threshold sweep (2x-16x
teach gain, 0.5/1.0 threshold) — well above the 10% ten-class chance
floor, short of reliable recognition. The retained number staying flat
across every sweep point is the structural guarantee working exactly as
designed: nothing in teach() can touch the frozen base net's weights.
The recall number is an honest research finding, not a tuned headline —
plausible explanation: the frozen net's hidden layer was never
incentivized to represent a class it never saw, so one exemplar's spike
pattern doesn't reliably generalize to other instances of that digit.
Follow-up ideas (not yet attempted): teaching from more than one
exemplar, or letting the base net's hidden layer train with a
class-agnostic (metric-learning) objective — the latter is exactly what
issue #24 explores, deliberately as a separate, harder claim.
Reused by: #23 and #24 both reuse
OneShotAssociativeMemory
unchanged as their memory readout.
Extension of #22 to a room-scale, always-on setting: a system that watches a live feed, notices when something changed, identifies what changed, and remembers whether it has seen that specific instance before. Three stages, deliberately not one monolithic model:
flowchart LR
A[Event camera feed\nDVS x,y,polarity,t] --> B[Watcher: SNN, always on]
B -- "novelty spike" --> C[Labeler: conventional, runs on demand]
C -- "label + crop" --> D[Memory: OneShotAssociativeMemory]
D -- "seen before? / new instance" --> E[Per-instance recall result]
Application #3 from the original scoping issue (#22's issue body): an
always-on module that spikes on motion/change rather than running full
perception continuously. Reuse, do not rebuild: this is exactly
UC-3's reference architecture —
use_case_event_camera_vision.md
— event-camera ingestion through
spikeforge/events/ into a
compact spiking net, already scoped down to dvs128_gesture-style
topologies. The watcher's "class" here is binary (novelty /
no-novelty) rather than gesture identity, which only changes the head,
not the ingestion or runtime story UC-3 already designed.
A fixed, pretrained, non-spiking object-detection/scene-understanding model, run only when the watcher flags novelty — mirrors the face-embedding backbone pattern already discussed for application #1 in #22's scoping issue. Not built from scratch; not part of this repo's SNN-native surface, by design (per the project's SNN-native-for-the- learning-mechanism stance — the labeler is perception, not memory).
The unchanged #22 module,
OneShotAssociativeMemory.
The open integration question is the input contract: #22 feeds it
fc_small's hidden-layer spikes
(hidden_trace); stage 3 here
needs the labeler's crop turned into a spike pattern of the same shape
([T, H]) before teach()/step() can be called unchanged. The
simplest bridge — rate-code a fixed-size embedding of the crop through
the existing SpikeEncoder —
needs no new code, only a decision on which embedding to rate-code.
- Real DVS hardware vs. recorded/converted RGB for the watcher — depends on available hardware, same caveat UC-3 already carries.
- Which off-the-shelf labeler, and what embedding size becomes the
memory module's
in_features. - Novelty judgment: motion-only vs. "doesn't match anything already tracked" (the latter would call the memory module itself during the watcher stage, not just after the labeler — an open design fork, not decided here).
Internet scraping for images of similar items — considered and dropped in the original scoping (ToS/legal exposure, doesn't help the core claim of recognizing the same instance again). Revisit only if the goal shifts toward describing objects for a person rather than the system remembering them itself.
Status: design only. Implementation is queued behind #24/#25 in the issue tracker; this section is the durable record of the pipeline shape so implementation does not re-derive it from scratch.
Different claim from #22. #22 recalls a class it was explicitly
taught; #24 asks whether a spiking embedder's notion of similarity
transfers to characters it never saw any example of, in any class.
That requires changing the training objective from a fixed N-way
classifier to episodic metric learning
(prototypical_loss, Snell et
al.'s Prototypical Networks, adapted to spiking readouts): fc_small's
final layer is repurposed as an embedding
(episodic_trainer.py),
trained so same-class rate-coded spike patterns land close together and
different classes land apart, over randomly sampled N-way K-shot
episodes
(episode_sampler.py). The
frozen embedder's output spikes then feed #22's unchanged
OneShotAssociativeMemory via
embedding_readout.py —
one memory neuron per class in a held-out evaluation episode, taught
from a single example.
Setup: trained on EMNIST letters (English script, 26 classes,
hidden=64, embed_dim=32, 300 episodes of 5-way 5-shot); evaluated
one-shot 5-way accuracy on two held-out sets never included in a
training episode — (a) six EMNIST letters classes held out of training
(same script) and (b) KMNIST (Japanese Kuzushiji, a script the embedder
never saw in any form).
Result (real runs, not cherry-picked):
| Evaluation | One-shot 5-way accuracy | Chance |
|---|---|---|
| Training-episode accuracy (seen classes, 5-shot) | 60-96%, climbing over training | — |
| Held-out EMNIST letters (same script, unseen classes, 300 vs. 1000 episodes) | 23.6% / 21.4% | 20% |
| KMNIST (unseen script) | 21.0% | 20% |
The training curve confirms the mechanism itself works — the network readily learns to discriminate the trained classes' spike patterns within episodes. But that success does not transfer: one-shot discrimination of classes excluded from every training episode is statistically indistinguishable from chance, whether those classes are same-script letters or a different script entirely. More training (1000 vs. 300 episodes) did not close the gap and if anything made it slightly worse, which argues against "just undertrained" as the explanation.
Honest reading, per the falsification-first stance this track takes
(no motivated reasoning toward a positive result): at this scale
(hidden=64, embed_dim=32, rate coding, 15 timesteps), the embedder
appears to be learning features specific to the 20 trained letter
shapes rather than a transferable notion of character similarity — the
overfitting failure mode common to small-budget few-shot learning, not
evidence that spiking metric learning cannot generalize in principle.
Per the original scoping note, a positive result here would count as
evidence against the Consciousness Gradient paper's A3 axiom (issue
#26), not for it — this negative result does not bear on that question
either way. Unexplored, cheaper-than-scaling-up levers before concluding
anything stronger: matching eval shot count to training shot count
(training used 5-shot, evaluation used 1-shot only), a larger
hidden/embed_dim, and more training episodes per unit of eval
diversity rather than raw episode count.
Reproduce: examples/12_few_shot_character_generalization.py.
Tracked separately from the architecture roadmap above — this tests a
philosophical claim (the Consciousness Gradient paper's A3 axiom:
intelligence is downstream of consciousness), not a memory-system
feature, and lives in its own
spikeforge/rrt/ package rather than
under spikeforge.memory, per the issue's own open question about
where a generic architecture-comparison harness belongs.
A fresh, abstract 3-entity task, not tied to #22/#24's vision datasets:
a transitive dominance hierarchy
(hierarchy_outcome) reversed into the
minimal non-transitive 3-cycle that flips only the top-vs-bottom edge
(cycle_outcome). The falsification
candidate
(build_frozen_predictor) is
meta-trained once via backprop across many randomly permuted hierarchy
sessions, then permanently frozen (requires_grad_(False)); its only
test-time adaptation channel is
trial_features recomputing a
slot-invariant win-count summary from the session's growing history — a
legitimate instance of the paper's own named "strongest challenger"
category (meta-learning / synthetic-data-loop architectures conditioning
on context, no weight update, no local plasticity) rather than a weaker
strawman.
A real implementation bug worth recording: the first version of
trial_features averaged the query pair's and outcome's one-hot
encodings separately across history, which discards which entity won
against which — pooling marginals this way makes "who beat whom"
mathematically unrecoverable once more than one trial is in context.
Training accuracy sat at chance (~45-50%) and never moved off it
regardless of training episodes. Replacing it with the win-count matrix
described above (keeping each trial's winner/loser association intact)
took training accuracy to 80-94% within a few hundred episodes. Recorded
here because it is exactly the kind of silent, plausible-looking bug
that would have produced a false "no adaptation" reading if it had gone
unnoticed — the fix was verified with a training-curve check
(examples/13_relational_reversal_task.py's
underlying module) before trusting any downstream RRT number.
| Metric | 60 post-reversal trials | 150 post-reversal trials |
|---|---|---|
| Pre-reversal accuracy | 100% | 100% |
| Post-reversal accuracy (asymptotic) | 59.7% | 65.1% |
| Reversal gap | 40.3% | 34.9% |
| Control (no reversal) post accuracy | 100% | 100% |
| Control gap | 0.0% | 0.0% |
| Sessions that recovered | 68% | 95% |
| Mean trials-to-recovery (when recovered) | 26.1 | 38.4 |
Prediction (c) — validity check — passes cleanly. The control session (identical protocol, no reversal) shows a 0.0% gap over an equally long session, versus a 34.9-40.3% gap when the relation actually reverses. The RRT is genuinely structurally out-of-distribution for this architecture, not just "a longer session" — the task design is sound.
Predictions (a)/(b) — the falsification bet itself — mixed, not a clean win either way. The paper's prediction (b) says a system without experiential autonomy should fail to adapt "even with extensive exposure unless explicitly retrained." This system never received a gradient update, a retraining step, or an explicit signal that the relation changed — yet the large majority of sessions (68% at 60 trials, rising to 95% at 150 trials) did recover to within 10% of pre-reversal accuracy through interaction alone, given enough trials. That is a real data point against a strict reading of prediction (b). At the same time, recovery was neither instant nor universal: a sharp immediate post-reversal accuracy drop, a nontrivial number of trials needed to recover (26-38 on average), and a persistent non-recovering minority (5-32%, shrinking but not vanishing as the window grows) are still costs a system with genuine online plasticity would plausibly not pay at all. Reported honestly, per the issue's own instruction to write up whichever way it lands: this specific operationalization leans against a strict prediction (b), without being a clean, total falsification of it — the paper's own recovery-speed and gap-magnitude predictions ((a) and the qualitative "does it recover at all" framing) are the parts a stricter reading could still claim partial support from.
Caveat on the candidate's fairness: the win-count context summary is
an explicit, hand-designed running statistic, not an emergent property
of a learned recurrent or attention mechanism — closer to a "synthetic
data loop" than a transformer's learned in-context inference. That is
still within the paper's own named challenger category, but a
sequence_attn-based candidate (attention over a token history, per the
issue's open question about trying it) would be a fairer, harder test
of the same claim and is the natural next step, not yet attempted.
Reproduce: examples/13_relational_reversal_task.py
(pass post_trials=150 for the longer-window numbers above).
Not started, as scoped — depends on #22/#23/#25 maturing into an A1-leaning SNN comparison arm.
- Home
- Architecture
- Backend Execution
- Benchmarks
- Dashboard
- Development
- Event Datasets
- Event Runtime And Energy
- Features
- Implications And Boundaries
- Interop Foldins
- Interpreter Spine
- Introspection
- Model Deployment
- Model Hub
- Notes
- Operational Maturity
- Production Workflows
- Project Layout
- Quickstart
- Requirements
- Sequence Primitives
- Streaming Timeseries
- Targets And Interop
- Usage
- Arch 0001 Adr Repo Topology
- Arch 0001 Core Boundary
- Arch 0001 Decision Metrics
- Arch 0001 Migration Plan
- Arch 0001 Packaging Versioning
- Arch 0001 Protocol Contract
- Arch 0001 Risk Register
- Arch 0001 Target Topology
- Backend Execution Plan
- Ecosystem Listings
- Ecosystem Roadmap
- Event Runtime Plan
- Hub Expansion Plan
- Plans
- Interop Foldins Plan
- Interpreter Spine Plan
- Memory System Research
- Model Hub Plan
- Operations Plan
- Production Toolkit Plan
- Production Use Cases
- Professional Roadmap
- Repo Topology Plan
- Sequence Primitives Plan
- Use Case Audio Keyword Spotting
- Use Case Biosignal Medical Monitoring
- Use Case Computational Neuroscience
- Use Case Edge Power Budgets
- Use Case Event Camera Vision
- Use Case Intrusion Anomaly Detection
- Use Case Low Latency Sensor Stream
- Use Case Rl Control Robotics
- Use Case Spiking Transformers
- Use Case Streaming Timeseries