E13b/c: harden real-weight speciation — full symmetry group + emergent-divergence null

E13c (the symmetry defense): alignment now runs modulo the FULL
function-preserving unit symmetry group of a ReLU MLP (per-unit positive
rescaling via canonicalise_scale, composed with Re-Basin permutations;
sanity gate recovers a permuted-and-rescaled copy exactly). Verdict: the
full group removes the independent-init barrier (residual 0.001) and
essentially none of the conflict barrier (0.502 -> 0.497) — the residual
is functional, not a missed symmetry (answers arXiv:2606.23607). The
cliff gains a hybrid-fitness readout: merged accuracy 0.97 -> 0.03 with
conflict. Floor proposition drafted (paper/si-notes.md S1): endpoint
invariance + max(eps_A, eps_B) >= mu(S)/2 for any merged model under any
alignment group.

E13b (emergent divergence): pre-registered second reading — with NO
conflicting training signal (disjoint class specialists; rolled-input
conventions), residual is 0.000 at every divergence to t_div=3200, and
the merge RESCUES the forgetting specialists (parents 0.535/0.474 ->
merged 0.955; a sustained Fisher-Muller rescue at zero barrier).
Speciation in real weights requires functional conflict; it does not
emerge from compatible specialisation on shared ancestry. LLM-scale
over-specialisation (cf. 2607.11997) deferred to Phase-3 llm_speciation.

3-panel figure, READMEs, +2 tests (149 green), make mnist wired.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BkRLcc18rwT2Lysu6PbG7v
This commit is contained in:
Giorgio Gilestro 2026-09-06 12:35:14 +01:00
parent 72d5e9e736
commit ea051a5f92
15 changed files with 435 additions and 77 deletions

View file

@ -26,6 +26,7 @@ mnist: ## run the torchvision tiers: MNIST collapse + E13 real-weigh
uv run python -m neural.experiment configs/neural/mnist_collapse.yaml
uv run python -m neural.experiment configs/neural/speciation_real.yaml
uv run python -m neural.experiment configs/neural/speciation_real_cliff.yaml
uv run python -m neural.experiment configs/neural/speciation_real_emergent.yaml
env-llm: ## add the LLM stack for the Layer-2 prototype (GPU; transformers/peft)
uv sync --extra dev --extra neural --extra llm

View file

@ -0,0 +1,36 @@
experiment: speciation_real_emergent
kind: speciation_real
seed: 813
n_replicates: 4
# E13b — EMERGENT model speciation (the decisive experiment; PNAS work order Phase 1). The committed
# E13 cliff IMPOSES contradiction (conflicting label maps); a true Bateson-Dobzhansky-Muller
# incompatibility is emergent — each lineage's changes harmless alone, incompatible only in
# combination. Here the two children diverge WITHOUT any imposed conflict:
# shared — control anchor (same task, same data): residual should stay ~0 at every divergence.
# disjoint — A trains only on classes 0-4, B only on 5-9 (complementary specialists, no
# contradiction). The money curve is acc_merge_* vs t_div against the parents: at low
# divergence the merge should RESCUE the two forgetting specialists (Fisher-Muller);
# if a residual barrier emerges and merged accuracy then falls with divergence, that is
# E12's compatible -> outbreeding-depression -> inviability trajectory, emergent in real
# weights. If the residual stays ~0, the honest conclusion is that models are SAFER to
# merge than the biological analogy predicts (a bound on the analogy) - either outcome
# is reportable; pre-registered falsifier language, do not tune toward one.
# augment — same task/labels, A on +3px-rolled images, B on -3px-rolled (pure representational
# conventions, zero output conflict): does convention drift alone isolate?
# Alignment is reported permutation-only (residual) AND scale-canonicalised+permutation
# (residual_scale, the full ReLU unit symmetry group; E13c) so any emergent residual cannot be
# dismissed as a missed symmetry (cf. arXiv:2606.23607).
speciation_real:
sizes: [784, 512, 512, 10]
conditions: [shared, disjoint, augment]
t_div: [100, 200, 400, 800, 1600, 3200]
base_steps: 500
lr: 0.05
batch: 128
n_eval: 2000
data_root: data
output:
dir: results/speciation_real_emergent

View file

@ -1,11 +1,20 @@
"""E13 figure — real-weight model speciation with Git Re-Basin.
"""E13 figure — real-weight model speciation: what alignment can and cannot merge, and what emerges.
(A) The barrier decomposition per condition: the linear-mode-connectivity error barrier between two
merged MLPs, split into the part permutation alignment REMOVES (coordinate artefact) and the RESIDUAL it
cannot (reproductive isolation). `shared` 0; `independent` (same task, different init) is almost all
removable (residual 0 same species, different basis); `conflict` (conflicting tasks) is almost all
residual (real isolation). (B) The isolation cliff: residual barrier vs the fraction of conflicting
classes the real-weight image of E12's cliff, after alignment (so it is not a coordinate artefact).
(A) The barrier decomposition per condition, at two alignment strengths: the linear-mode-connectivity
error barrier between two merged MLPs, naive vs after Git Re-Basin permutation alignment vs after
alignment modulo the FULL ReLU unit symmetry group (scale-canonicalisation + permutation, E13c).
`independent` (same task, different init) is a coordinate artefact either alignment removes ~all of
it; `conflict` (contradictory label maps) survives both real reproductive isolation, not a missed
symmetry (cf. arXiv:2606.23607).
(B) The isolation cliff as hybrid fitness: sweeping the fraction of conflicting classes, the residual
(full-symmetry) barrier rises while the merged (midpoint) model's accuracy falls 0.97 -> 0.03 — the
real-weight image of E12's compatible -> depression -> inviability trajectory.
(C) Emergent divergence (E13b): children specialising on disjoint classes (or divergent input
conventions) from a shared fork develop NO residual barrier at any divergence instead the merge
RESCUES the two forgetting specialists (Fisher-Muller), holding ~0.95 while the parents decay.
Speciation requires functional conflict; it does not emerge from compatible specialisation here.
Usage: python figures/plot_speciation_real.py
"""
@ -25,40 +34,72 @@ from _figlib import load_bundle, savefig # noqa: E402
def main() -> None:
dec, _ = load_bundle("results/speciation_real")
cliff, _ = load_bundle("results/speciation_real_cliff")
emer, _ = load_bundle("results/speciation_real_emergent")
fig, axes = plt.subplots(1, 2, figsize=(13, 5))
fig, axes = plt.subplots(1, 3, figsize=(17.5, 5))
# Panel A: removable (coordinate artefact) vs residual (isolation), stacked, per condition.
# Panel A: naive / residual(perm) / residual(perm+scale) per condition.
ax = axes[0]
order = [c for c in ["shared", "independent", "conflict"] if c in set(dec["condition"])]
g = dec.groupby("condition").agg(removable=("removable", "mean"),
residual=("residual", "mean")).reindex(order)
x = np.arange(len(order))
ax.bar(x, g["removable"], 0.6, label="removable by alignment\n(coordinate artefact)", color="#9ecae1")
ax.bar(x, g["residual"], 0.6, bottom=g["removable"], label="residual after alignment\n(reproductive isolation)",
color="#d62728")
g = dec.groupby("condition").agg(naive=("barrier_naive", "mean"),
res_p=("residual", "mean"),
res_s=("residual_scale", "mean")).reindex(order)
x = np.arange(len(order)); w = 0.27
ax.bar(x - w, g["naive"], w, label="naive (no alignment)", color="#9ecae1")
ax.bar(x, g["res_p"], w, label="residual after permutation\n(Git Re-Basin)", color="#fc9272")
ax.bar(x + w, g["res_s"], w, label="residual after FULL symmetry group\n(scale + permutation)", color="#d62728")
ax.set_xticks(x); ax.set_xticklabels(order)
ax.set(ylabel="linear-mode-connectivity error barrier",
title="Merge barrier = coordinate artefact + residual isolation\n"
"(same task even across inits is coordinate; conflict is real)")
ax.legend(frameon=False, fontsize=8)
title="(A) coordinate artefact vs functional isolation\n"
"(conflict survives the full ReLU symmetry group)")
ax.legend(frameon=False, fontsize=7.5)
# Panel B: the isolation cliff — residual barrier vs conflict fraction.
# Panel B: the cliff — residual barrier and hybrid fitness vs conflict fraction.
ax = axes[1]
cg = cliff.groupby("conflict_frac").agg(res_m=("residual", "mean"), res_s=("residual", "std"),
nai_m=("barrier_naive", "mean")).reset_index()
ax.plot(cg["conflict_frac"], cg["nai_m"], "--o", color="#999", lw=1.4, label="naive barrier")
ax.plot(cg["conflict_frac"], cg["res_m"], "-o", color="#d62728", lw=2, label="residual (after alignment)")
ax.fill_between(cg["conflict_frac"], cg["res_m"] - cg["res_s"], cg["res_m"] + cg["res_s"],
cg = cliff.groupby("conflict_frac").agg(res_s=("residual_scale", "mean"), sd=("residual_scale", "std"),
nai=("barrier_naive", "mean"),
hyb=("acc_merge_scale", "mean")).reset_index()
ax.plot(cg["conflict_frac"], cg["nai"], "--o", color="#999", lw=1.4, label="naive barrier")
ax.plot(cg["conflict_frac"], cg["res_s"], "-o", color="#d62728", lw=2,
label="residual (full-symmetry alignment)")
ax.fill_between(cg["conflict_frac"], cg["res_s"] - cg["sd"], cg["res_s"] + cg["sd"],
color="#d62728", alpha=0.15)
ax.set(xlabel="fraction of classes with conflicting labels", ylabel="error barrier",
ylim=(-0.02, None),
title="The reproductive-isolation cliff, in real weights\n"
"(residual rises with task conflict — not removable by alignment)")
ax.legend(frameon=False, fontsize=9)
title="(B) the isolation cliff, in real weights\n(hybrid fitness falls as conflict rises)")
ax2 = ax.twinx()
ax2.plot(cg["conflict_frac"], cg["hyb"], "-s", color="#2c7fb8", lw=1.8, label="merged-model accuracy")
ax2.set_ylabel("merged (hybrid) accuracy", color="#2c7fb8")
ax2.tick_params(axis="y", labelcolor="#2c7fb8"); ax2.set_ylim(-0.02, 1.02)
lines, labels = ax.get_legend_handles_labels()
l2, la2 = ax2.get_legend_handles_labels()
ax.legend(lines + l2, labels + la2, frameon=False, fontsize=7.5, loc="center left")
fig.suptitle("E13 — real-weight model speciation: what permutation alignment can and cannot merge",
y=1.02, fontsize=13)
# Panel C: emergent divergence — no isolation; the merge rescues the forgetting specialists.
ax = axes[2]
colors = {"shared": "#999999", "disjoint": "#2c7fb8", "augment": "#41ab5d"}
for cond in ["shared", "disjoint", "augment"]:
sub = emer[emer["condition"] == cond]
if sub.empty:
continue
m = sub.groupby("t_div").agg(merge=("acc_merge_scale", "mean"),
pa=("acc_parent_a", "mean"), pb=("acc_parent_b", "mean"),
res=("residual_scale", "mean")).reset_index()
ax.plot(m["t_div"], m["merge"], "-o", color=colors[cond], lw=2, label=f"{cond}: merged")
if cond == "disjoint":
ax.plot(m["t_div"], (m["pa"] + m["pb"]) / 2, "--", color=colors[cond], lw=1.2,
label="disjoint: parents (forgetting)")
max_res = float(emer[emer["condition"] != "shared"]["residual_scale"].max())
ax.set_xscale("log")
ax.set(xlabel="divergence (post-fork training steps)", ylabel="accuracy on the full task",
ylim=(0, 1.02),
title="(C) emergent divergence does NOT speciate —\n"
f"the merge rescues the specialists (max residual = {max_res:.3f})")
ax.legend(frameon=False, fontsize=7.5, loc="center left")
fig.suptitle("E13 — real-weight model speciation: isolation requires functional conflict; "
"alignment (even modulo the full symmetry group) cannot remove it, and compatible "
"specialists merge into a rescuing generalist", y=1.03, fontsize=12)
fig.tight_layout()
savefig(fig, "results/speciation_real", "speciation_real")

67
paper/si-notes.md Normal file
View file

@ -0,0 +1,67 @@
# SI notes — drafts of formal statements for the PNAS manuscript
*Working drafts; folded into the SI Appendix at Phase 4. Each statement is written to be exactly as
strong as what is true — no more.*
## S1. The incompatibility floor: what no alignment can remove (E13c)
**Setting.** Models A and B are trained on the same input distribution; their target label functions
`f_A` and `f_B` agree except on a conflict set `S` of probability mass `μ(S)` (in E13's conflict
condition, the cyclically-relabelled classes; `μ(S) ≈ conflict_frac` up to class balance). A
*function-preserving transformation* `T` (any composition of hidden-unit permutations and, for ReLU
networks, positive per-unit rescalings — the full unit symmetry group of a plain ReLU MLP) satisfies
`T(B)(x) = B(x)` for all `x` by construction.
**Proposition 1 (endpoint invariance).** For every function-preserving `T`, the endpoint functions —
and hence the endpoint losses/errors and the linear chord between them — are identical for the pair
`(A, T(B))` and the pair `(A, B)`. Alignment can only re-coordinate the *interpolation path*, never
the endpoints or the chord. *(Immediate from the definition of function-preserving.)*
**Proposition 2 (no merged model can serve both parents).** Let `h` be *any* single classifier (in
particular, any interpolated/merged model, under any alignment). On every `x ∈ S`, `f_A(x) ≠ f_B(x)`,
so `h(x)` disagrees with at least one of them. Hence
`ε_A(h) + ε_B(h) ≥ μ(S)`, and therefore `max(ε_A(h), ε_B(h)) ≥ μ(S)/2`,
where `ε_P(h)` is `h`'s error against parent `P`'s labels. A hybrid of two models whose conventions
conflict on mass `μ(S)` errs at rate at least `μ(S)/2` against at least one parent — **hybrid
disadvantage with an information-theoretic floor, independent of the alignment group, the
architecture, and the merging operator.** This is reproductive isolation in the fitness sense: past a
given functional conflict, *no* recombination operator produces an offspring loyal to both lineages.
**What remains empirical, and why the experiment is designed as it is.** Propositions 12 do *not*
bound the single-task path barrier (the loss along the interpolation between A and `T(B)` evaluated
on one parent's task): in principle a path could dip toward one parent's function. Whether it does is
exactly what E13 measures — and the measured answer is that it does not: the conflict-condition
barrier is unchanged by permutation alignment (`residual`) *and* by alignment modulo the full
permutation × positive-rescaling group (`residual_scale`), while the same aligner removes ~all of the
independent-init barrier (the positive control). Richer-symmetry results for transformers
(arXiv:2606.23607; neuron-identifiability approaches to linear mode connectivity, 2026) strengthen
the *removable* side of the decomposition and are therefore complementary: the more barrier a larger
group can remove for *compatible* models, the sharper the meaning of the residual that survives for
*incompatible* ones — and Proposition 2 caps what any of them could ever achieve on the conflict set.
**Terminology note for the paper.** "Residual (after alignment)" = the estimated functional
incompatibility; for ReLU MLPs we align modulo the full unit symmetry group, so the estimate is not
confounded by missed symmetries of that architecture class.
## S2. Emergent vs imposed incompatibility (E13b framing)
The conflict condition *imposes* contradiction (the two label maps disagree on `S`), which pins
`μ(S) > 0` and activates Proposition 2. A true BatesonDobzhanskyMuller incompatibility is
*emergent*: each lineage's substitutions are harmless on their own background (`μ(S) = 0` — the
training signals never contradict), and incompatibility, if any, arises only in the *combination*.
The `disjoint` (complementary class specialists) and `augment` (divergent input conventions)
conditions realise this: any residual barrier they develop cannot be attributed to label conflict and
is the emergent-speciation signal proper. Pre-registered readings: residual grows with divergence →
model speciation is emergent in real weights (E12's trajectory realised); residual stays at the
`shared`-control level → within this regime, trained networks are *more* merge-compatible than the
biological analogy predicts — an honest bound on the analogy, and itself a design-relevant result
(merging is safe absent functional conflict).
**Outcome (2026-08-11 run, 4 reps, t_div ≤ 3200): the second reading.** Residual 0.000 at every
divergence in both emergent conditions, and the merge *rescues* the forgetting `disjoint` specialists
(parents → 0.535/0.474 on the full task; merged ≈ 0.955 throughout — a sustained FisherMuller rescue
at zero barrier). Isolation in real weights required functional conflict in this regime; whether
long-horizon over-specialisation erodes mergeability at LLM scale (cf. arXiv:2607.11997) is the
`llm_speciation` question (Phase 3).

View file

@ -1,54 +1,85 @@
# E13 — Real-weight model speciation (Git Re-Basin residual)
# E13 — Real-weight model speciation (the alignment residual, now modulo the full symmetry group)
**Claim tested.** E12 predicts model *speciation* analytically: as two lineages diverge, recombination
(merging) fails, via BatesonDobzhanskyMuller incompatibilities. E13 confirms it in **real trained
weights**, and — decisively — separates the part of the incompatibility that is a mere **coordinate
artefact** (removable by permuting hidden units; Git Re-Basin, Ainsworth et al. 2022) from the
**residual** that permutation *cannot* remove, which is the true reproductive-isolation signal. This is
the experiment that answers the mode-connectivity reviewer: if alignment removes the barrier, it was a
coordinate artefact; the barrier that *survives* alignment is real speciation.
weights**, separating the part of the merge barrier that is a mere **coordinate artefact** (removable
by re-coordinating hidden units) from the **residual** that no alignment can remove — the true
reproductive-isolation signal.
**Setup.** Small no-BatchNorm MLPs (78451251210) on MNIST — the clean Re-Basin regime. Two children
are forked from a shared base and trained independently; we weight-average them and measure the
**linear-mode-connectivity error barrier** before (`naive`) and after (`aligned`) in-house, deterministic
Git Re-Basin weight-matching (`neural/rebasin.py`, scipy `linear_sum_assignment`). Statistically
reproducible (seeded torch; NumPy/scipy alignment is deterministic). 3 replicates.
**E13c hardening (2026 PNAS campaign).** Recent work shows symmetry groups *richer than permutations*
remove more of the barrier between independently trained transformers (arXiv:2606.23607;
neuron-identifiability LMC). We therefore align modulo the **full function-preserving unit symmetry
group of a plain ReLU MLP** — per-unit positive rescaling (scale canonicalisation, exact) *composed
with* Git Re-Basin permutation matching (`neural/rebasin.py`; the sanity gate recovers a permuted
**and rescaled** copy to exact weight identity). Both residuals are reported: `residual` (permutation
only) and `residual_scale` (full group).
**Setup.** No-BatchNorm MLPs (78451251210) on MNIST. Children forked/trained per condition;
weight-average merge; linear-mode-connectivity error barrier before/after alignment; midpoint
(merged-model) accuracy recorded alongside. 3 replicates (decomposition/cliff), 4 (emergent).
Statistically reproducible (seeded); the alignment itself is deterministic NumPy/scipy.
### Results — the decomposition (mean over divergence, reps)
| condition | naive barrier | removable (coordinate) | **residual (isolation)** |
|---|---|---|---|
| `shared` (same task, shared fork) | 0.00 | 0.00 | **0.00** |
| `independent` (same task, different init) | 0.056 | 0.055 | **0.001** |
| `conflict` (conflicting label maps) | 0.496 | 0.000 | **0.496** |
| condition | naive barrier | residual (permutation) | **residual (full symmetry group)** | merged acc |
|---|---|---|---|---|
| `shared` (same task, shared fork) | 0.000 | 0.000 | **0.000** | 0.964 |
| `independent` (same task, different init) | 0.044 | 0.001 | **0.001** | 0.960 (= parents) |
| `conflict` (contradictory label maps) | 0.502 | 0.502 | **0.497** | **0.037 (inviable)** |
- **`independent`**: two nets trained *from different random inits* on the *same task* have a real naive
barrier — which alignment **removes ~98%** of (residual 0.001). Same species, different basis: the
incompatibility is a coordinate artefact. (This reproduces the canonical Git Re-Basin result and
proves our alignment works.)
- **`conflict`**: two nets that learned *conflicting* functions have a large barrier that alignment
**removes none** of (residual 0.496). Different species: genuine reproductive isolation. Because
alignment demonstrably works on `independent`, this residual cannot be dismissed as a failure to align.
- The **residual after alignment** is therefore the clean discriminator: ~0 for compatible models (even
independently trained), large only for functionally incompatible ones.
- **`independent`**: the barrier is a coordinate artefact — permutations already remove ~98%, and the
full symmetry group confirms (residual 0.001). The aligned merge performs **at parent level**
(0.960): same species, different basis.
- **`conflict`**: the full symmetry group removes essentially nothing (0.502 → 0.497). The residual is
**functional**, not a missed symmetry — and the hybrid is functionally dead (accuracy 0.037).
Because the same aligner erased the independent-init barrier, this cannot be a failure to align.
- Formal floor (SI note S1, `paper/si-notes.md`): for label maps conflicting on mass `μ(S)`, *any*
single merged model errs at rate ≥ `μ(S)/2` against at least one parent, under *any* alignment
group and merge operator — hybrid disadvantage is information-theoretic, and endpoints/chord are
invariant to all function-preserving transformations.
### Results — the isolation cliff (`speciation_real_cliff/`)
Sweeping the fraction of classes on which child B learns a *conflicting* label map, the residual
(after-alignment) barrier rises monotonically — the real-weight image of E12's cliff:
Sweeping the fraction of conflicting classes (residual = full-symmetry alignment; `t_div=800`):
| conflict fraction | 0.0 | 0.2 | 0.4 | 0.6 | 0.8 | 1.0 |
|---|---|---|---|---|---|---|
| residual barrier | 0.00 | 0.13 | 0.19 | 0.28 | 0.40 | 0.49 |
| residual barrier | 0.000 | 0.122 | 0.187 | 0.278 | 0.406 | 0.506 |
| **merged (hybrid) accuracy** | 0.968 | 0.764 | 0.586 | 0.396 | 0.199 | 0.034 |
residual = naive at every point (alignment removes nothing in the conflict condition), so the cliff is
genuinely functional isolation, not a coordinate artefact.
`residual_scale ≈ residual` at every point (±0.005): the cliff is functional isolation under the full
symmetry group. Read as **hybrid fitness**, the merged model's accuracy falls 0.97 → 0.03 — the
real-weight image of E12's *compatible → outbreeding depression → hybrid inviability* trajectory.
### Results — emergent divergence does NOT speciate (`speciation_real_emergent/`, E13b)
The conflict condition *imposes* contradiction; a true BDM incompatibility is *emergent*. Two
pre-registered conditions with **no conflicting training signal anywhere**: `disjoint` (child A trains
only on classes 04, child B on 59) and `augment` (same labels, inputs rolled ±3 px), swept to
`t_div = 3200` (children trained 6.4× longer than the shared base):
- **Residual barrier = 0.000 at every divergence, both conditions** (naive barrier is 0 too — the
children never leave the shared basin).
- The `disjoint` parents decay to 0.535/0.474 on the full task (each forgets the other's classes),
while the **merged model holds ≈ 0.955 at every divergence** — a sustained ~40-point
**FisherMuller rescue** of two catastrophically-forgetting specialists, at zero barrier.
`augment` shows the same shape (parents 0.65/0.73, merge ≈ 0.90).
**Honest conclusion (the pre-registered second reading):** in this regime — shared ancestry, same
architecture, compatible tasks, divergence up to 3200 steps — **model speciation does not emerge
spontaneously; reproductive isolation requires functional conflict.** Trained networks are *more*
merge-compatible than the biological analogy predicts, and the design rule sharpens: *merge freely
across divergently-specialised lineages of shared ancestry — the danger is conflicting conventions,
not specialisation per se.* Scope caveat: small MLPs, one fork depth; whether long-horizon
over-specialisation at LLM scale erodes mergeability (as the expert-training-duration literature
suggests, arXiv:2607.11997) is exactly the Phase-3 `llm_speciation` question.
### Positioning
The incumbents each hold one piece: Git Re-Basin / Entezari (barriers are coordinate artefacts),
Frankle (the fork-instability protocol), Pari et al. 2024 (specialisation diverges representations,
route don't fuse), Zhou et al. 2026 (predict mergeability from divergence metrics). E13's contribution
is the synthesis they lack: a controlled decomposition where alignment cleanly partitions the merge
barrier into a **removable coordinate artefact** and a **residual reproductive-isolation** term that
rises with task conflict — the real-weight confirmation of E12's speciation prediction, and the direct
answer to "isn't this just a loss barrier / permutation artefact?" **Falsifier (not triggered):**
alignment failing to remove the independent-init barrier (then residual is meaningless), or conflict
showing no residual — instead alignment removed 98% of the former and 0% of the latter.
Git Re-Basin / Entezari (barriers as coordinate artefacts), the richer-symmetry LMC results
(2606.23607 and neuron-identifiability, 2026), Frankle (fork instability), Pari 2024 (route don't
fuse), Zhou 2026 / 2601.22285 (predict mergeability from divergence/geometry), 2603.09463
(merge-collapse capacity theory). E13's contribution is the synthesis they lack: a controlled
decomposition where alignment — *modulo the full symmetry group* — cleanly partitions the merge
barrier into a removable coordinate artefact and a **functional reproductive-isolation residual** that
rises with task conflict, is absent under compatible specialisation, and carries an
information-theoretic floor. **Falsifiers (none triggered):** alignment failing on `independent`
(would invalidate the residual); conflict showing no residual; the richer symmetry group dissolving
the conflict residual (it removed 0.005 of 0.502); emergent conditions showing residual attributable
to alignment failure.

View file

@ -1,8 +1,8 @@
{
"experiment": "speciation_real",
"master_seed": 13,
"git_commit": "56f642e7f9ae01fe01d863bdffe98b226b9dbb7b",
"python": "3.14.5",
"git_commit": "f5f68f52498402ba7cc6a5193e5e357be6357446",
"python": "3.14.7",
"libraries": {
"numpy": "2.5.0",
"scipy": "1.18.0",
@ -12,7 +12,7 @@
"torchvision": "0.27.1"
},
"rows": 45,
"results_sha256": "14b15c16ea8a43523fdc929641b8ad5741445435203d1511ecb698097da0a806",
"results_sha256": "dc77ac51b8dc92549e39edbed8d1a68469ad40de288f28672d87d1739436247a",
"layer": "1.5",
"tier": "speciation_real"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 KiB

After

Width:  |  Height:  |  Size: 234 KiB

Before After
Before After

View file

@ -1,8 +1,8 @@
{
"experiment": "speciation_real_cliff",
"master_seed": 13,
"git_commit": "56f642e7f9ae01fe01d863bdffe98b226b9dbb7b",
"python": "3.14.5",
"git_commit": "f5f68f52498402ba7cc6a5193e5e357be6357446",
"python": "3.14.7",
"libraries": {
"numpy": "2.5.0",
"scipy": "1.18.0",
@ -12,7 +12,7 @@
"torchvision": "0.27.1"
},
"rows": 18,
"results_sha256": "0252581d848376ad698f56d4e69edbcae40cf5a0f090203d6f723cfc5e25303c",
"results_sha256": "889945655a6efaba9d97eed409f24968c9f77764101bdfa05acdf00c8f8668b7",
"layer": "1.5",
"tier": "speciation_real"
}

View file

@ -0,0 +1,16 @@
# E13b — Emergent divergence (no imposed conflict): does model speciation arise spontaneously?
Companion to `results/speciation_real/` (full legend and interpretation there; figure panel C of
`speciation_real.png`). Pre-registered design: `shared` control, `disjoint` (complementary class
specialists 04 vs 59), `augment` (same labels, inputs rolled ±3 px) — **no conflicting training
signal anywhere** — swept over post-fork divergence `t_div ∈ [100, 3200]`, 4 replicates, with
alignment modulo the full ReLU unit symmetry group (E13c).
**Outcome (the pre-registered second reading):** residual barrier **0.000 at every divergence in both
emergent conditions**; the merged model **rescues** the two forgetting `disjoint` specialists
(parents → 0.535/0.474; merge ≈ 0.955 throughout — a sustained FisherMuller rescue at zero barrier).
**Speciation requires functional conflict; it does not emerge from compatible specialisation on shared
ancestry in this regime.** An honest bound on the biological analogy, and a positive design result:
merging complementary specialists of shared ancestry is safe — the danger is conflicting conventions,
not specialisation. LLM-scale over-specialisation is the open tier (`llm_speciation`, PNAS work order
Phase 3).

View file

@ -0,0 +1,18 @@
{
"experiment": "speciation_real_emergent",
"master_seed": 813,
"git_commit": "f5f68f52498402ba7cc6a5193e5e357be6357446",
"python": "3.14.7",
"libraries": {
"numpy": "2.5.0",
"scipy": "1.18.0",
"pandas": "3.0.3",
"pyarrow": "24.0.0",
"torch": "2.12.1",
"torchvision": "0.27.1"
},
"rows": 72,
"results_sha256": "95c626e0d1854690b0ad6ceaf696caa1cff005104a0814cc044c0b6b2604482b",
"layer": "1.5",
"tier": "speciation_real"
}

View file

@ -0,0 +1,32 @@
experiment: speciation_real_emergent
seed: 813
n_replicates: 4
source_config:
experiment: speciation_real_emergent
kind: speciation_real
seed: 813
n_replicates: 4
speciation_real:
sizes:
- 784
- 512
- 512
- 10
conditions:
- shared
- disjoint
- augment
t_div:
- 100
- 200
- 400
- 800
- 1600
- 3200
base_steps: 500
lr: 0.05
batch: 128
n_eval: 2000
data_root: data
output:
dir: results/speciation_real_emergent

View file

@ -66,6 +66,41 @@ def weight_matching(params_a: list, params_b: list, rng: np.random.Generator,
return perms
def canonicalise_scale(params: list, eps: float = 1e-12) -> list:
"""Remove the per-unit positive-rescaling symmetry (ReLU nets): a canonical representative.
For a ReLU MLP, scaling hidden unit ``i`` of layer ``k`` ``(W_k[i,:], b_k[i]) *= c`` and
``W_{k+1}[:,i] /= c`` with ``c > 0`` preserves the function exactly (positive homogeneity of
ReLU). Together with permutations this is the *full* function-preserving unit symmetry group of a
plain ReLU MLP, and recent work (arXiv:2606.23607; neuron-identifiability LMC) shows richer groups
than permutations remove more of the merge barrier. Canonicalising both models first rescaling
every hidden unit so its incoming ``(W, b)`` vector has unit L2 norm, pushing the norm into the
outgoing weights makes the subsequent permutation matching scale-invariant, so the residual
barrier is measured modulo the *whole* symmetry group, not just permutations.
Layers are processed first-to-last (rescaling layer ``k`` changes layer ``k+1``'s rows before they
are themselves normalised), which yields a unique representative up to permutation. Deterministic;
function-preserving (asserted by tests).
Args:
params (list[tuple[np.ndarray, np.ndarray]]): ``(W, b)`` per linear layer; ``W`` is ``[out, in]``.
eps (float): guard for dead units with ~zero incoming norm (left unscaled).
Returns:
list[tuple[np.ndarray, np.ndarray]]: the canonicalised copy (input unchanged).
"""
out = [(W.copy(), b.copy()) for W, b in params]
hidden = len(out) - 1
for k in range(hidden):
W, b = out[k]
norms = np.sqrt((W ** 2).sum(axis=1) + b ** 2) # per-unit incoming (W, b) L2 norm
scale = np.where(norms > eps, norms, 1.0)
out[k] = (W / scale[:, None], b / scale)
Wn, bn = out[k + 1]
out[k + 1] = (Wn * scale[None, :], bn) # push the norm into the outgoing weights
return out
def apply_perms(params: list, perms: list) -> list:
"""Return a copy of ``params`` with hidden-unit permutations applied (rows of k, columns of k+1)."""
out = [(W.copy(), b.copy()) for W, b in params]

View file

@ -15,9 +15,20 @@ empirical question this experiment answers:
- ``conflict`` the children learn *conflicting* label maps (B's labels cyclically shifted):
genuinely incompatible functions on shared capacity. A large barrier that alignment *cannot* remove
(residual stays high) true reproductive isolation. "Different species."
- ``disjoint`` (E13b, *emergent* divergence) child A keeps training only on classes 04, child B only
on 59: no contradiction anywhere (a true DobzhanskyMuller setting each lineage's changes are
harmless alone). Does a residual barrier *emerge* with divergence, without imposed conflict? And does
the *merged* model first rescue the two forgetting specialists (FisherMuller) then fail (speciation)
as divergence grows E12's compatible → depression → inviability curve, emergent in real weights?
- ``augment`` (E13b, conventions) same task and labels, but A trains on images rolled +3 px and B on
images rolled 3 px: representational conventions drift with zero output conflict.
The discriminating metric is the **residual** (barrier after alignment): ~0 for ``shared`` and
``independent`` (compatible the incompatibility, if any, is coordinate), large for ``conflict``.
Alignment is reported at two levels (E13c): permutation-only (Git Re-Basin, ``residual``) and
**scale-canonicalised + permutation** (``residual_scale``) the *full* function-preserving unit
symmetry group of a plain ReLU MLP so the residual cannot be attributed to a symmetry the aligner
missed (cf. arXiv:2606.23607). Merged-model (midpoint) accuracies are recorded alongside the barriers.
Divergence is swept via post-fork training steps ``t_div``. Small no-BatchNorm MLPs on MNIST the clean
Re-Basin regime. Statistically reproducible (seeded); NumPy/scipy alignment is deterministic.
@ -30,7 +41,7 @@ from typing import Any, Mapping
import numpy as np
import pandas as pd
from .rebasin import apply_perms, barrier, weight_matching
from .rebasin import apply_perms, barrier, canonicalise_scale, interpolate, weight_matching
from .train import seed_everything
@ -114,10 +125,19 @@ def run_speciation_real(cfg: Mapping[str, Any], seed: int) -> pd.DataFrame:
y2[ytr == int(c)] = int(c2)
return y2
def _rolled(px):
"""Images shifted horizontally by ``px`` pixels (a representational convention; labels intact)."""
return torch.roll(Xtr.reshape(-1, 28, 28), shifts=px, dims=2).reshape(-1, 784)
def subset(cond, child, conflict_frac):
"""(X, y) the child trains on for a given condition."""
if cond == "conflict" and child == 1:
return Xtr, _conflict_labels(conflict_frac) # B learns a conflicting label map
if cond == "disjoint": # emergent DMI: disjoint, compatible tasks
mask = (ytr < 5) if child == 0 else (ytr >= 5)
return Xtr[mask], ytr[mask]
if cond == "augment": # emergent conventions: same task, shifted views
return _rolled(3 if child == 0 else -3), ytr
return Xtr, ytr # shared / independent / conflict-A: normal task
# Two modes: (1) conditions x t_div decomposition; (2) a conflict-fraction isolation cliff.
@ -150,16 +170,36 @@ def run_speciation_real(cfg: Mapping[str, Any], seed: int) -> pd.DataFrame:
pA, pB = children
probe = _mlp(sizes, device); loss_fn = make_loss_fn(probe)
b_naive = barrier(pA, pB, loss_fn)
# E13: permutation-only alignment (Git Re-Basin) — the coordinate artefact.
perms = weight_matching(pA, pB, np.random.default_rng(ss + 5))
b_aligned = barrier(pA, apply_perms(pB, perms), loss_fn)
pB_perm = apply_perms(pB, perms)
b_aligned = barrier(pA, pB_perm, loss_fn)
# E13c: scale-canonicalise both, then match — the FULL ReLU unit symmetry group, so the
# residual cannot be blamed on a symmetry the aligner missed (arXiv:2606.23607).
cA, cB = canonicalise_scale(pA), canonicalise_scale(pB)
perms_c = weight_matching(cA, cB, np.random.default_rng(ss + 5))
cB_al = apply_perms(cB, perms_c)
b_scale = barrier(cA, cB_al, loss_fn)
# E13b money curve: the merged (midpoint) model vs its parents on the full task.
accA, accB = 1 - loss_fn(pA)[1], 1 - loss_fn(pB)[1]
acc_mid_naive = 1 - loss_fn(interpolate(pA, pB, 0.5))[1]
acc_mid_aligned = 1 - loss_fn(interpolate(pA, pB_perm, 0.5))[1]
acc_mid_scale = 1 - loss_fn(interpolate(cA, cB_al, 0.5))[1]
rows.append({
"condition": cond, "t_div": t_div, "conflict_frac": conflict_frac, "replicate": rep,
"barrier_naive": b_naive["error_barrier"],
"barrier_aligned": b_aligned["error_barrier"],
"removable": b_naive["error_barrier"] - b_aligned["error_barrier"],
"residual": b_aligned["error_barrier"],
"barrier_aligned_scale": b_scale["error_barrier"],
"removable_scale": b_naive["error_barrier"] - b_scale["error_barrier"],
"residual_scale": b_scale["error_barrier"],
"loss_barrier_naive": b_naive["loss_barrier"],
"loss_barrier_aligned": b_aligned["loss_barrier"],
"loss_barrier_scale": b_scale["loss_barrier"],
"acc_parent_a": accA, "acc_parent_b": accB,
"acc_merge_naive": acc_mid_naive,
"acc_merge_aligned": acc_mid_aligned,
"acc_merge_scale": acc_mid_scale,
"parent_acc": (accA + accB) / 2.0})
return pd.DataFrame(rows)

View file

@ -5,7 +5,7 @@ from __future__ import annotations
import numpy as np
import pytest
from neural.rebasin import apply_perms, barrier, interpolate, weight_matching
from neural.rebasin import apply_perms, barrier, canonicalise_scale, interpolate, weight_matching
def _mlp(sizes, rng):
@ -64,3 +64,44 @@ def test_apply_perms_preserves_function():
perms = [rng.permutation(7), rng.permutation(7)]
X = rng.standard_normal((16, 4))
assert np.allclose(_forward(A, X), _forward(apply_perms(A, perms), X))
def _rescale(params, scales_per_layer):
# Apply the positive per-unit rescaling symmetry: unit i of hidden layer k scaled by c>0.
out = [(W.copy(), b.copy()) for W, b in params]
for k, scales in enumerate(scales_per_layer):
W, b = out[k]
out[k] = (W * scales[:, None], b * scales)
Wn, bn = out[k + 1]
out[k + 1] = (Wn / scales[None, :], bn)
return out
def test_canonicalise_scale_preserves_function_and_normalises():
rng = np.random.default_rng(6)
A = _mlp([5, 9, 9, 2], rng)
C = canonicalise_scale(A)
X = rng.standard_normal((24, 5))
assert np.allclose(_forward(A, X), _forward(C, X), atol=1e-8) # function-preserving (ReLU homogeneity)
for k in range(len(C) - 1): # every hidden unit's (W, b) is unit-norm
W, b = C[k]
assert np.allclose(np.sqrt((W ** 2).sum(axis=1) + b ** 2), 1.0)
def test_weight_matching_recovers_permutation_and_rescaling():
# A permuted AND positively-rescaled copy is functionally identical; permutation-only matching can
# miss it, but canonicalise-then-match must realign it to functional identity — the full ReLU
# symmetry group (the E13c referee-proofing gate).
rng = np.random.default_rng(7)
A = _mlp([6, 12, 12, 3], rng)
B = apply_perms(_rescale(A, [np.exp(rng.uniform(-2, 2, 12)), np.exp(rng.uniform(-2, 2, 12))]),
[rng.permutation(12), rng.permutation(12)])
X = rng.standard_normal((32, 6))
assert np.allclose(_forward(A, X), _forward(B, X), atol=1e-6) # symmetry-equivalent copy
cA, cB = canonicalise_scale(A), canonicalise_scale(B)
perms = weight_matching(cA, cB, np.random.default_rng(8))
B_aligned = apply_perms(cB, perms)
assert np.allclose(_forward(cA, X), _forward(B_aligned, X), atol=1e-5) # realigned exactly
# and the aligned weights themselves coincide (canonical form is unique up to permutation)
for (Wa, ba), (Wb, bb) in zip(cA, B_aligned):
assert np.allclose(Wa, Wb, atol=1e-6) and np.allclose(ba, bb, atol=1e-6)