AlexWortega's picture
Upload index.html with huggingface_hub
6b97d31 verified
Raw
History Blame Contribute Delete
13.8 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Weight-Space Geometry of Offline Reasoning Training</title>
<meta name="description" content="An interactive look at the weight-space geometry of six offline reasoning losses trained on identical data." />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600&family=Newsreader:ital,opsz,wght@0,6..72,400;0,6..72,500;0,6..72,600;1,6..72,400;1,6..72,500&family=IBM+Plex+Mono:wght@400;500&display=swap" rel="stylesheet" />
<script src="https://cdn.plot.ly/plotly-2.35.2.min.js" charset="utf-8"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css" />
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js"></script>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<a class="skip" href="#abstract">Skip to content</a>
<nav id="toc" aria-label="Table of contents">
<div class="toc-inner">
<div class="toc-title">Contents</div>
<ol>
<li><a href="#abstract">Abstract</a></li>
<li><a href="#reading">Reading the geometry</a></li>
<li><a href="#methods">The six losses</a></li>
<li><a href="#cosine">Cosine map</a></li>
<li><a href="#perlayer">Layer by layer</a></li>
<li><a href="#cka">Representations (CKA)</a></li>
<li><a href="#svd">Output subspace</a></li>
<li><a href="#angles">Principal angles</a></li>
<li><a href="#geometry">Update geometry</a></li>
<li><a href="#lmc">Mode connectivity</a></li>
<li><a href="#accuracy">Accuracy</a></li>
<li><a href="#seedlr">Seed &amp; LR</a></li>
<li><a href="#takeaways">Takeaways</a></li>
</ol>
</div>
</nav>
<main>
<header class="hero">
<div class="venue" id="venue"></div>
<h1 id="title"></h1>
<p class="lede" id="subtitle"></p>
<div class="byline">
<a id="paperlink" href="#" target="_blank" rel="noopener">paper ↗</a>
· interactive companion ·
<a id="repolink" href="#" target="_blank" rel="noopener">source &amp; data ↗</a>
</div>
</header>
<section id="abstract" class="aside">
<h2>Abstract</h2>
<p id="abstract-text" class="dropcap"></p>
<p>
Six losses, one base model, one fixed set of math rollouts. If the data is held
identical, what does the <em>choice of loss</em> actually do to the weights? This page
lets you turn the same knobs we did — pick method pairs, scrub across all 36 layers,
and watch each geometric metric respond.
</p>
</section>
<section id="reading" class="aside">
<h2>Reading the geometry</h2>
<p>
Every chart below is computed on the LoRA weight update <strong>ΔW</strong> — the small
change each method writes into the base model — or on the representations that update
produces. Four tools, each asking a different version of <em>“are these two the same?”</em>
</p>
<div class="note">
<dl class="glossary">
<div>
<dt>Cosine similarity</dt>
<dd>Do two weight updates point the same way? <b>+1</b> = identical direction, <b>0</b> = orthogonal (unrelated), <b>below 0</b> = opposed. This is the headline number, taken on the stacked ΔW.</dd>
</div>
<div>
<dt>Principal angles</dt>
<dd>How far apart are the <b>subspaces</b> the two updates span — a basis-free generalization of cosine. A few degrees means effectively the same subspace; near 90° means disjoint.</dd>
</div>
<div>
<dt>Mode connectivity<span>linear · LMC</span></dt>
<dd>Interpolate between two trained adapters and watch the loss. A flat path means they sit in the <b>same basin</b>; a bump in the middle is a barrier separating two different solutions.</dd>
</div>
<div>
<dt>CKA<span>centered kernel alignment</span></dt>
<dd>Do the two models compute the same thing <b>inside</b>? Unlike the others, CKA compares hidden representations, not weights. <b>≈1</b> = near-identical computation; lower means the circuit has been rewired.</dd>
</div>
</dl>
</div>
</section>
<section id="methods">
<h2>The six losses</h2>
<p>
Every method is trained on the same rollouts from Qwen3-4B-Instruct with attention-only
LoRA (q, k, v, o; rank 32). They differ only in how the loss treats negatives, reward,
and a reference policy.
</p>
<figure class="wide">
<table id="methods-table" class="methods"></table>
</figure>
<p class="block-label">The objectives, written out</p>
<div class="note">
<dl class="glossary objectives" id="objectives"></dl>
</div>
<p class="footnote">
Every objective above is token-level <strong>cross-entropy</strong>: the term
<span id="ce-eq">−𝔼 log π_θ(y∣x)</span> is exactly the CE between a rollout and the
model. SFT, RFT and RIFT are the <em>same</em> CE, only reweighted per rollout —
over all tokens, over positives only, or by reward. DFT reweights it by the
stop-gradient probability; GRPO and DPO leave the CE form entirely.
</p>
</section>
<section id="cosine">
<h2>A map of directions</h2>
<p>
Start global. Stack each method's LoRA update into a single vector ΔW and measure the
cosine between every pair. Three blocks of the matrix tell the whole story: a hot
reward-weighted cluster (SFT / RFT / RIFT), a lukewarm Offline GRPO, and a cold,
near-orthogonal DPO. Add the on-policy methods and they detach from everything offline.
</p>
<figure class="wide">
<div class="controls">
<div class="seg" role="group" aria-label="matrix size">
<button class="seg-btn active" data-mx="6">6 offline losses</button>
<button class="seg-btn" data-mx="8">+ online RL (8×8)</button>
</div>
<span class="hint">hover a cell for the value · click to inspect that pair below</span>
</div>
<div id="chart-cosine" class="plot square"></div>
<figcaption data-cap="cosine"></figcaption>
</figure>
</section>
<section id="perlayer">
<h2>Layer by layer</h2>
<p>
A single number hides where methods agree. Here is the cosine of ΔW computed
independently in each of the 36 transformer blocks. Toggle pairs and drag the slider:
the SFT family is colinear from embedding to head, while DPO and online RL stay pinned
near zero — and Offline GRPO peels away in the <em>late</em> layers.
</p>
<figure class="wide">
<div class="controls" id="perlayer-pairs"></div>
<div id="chart-perlayer" class="plot"></div>
<div class="slider-row">
<label for="layer-slider">Layer</label>
<input type="range" id="layer-slider" min="0" max="35" value="30" step="1" />
<output id="layer-readout"></output>
</div>
<figcaption data-cap="perlayer"></figcaption>
</figure>
</section>
<section id="cka">
<h2>Does it rewire the computation?</h2>
<p>
Cosine compares <em>updates</em>. CKA compares what the network actually computes —
the hidden representations. Most methods leave them almost untouched (CKA ≈ 1). DPO is
the exception: its representation similarity collapses in the final blocks, the
fingerprint of a method that changes the circuit, not just the write direction. The
layer slider is shared with the chart above.
</p>
<figure class="wide">
<div class="controls" id="cka-pairs"></div>
<div id="chart-cka" class="plot"></div>
<figcaption data-cap="cka"></figcaption>
</figure>
</section>
<section id="svd">
<h2>Same answer, different basis</h2>
<p>
Low cosine does not always mean a different solution. Decompose each ΔW and compare only
the dominant <em>output</em> direction (the top left-singular vector u). Across the SFT
family these stay aligned even where the raw vectors diverge — the updates point the same
way in output space while differing in their input-side basis, an artifact of random LoRA
initialization rather than a genuinely different circuit.
</p>
<figure class="wide">
<div class="controls" id="svd-pairs"></div>
<div id="chart-svd" class="plot"></div>
<figcaption data-cap="svd"></figcaption>
</figure>
</section>
<section id="angles">
<h2>How far apart are the subspaces?</h2>
<p>
Principal angles measure the gap between the subspaces two updates span — a basis-free
version of cosine. SFT and RFT sit about 7° apart (effectively the same subspace);
SFT and DPO open up to ~55°. Each bar is the median over 144 modules; the whisker shows
the spread of the worst of the top-10 angles.
</p>
<figure class="wide">
<div id="chart-angles" class="plot"></div>
<figcaption data-cap="angles"></figcaption>
</figure>
</section>
<section id="geometry">
<h2>Size and rank of the move</h2>
<p>
Direction is only half of it. How <em>far</em> does each loss push, and how concentrated
is the push? The SFT family travels far along a low-rank direction; DPO barely moves yet
spreads that tiny step across a much higher effective rank — a small, broad nudge versus
a large, focused shove.
</p>
<figure class="wide">
<div id="chart-geometry" class="plot"></div>
<figcaption data-cap="geometry"></figcaption>
</figure>
</section>
<section id="lmc">
<h2>One basin or two?</h2>
<p>
Linearly interpolate between two trained adapters and watch the loss. A flat or monotone
path means the two solutions share a basin; a bump in the middle is an energy barrier
separating them. SFT ↔ Offline GRPO is barrier-free — same basin. Paths into DPO climb a
wall.
</p>
<figure class="wide">
<div class="controls" id="lmc-pairs"></div>
<div id="chart-lmc" class="plot"></div>
<figcaption data-cap="lmc"></figcaption>
</figure>
</section>
<section id="accuracy">
<h2>Does the geometry show up in accuracy?</h2>
<p>
Yes — and it inverts the usual intuition. The methods that move <em>orthogonally</em> to
the SFT direction (DPO and on-policy RL) hold onto the base model's accuracy, while the
colinear SFT family drags GSM8K below base. Online GRPO posts the best AIME26.
</p>
<figure class="wide">
<div class="controls">
<div class="seg" role="group" aria-label="benchmark">
<button class="seg-btn active" data-bench="gsm8k">GSM8K</button>
<button class="seg-btn" data-bench="aime26">AIME26</button>
</div>
</div>
<div id="chart-accuracy" class="plot"></div>
<figcaption data-cap="accuracy"></figcaption>
</figure>
</section>
<section id="seedlr">
<h2>Is the geometry an artifact of seed or learning rate?</h2>
<p>
A fair worry: maybe the directions are just noise. They are not. Two seeds of the same
loss produce a low raw weight-cosine — yet the top-1 <em>output</em> direction stays at
~0.99. The disagreement is entirely in the input-side basis (random LoRA A-init), not in
the solution. Separately, a 10× learning-rate change <em>rotates</em> ΔW rather than
merely rescaling it — so DPO's smaller LR is genuinely part of its geometry.
</p>
<figure class="wide">
<div class="controls">
<div class="seg" role="group" aria-label="seed view">
<button class="seg-btn active" data-seed="cos">Raw cosine vs output dir</button>
<button class="seg-btn" data-seed="lr">LR rotates ΔW</button>
</div>
</div>
<div id="chart-seedlr" class="plot"></div>
<figcaption data-cap="seedlr"></figcaption>
</figure>
</section>
<section id="takeaways">
<h2>Takeaways</h2>
<ul class="takeaways">
<li><strong>The reward-weighted MLE family is one direction.</strong> SFT, RFT, and RIFT have cosine ≥ 0.94 and ~7° top-1 principal angle — interchangeable in weight space.</li>
<li><strong>DFT diverges the most among offline losses</strong> despite seeing identical data — the stop-gradient reshaping matters geometrically.</li>
<li><strong>Offline GRPO stays in the SFT basin but adds a large orthogonal late-layer component</strong> (up to ~86% off-SFT in the final blocks).</li>
<li><strong>DPO is the outlier:</strong> near-orthogonal subspace, a mode-connectivity barrier, late-layer CKA collapse — and the best accuracy, at a 10× smaller learning rate.</li>
<li><strong>On-policy RL is geometrically unlike everything offline.</strong> Online GRPO/DAPO are near-orthogonal to every offline loss and to each other: shared-rollout colinearity is partly an artifact of training on the same fixed data.</li>
</ul>
<p class="repro">
Base model Qwen3-4B-Instruct-2507 · attention-only LoRA (q,k,v,o, r32 a64) · DeepScaleR
math rollouts · math-verify reward. All metrics on this page are computed from the
published analysis JSON. <a id="repolink2" href="#" target="_blank" rel="noopener">Code, adapters, and raw results ↗</a>
</p>
</section>
<footer>
<p>Built as an interactive companion to <span id="footer-title"></span>. Figures rendered client-side with Plotly from the paper's released metrics.</p>
</footer>
</main>
<script src="app.js"></script>
</body>
</html>