epistasis_predicts: functional conflict, not weight geometry, predicts merge failure pre-merge
The decisive experiment from the external review. 39 LoRA parent pairs (0.5B, 3 seeds) on three axes decorrelated by construction: conflict (contradictory conventions on shared prompts, private budgets fixed), compat (same prompts, SAME convention — overlap without conflict), and duration (weight divergence, zero conflict). Six pre-merge predictors; primary outcome = merge penalty (parent potential − merged achieved). League table (Spearman vs penalty, n=39): functional measures predict (dis_raw +0.460, epi_conf +0.446, p<0.005); geometry collapses (delta_cos +0.03, delta_l2 +0.17 n.s.); gradient alignment weak (−0.35); performance ~0. The first grid's apparent geometry win (+0.60) was an overlap/volume artifact — the compat control axis (added for exactly this) exposed and killed it: same overlap and data volume, zero penalty. Honest riders in the README: confidence weighting does not beat raw disagreement as a rank predictor (pre-registered internal prediction not confirmed; it does double the conflict/compat level contrast), and |rho|~0.45 is bounded by 0.5B merge-outcome noise (7B is the firm-up). Also: micro-batched gradient accumulation (OOM fix on the shared 16GB GPU), exact r-space LoRA-delta geometry (brute-force-verified test, 151 green), systemd-run runbook lesson (tmux dies with the SSH session scope on this box). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BkRLcc18rwT2Lysu6PbG7v
This commit is contained in:
parent
5a23ddaf2a
commit
287d2326cc
16 changed files with 622 additions and 3 deletions
87
figures/plot_llm_epistasis.py
Normal file
87
figures/plot_llm_epistasis.py
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
"""The decisive-experiment figure — does pre-merge epistasis predict merge failure?
|
||||
|
||||
(A) The theory's predictor: operational epistasis (confidence-weighted bilateral disagreement,
|
||||
measured before merging) against the merge penalty (parent potential − merged achieved, the
|
||||
hybrid-load analogue). Conflict-axis pairs in red, duration-axis pairs in blue.
|
||||
|
||||
(B) The geometry predictor on the same outcome: weight divergence (LoRA-delta L2) — the
|
||||
matched-divergence contrast: the duration axis spans large weight divergence at ~zero penalty, while
|
||||
the conflict axis generates penalty at modest divergence. Distance is not what breaks merging.
|
||||
|
||||
(C) The league table: |Spearman rho| against the merge penalty for every pre-merge predictor,
|
||||
including the internal ablation (raw disagreement, which the theory predicts must mislead because it
|
||||
counts harmless complementation as conflict).
|
||||
|
||||
Usage: python figures/plot_llm_epistasis.py
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from scipy.stats import spearmanr
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).parent))
|
||||
from _figlib import load_bundle, savefig # noqa: E402
|
||||
|
||||
PREDICTORS = [("epi_conf", "operational\nepistasis"),
|
||||
("dis_raw", "raw\ndisagreement"),
|
||||
("grad_cos", "gradient\nalignment"),
|
||||
("delta_cos", "delta\ncosine"),
|
||||
("delta_l2", "delta\nL2"),
|
||||
("cross_perf", "cross-family\naccuracy")]
|
||||
OUTCOME = "merge_penalty"
|
||||
|
||||
|
||||
def _scatter(ax, df, xcol, xlabel, title):
|
||||
for mode, color, marker in (("conflict", "#d62728", "o"), ("duration", "#2c7fb8", "s"),
|
||||
("compat", "#41ab5d", "^")):
|
||||
sub = df[df["mode"] == mode]
|
||||
ax.scatter(sub[xcol], sub[OUTCOME], c=color, marker=marker, s=42, alpha=0.75,
|
||||
label=f"{mode} axis")
|
||||
rho, p = spearmanr(df[xcol], df[OUTCOME])
|
||||
ax.set(xlabel=xlabel, ylabel="merge penalty (parent potential − merged)",
|
||||
title=f"{title}\nSpearman ρ = {rho:.2f} (p = {p:.1g}, n = {len(df)})")
|
||||
ax.axhline(0, color="#999", lw=0.6)
|
||||
ax.legend(frameon=False, fontsize=8)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
import pandas as pd
|
||||
df, _ = load_bundle("results/llm_epistasis")
|
||||
try: # the overlap-without-conflict control axis
|
||||
compat, _ = load_bundle("results/llm_epistasis_compat")
|
||||
df = pd.concat([df, compat], ignore_index=True)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
fig, axes = plt.subplots(1, 3, figsize=(16.5, 4.9))
|
||||
_scatter(axes[0], df, "epi_conf", "operational epistasis (pre-merge)",
|
||||
"(A) the theory's predictor")
|
||||
_scatter(axes[1], df, "delta_cos", "LoRA-delta cosine similarity (pre-merge)",
|
||||
"(B) the geometry predictor — does it detect\nincompatibility, or just task overlap?")
|
||||
|
||||
ax = axes[2]
|
||||
rhos, labels = [], []
|
||||
for col, label in PREDICTORS:
|
||||
rho, _ = spearmanr(df[col], df[OUTCOME])
|
||||
rhos.append(abs(rho)); labels.append(label)
|
||||
colors = ["#d62728" if c == "epi_conf" else ("#fc9272" if c == "dis_raw" else "#9ecae1")
|
||||
for c, _ in PREDICTORS]
|
||||
x = np.arange(len(rhos))
|
||||
ax.bar(x, rhos, 0.62, color=colors)
|
||||
ax.set_xticks(x); ax.set_xticklabels(labels, fontsize=7)
|
||||
ax.set(ylabel="|Spearman ρ| vs merge penalty", ylim=(0, 1),
|
||||
title="(C) predictor league table (pre-merge only)")
|
||||
|
||||
fig.suptitle("Predicting merge failure BEFORE merging: functional conflict, not weight divergence "
|
||||
"(conflict, overlap-without-conflict, and divergence decorrelated by construction; 3 seeds)", y=1.03, fontsize=12)
|
||||
fig.tight_layout()
|
||||
savefig(fig, "results/llm_epistasis", "llm_epistasis")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue