Downloads · 30 days
0
recoilme/losslessmix-dit
losslessmix-dit is a machine learning model from recoilme. Use it for the machine learning task on the model card, and read the license before you ship it in a product.
Reduce the depth of a diffusion transformer (DiT) by merging pairs of adjacent residual blocks — without quantization and without training.
Downloads · 30 days
0
Access
Public
Updated Aug 28, 2026
Repo size
—
Likes
0
Public
Click a slice to open those files.
.py8.2 KB · 64%
From the Hugging Face model README
Reduce the depth of a diffusion transformer (DiT) by merging pairs of adjacent residual blocks — without quantization and without training.
A DiT block is residual: x -> x + F(x). Two adjacent blocks compose as
B_j(B_i(x)) = x + F_i(x) + F_j(x + F_i(x))
Merging a pair into one block is lossy. The goal is to lose as little as possible:
Merge step — blend the two blocks' weights per channel by the absolute cosine similarity of their weight vectors:
k = clamp(cos(W_i, W_j), 0, 1)
W = W_i * k + W_j * (1 - k)
W_j entirely.So incompatible features are never averaged into garbage — that's the "lossless" part, inherited from recoilme/losslessmix.
Which pairs? Rank every block by block influence, measured on real activations:
BI_i = 1 - cos(x_i, x_{i+1}) # 0 = block is ~identity
Then greedily pick the emptiest (lowest combined BI) non-overlapping adjacent pairs, protecting the edge blocks (first/last and their neighbours), which are load-bearing.
BI and pairwise S.BI, non-overlapping, protect edges.merge_pair blends each pair into one block via cosine_merge_2d.| measure | value |
|---|---|
| 5 merged pairs | 2.17B params = 4.34 GB = 16.9% of the DiT |
| quality | near-zero CLIP degradation on simple prompts |
| merge method | absolute cosine > relative min-max |
| pair selection | by BI (emptiness) > by S (similarity) |
Beyond ~6 pairs (≈22 blocks) the degradation cliff appears — diffusion is iterative, so small per-block errors amplify over the denoising steps.
from diffusers import DiffusionPipeline
from merge_dit import analyze_blocks, select_pairs, apply_merges
pipe = DiffusionPipeline.from_pretrained("krea/Krea-2-Raw", torch_dtype=torch.bfloat16)
tr = pipe.transformer
blocks = tr.transformer_blocks
# 1. measure BI / S (run_forward runs one full transformer forward)
bi, S = analyze_blocks(tr, run_forward, n_passes=24)
# 2. pick pairs
pairs = select_pairs(bi, S, k=5, protect_head=2, protect_tail=2)
# 3. merge
apply_merges(blocks, pairs)
# update config and save / generate as usual
tr.register_to_config(num_layers=len(blocks))
B_j(B_i(x)). A naive functional (least-squares) fit of the composition
overfit on few samples and was worse than this weight merge.merge_dit.py — the algorithm (merge + analyze + select + apply).