mixle.experimental.tying_discovery module¶
Tying discovery via arrangement similarity – the neural half of ConditionalJIT (H4).
The R1 copula note (see the roadmap doc, R1 -> G4, F6, I2, H4) observes that any weight tensor’s flattened
value vector v decomposes as v = P . s: a sorted profile s (the empirical quantile function –
the values in sorted order) composed with a permutation P (the arrangement – which sorted rank each
original position maps to). That is exactly Sklar’s theorem one level down: a joint distribution factors into
marginals (here: the profile / value distribution) and a dependence structure (here: the arrangement). This
module uses only the marginal half of that decomposition as a discovery signal: two tensors whose PROFILES
are close are, value-distribution-wise, “the same numbers, differently arranged” – exactly the situation a
weight tie (two module attributes sharing one nn.Parameter, the tensor analogue of this codebase’s
keys= mechanism for tying distribution parameters across combinator children, see
mixle.stats.combinator) can exploit for a real, measurable parameter reduction.
This module deliberately stays on the “discovery” side of the R1 note. Training a permutation (differentiable
OT / Sinkhorn / torchsort) is explicitly out of scope here – profile comparison via sorted-vector L2 distance
is closed-form and needs no optimization loop. See profile_distance() for why sorted-vector L2 already
is the right 1-D optimal-transport quantity for this purpose.
Workflow:
tensor_profile()– extract a fixed-length quantile-function profile from a weight tensor.profile_distance()– an L2 distance between two profiles (= 1-D Wasserstein-2 distance between the corresponding empirical distributions).propose_ties()– rank all pairs of named tensors by profile distance and return the most promising tying candidates.apply_tie()– actually replace two tensors with one sharednn.Parameterand report a measured output-parity receipt (the model is NOT guaranteed function-preserving by a tie; the receipt is the honest, measured delta, not an assumed zero).
Everything here lives in mixle/experimental/ per F7: it graduates out once the mechanism has field mileage
and (once merged) should be registered against E0’s graduation ledger – a trivial follow-up, not done here
since mixle/experimental/graduation.py does not yet exist on this branch.
- tensor_profile(tensor, n_quantiles=256)[source]
Return the fixed-length quantile-function profile of a tensor’s values.
The profile is the empirical quantile function of the tensor’s flattened values: sort the values, then resample that sorted curve onto
n_quantilesevenly spaced quantile positions in[0, 1]by linear interpolation. Fixingn_quantilesmakes profiles from differently shaped/sized tensors directly comparable (a(64, 64)weight and a(32, 128)weight both reduce to a length-n_quantilescurve).This throws away the ARRANGEMENT entirely (sorting is exactly “forget the permutation P in v = P . s”) and keeps only the value distribution – by design, since arrangement similarity is not what tying discovery is asking about here: two tensors that hold “the same numbers” but scattered into different spatial slots are still excellent tying candidates once one of them is permuted (or once the model is simply insensitive to which of the two arrangements it uses, which the parity receipt in
apply_tie()checks directly).- Parameters:
tensor (Any) – A torch tensor of any shape (or anything
torch.as_tensoraccepts).n_quantiles (int) – Number of fixed quantile positions to resample the sorted values onto. Must be >= 2. Default 256 is small enough to be cheap and large enough that two profiles from differently-shaped tensors compare fairly.
- Returns:
A 1-D torch tensor of length
n_quantiles, dtype float32, containing the interpolated quantile function.- Return type:
- profile_distance(profile_a, profile_b)[source]
L2 distance between two equal-length quantile-function profiles.
Sorted-vector-vs-sorted-vector L2 distance between two empirical quantile functions IS the (discretized) 1-D Wasserstein-2 distance between the two underlying empirical distributions – a standard, well-known fact worth stating explicitly rather than leaning on silently: for 1-D distributions, the optimal transport coupling between two empirical measures is exactly the sorted-to-sorted (rank-to-rank) matching, so
W2(mu, nu) = ||sort(x) - sort(y)||_2up to the1/sqrt(n_quantiles)normalization used here. That is also thev = P . sdecomposition’s marginal half compared directly: two tensors with identical profiles (profile_distance == 0) hold the same multiset of values up to arrangement, i.e. one is some permutation of the other – the exact condition a weight tie wants.
- class TyingCandidate(name_a, name_b, distance, shape_a, shape_b)[source]
Bases:
objectA single proposed weight tie between two named tensors.
- name_a
Name of the first tensor (as passed into
propose_ties()).- Type:
- name_b
Name of the second tensor.
- Type:
- distance
Profile distance between the two tensors (lower = more similar = better candidate).
- Type:
- propose_ties(named_tensors, n_quantiles=256, max_distance=None, top_k=None)[source]
Propose weight-tying candidates by pairwise profile similarity across a set of named tensors.
Computes a
tensor_profile()for every tensor, then ranks all pairs byprofile_distance()(ascending – most similar first). This is the discovery step of H4: the analogue of scanning distribution combinators for parameters that could share akeys=tag, applied to torch tensors instead.- Parameters:
named_tensors (dict[str, Any]) – Mapping from a tensor name (e.g.
"layer0.head2.q") to the tensor itself. Tensors may have different shapes – profiles fix that via resampling.n_quantiles (int) – Passed through to
tensor_profile().max_distance (float | None) – If given, only pairs with
distance <= max_distanceare returned. Left unset (None) by default so callers can inspect the full ranked list and pick a threshold.top_k (int | None) – If given, only the
top_kclosest pairs are returned (aftermax_distancefiltering, if any).
- Returns:
- Candidates sorted by ascending distance (most similar / best tying candidate
first).
- Return type:
list[TyingCandidate]
- class ParityReceipt(max_abs_diff, relative_l2, params_before, params_after)[source]
Bases:
objectMeasured output-parity receipt for a function-preserving-edit attempt.
- max_abs_diff
Max absolute elementwise difference between pre- and post-edit outputs.
- Type:
- relative_l2
||after - before||_2 / ||before||_2(0 ifbeforeis identically zero).- Type:
- params_before
Total parameter count before the edit.
- Type:
- params_after
Total parameter count after the edit.
- Type:
- property params_reduced: int
Absolute parameter-count reduction (>= 0 for a real tie; can be 0 if no sharing occurred).
- property params_reduced_fraction: float
Fractional parameter-count reduction, in
[0, 1].
- apply_tie(module, name_a, name_b, inputs, strategy='average')[source]
Apply a proposed weight tie to two
nn.Parameterattributes onmoduleand measure the parity cost.Replaces the two named parameters with ONE shared
nn.Parameter(both attributes point at the same tensor object afterward, so a gradient step on either updates both – an actual, literal tie, not merely initializing them equal).strategypicks the shared value:"average"(default): elementwise mean of the two original tensors. Requires identical shapes. This is the natural choice when the two tensors are similar-valued-but-not-identical (the realistic case tying discovery is meant to catch, per the H4 acceptance note) – it minimizes the summed squared perturbation to both tensors simultaneously."keep_a": keepname_a’s tensor verbatim and pointname_bat it. Useful when one tensor is trusted more (e.g. it trained longer, orname_ais canonical by convention).
Weight tying is NOT assumed to be output-preserving – it is exactly a bet that it will be nearly so, which is what the profile-similarity threshold in
propose_ties()is for. This function does not enforce any tolerance itself; it measures and returns the actual delta via a forward pass oninputsbefore and after the edit, so the caller can decide whether the receipt is acceptable.- Parameters:
module (Any) – A
torch.nn.Modulewhose forward pass is deterministic giveninputs(caller should.eval()it first if it contains dropout/batchnorm-type layers).name_a (str) – Dotted attribute path to the first
nn.Parameter(e.g."blocks.0.attn.qkv.weight").name_b (str) – Dotted attribute path to the second
nn.Parameter. Must have the same shape asname_a.inputs (Any) – Whatever
module(inputs)accepts; used for the before/after forward pass.strategy (str) –
"average"or"keep_a"; see above.
- Returns:
measured output delta and parameter-count change.
- Return type:
ParityReceipt