M6.4 - The Low-Rank Adaptation Design Space: QLoRA, AdaLoRA, rsLoRA, LoRA+, LoRA-FA, PiSSA, LoftQ, and DoRA
M6.4 - The Low-Rank Adaptation Design Space: QLoRA, AdaLoRA, rsLoRA, LoRA+, LoRA-FA, PiSSA, LoftQ, and DoRA
0x00 Overview: Why LoRA Became A Design Space
M6.3 specified vanilla LoRA:
with frozen , trainable and , and usually:
That baseline contains several independent design decisions:
base representation:
full precision or quantized
rank:
fixed per matrix or allocated dynamically
scaling:
alpha/r or another rank-dependent rule
optimization:
same or different learning rates, or one frozen factor
initialization:
random/zero, spectral, gradient-aligned, or quantization-aware
weight parameterization:
additive update only or magnitude/direction decomposition
Vanilla LoRA solves one problem: it replaces an unrestricted dense update with a low-rank trainable branch. It does not decide how the frozen base should be stored, whether every module deserves the same rank, how update magnitude should behave as rank changes, how the two factors should be initialized or optimized, or whether weight magnitude and direction should be adapted together.
Those unresolved choices are why “a LoRA variant” is not one category of modification. Each method should first be located in the training and execution path.
The owner question is:
Which limitation of vanilla LoRA does each major variant change, and what does that change do to tensors, gradients, training memory, mergeability, and runtime integration?
0x00A LoRA Solved One State Problem, Not The Whole Training System
The original LoRA result was a decisive change in where a task update is stored. Instead of optimizing every entry of a dense pretrained matrix, it freezes that matrix and optimizes a low-rank product. But a training run is not described by trainable parameter count alone. It also owns a base representation, an initialization, a scale rule, an optimizer, retained activations, a checkpoint ABI, and an export path.
One useful contract is:
adaptation system =
base representation
+ update parameterization
+ initialization
+ rank and scale policy
+ backward and optimizer state
+ checkpoint and merge representation
+ runtime execution path
Vanilla LoRA changed the update parameterization. The methods in this article exist because the other coordinates remained open. A method that quantizes the frozen base and a method that changes the two factor learning rates can both be called “LoRA variants,” yet they do not solve the same bottleneck and do not produce the same artifact.
0x00B The Design Space Grew As Distinct Bottlenecks Became Visible
The relevant papers form a problem-response sequence rather than one linear replacement ladder:
| Paper lineage | Limitation made explicit | Object changed |
|---|---|---|
| AdaLoRA | equal rank at every target spends a global budget uniformly | singular-component allocation, importance state, and budget schedule |
| QLoRA | frozen weights still dominate training residency at 16 bits | frozen-base representation, dequantization path, quantization metadata, and paging policy |
| LoRA-FA | few trainable parameters do not eliminate activation retention | trainable-factor set and backward liveness |
| LoftQ | ordinary LoRA starts from a quantized base with an uncorrected representation error | coupled quantized base and low-rank initialization |
| rsLoRA | the usual rank divisor can weaken learning as rank grows | rank-dependent branch scale |
| DoRA | one additive low-rank delta couples weight magnitude and direction | trainable magnitude plus a normalized low-rank directional update |
| LoRA+ | equal factor learning rates need not preserve efficient feature learning at large width | optimizer groups and factor learning-rate ratio |
| PiSSA | random/zero factors spend early optimization discovering a useful subspace | spectral factor initialization and frozen residual base |
Dates establish lineage, not superiority. Each paper evaluates a different model/task/precision surface, and later revision numbers matter because titles, algorithms, and implementation guidance changed. Benchmark values remain source-reported until an article-local reproduction says otherwise.
The handwritten Transformer Series A22 already exposes the broader family: decomposition, pruning or freezing of adapter state, quantized bases, rank refinement and augmentation, spectral initialization, and continual composition. M6.4 narrows that survey into eight mechanism owners whose tensor, gradient, optimizer, and artifact contracts can be compared directly. Other A22 variants remain registered in the figure and source manifests rather than disappearing from the lineage.
0x00C Compare The Changed Object Before Comparing Results
The first comparison key is not benchmark score. It is the object whose state transition differs from M6.3:
| Method | Frozen or baseline object consumed | New mutable or derived object | First parity question |
|---|---|---|---|
| QLoRA | full-precision pretrained weight identity | packed codes, block metadata, dequantized compute view, floating adapter | does the declared quantized operator match the training graph? |
| AdaLoRA | fixed-rank target | SVD-like triplets, importance history, active mask, budget phase | does masked/final state reconstruct the exported rank allocation? |
| rsLoRA | fixed rank with scale | alternative rank-dependent scale | are forward and gradient comparisons made at a declared rank/alpha control? |
| LoRA+ | one optimizer group for both factors | factor-specific learning-rate groups | do saved optimizer groups preserve factor identity on resume? |
| LoRA-FA | both factors trainable | frozen projection-down factor and trainable projection-up factor | does backward omit the full-rank activation solely because the frozen factor permits it? |
| PiSSA | immutable original base plus zero initial delta | trainable principal factors plus frozen spectral residual | does residual plus factors reproduce the original function at initialization? |
| LoftQ | independently quantized base and ordinary adapter initialization | alternating quantization/error-compensation state | does the exported pair reproduce the final initialization objective? |
| DoRA | additive | magnitude vector and normalized directional weight | does merge preserve the exact column-norm convention and epsilon policy? |
This prevents a common category error: two methods may leave the eventual dense matrix mergeable while requiring different training state to reach it. Conversely, two methods may reduce memory in different ledgers: QLoRA reduces frozen-base storage, while LoRA-FA targets adapter-side activation liveness.
0x00D Evidence Classes, Claim Status, And Limits
M6.4 keeps four evidence classes separate:
| Evidence class | What it can establish | What it cannot establish alone |
|---|---|---|
| A22 source-local material | how the handwritten series introduced and connected variant families | correctness of every survey statement or current framework behavior |
| pinned primary paper | the method, assumptions, equations, figures, and source-reported experiments at one revision | universal quality, memory, or speed claims |
| pinned official implementation | behavior of named files and symbols at one commit/release | equivalence to every paper revision or backend |
| Transformer System derivation and oracle | exact consequences under the declared tiny tensor/state contract | reproduction of a paper-scale run or production kernel |
An equation derived here is marked as a Transformer System derivation unless it is tied to a paper equation. An implementation trace names a commit. A paper figure is retained with provenance and a semantic job; it is not decorative evidence.
0x00E Owner, Boundary, And Loop Contract
M6.4 consumes the vanilla operator, gradients, factor identities, checkpoint ABI, and merge limits frozen in M6.3. It owns only the state that changes those contracts:
owned here:
QLoRA training representation
AdaLoRA allocation and schedule state
rsLoRA scaling
LoRA+ and LoRA-FA optimization/backward state
PiSSA and LoftQ initialization state
DoRA magnitude-direction parameterization
compatibility and paper-by-contract comparison
deferred:
serving many adapter identities -> M6.5
general low-rank theory and diagnostics -> M6.7
routed/shared/continual adapters -> M6.9
generic numerical formats and deployment quantization -> M8
forbidden collapse:
do not rederive vanilla LoRA as a variant
do not turn NF4 into a general quantization tutorial
do not infer a production serving path from mergeability
do not rank papers by incomparable source-reported benchmarks
The twelve-loop evidence program follows the changed object through source, tensor, gradient, optimizer, checkpoint, compatibility, failure, and browser contracts. Loop 1 freezes the paper/code/figure surface and all 53 A22 figure dispositions. Later loops may deepen or correct prose, but they must not change an owner or source revision silently.
The point is not to produce a list of acronyms. Two papers can use the same shape while changing different objects, consuming different state, and requiring different runtime support.
0x01 Prerequisites: The Independent Axes Inside A LoRA System
0x01A Freeze The Vanilla Baseline Before Comparing Variants
For one target matrix:
vanilla LoRA computes:
with the usual baseline contract:
W_0:
frozen, commonly stored in fp16 or bf16
A and B:
trainable low-rank factors
rank r:
fixed for the module
scale s:
commonly alpha/r
initial effect:
commonly zero because B starts at zero
A method comparison is meaningful only if it states which line changes. Otherwise QLoRA, AdaLoRA, and DoRA appear to be competing answers to the same question when they are not.
0x01B Separate Base State, Adapter State, And Optimizer State
The forward equation hides three storage classes:
| State | Example objects | Typical owner |
|---|---|---|
| base state | , quantization codes/scales, frozen residual | checkpoint/runtime |
| adapter state | , , magnitude vector, rank mask | task adaptation |
| optimizer state | moments, importance statistics, schedules | training only |
QLoRA primarily reduces base-state memory during training. AdaLoRA adds optimizer-side importance and rank-allocation state. DoRA adds a trainable magnitude object. None of these conclusions can be read from adapter parameter count alone.
0x01C Quantization Changes Representation And Compute Precision
Quantization maps a block of higher-precision weights to compact codes plus metadata:
full-precision block W
-> normalize by block scale
-> map values to finite codebook
-> store codes + scale metadata
During a matrix multiplication, the runtime dequantizes or otherwise consumes that packed representation in a supported kernel. Three dtypes may therefore differ:
storage dtype:
how frozen weights are packed
compute dtype:
precision used for matrix multiplication/accumulation
adapter dtype:
precision of trainable A/B and their optimizer state
QLoRA is not “LoRA with 4-bit gradients.” It keeps a quantized frozen base, performs differentiable computation through its dequantized values, and trains floating-point adapter factors.
0x01D Rank Has Allocation, Scaling, And Optimization Consequences
For one module, LoRA parameters scale as:
But a fixed total rank budget can be distributed uniformly or concentrated in selected modules. Rank also changes branch magnitude and gradient statistics. This creates three independent design questions:
allocation:
which modules receive how much rank?
scaling:
should s vary as 1/r, 1/sqrt(r), or another rule?
optimization:
should A and B use the same learning rate?
AdaLoRA addresses allocation, rsLoRA scaling, LoRA+ factor-specific learning rates, and LoRA-FA factor freezing. They can share the same visible factor shapes at one instant while implementing different training dynamics and activation-retention requirements.
0x01E Initialization Chooses The Starting Function And Subspace
Standard random-/zero- initialization preserves the base function at step zero:
Spectral methods instead initialize from structure in a weight or residual. Quantization-aware methods initialize against quantization error. These choices affect:
whether the initial model exactly matches W_0
which directions receive early gradients
whether W_0 is redefined as a residual
what must be saved to reconstruct or merge the model
PiSSA and LoftQ therefore cannot be reduced to alternative random seeds.
0x01F Training Efficiency, Mergeability, And Serving Are Different Tests
A method can reduce training memory while making deployment more specialized. Ask three separate questions:
training:
which weights, gradients, optimizer states, and activations exist?
artifact:
can the adaptation be represented as an additive dense delta?
runtime:
can current kernels execute or merge that representation correctly?
An algebraically mergeable update may still be kept live to support many adapters. A quantized training base does not force one inference quantization format. A dynamic rank schedule may end in a fixed deployment rank, while a magnitude/direction parameterization may need a specialized merge path.
0x01G Comparison Map
| Method | Primary changed mechanism | What remains LoRA-like | New state or constraint |
|---|---|---|---|
| QLoRA | frozen base storage and quantized training path | trainable low-rank factors | quantization metadata, dequantization compute, paged optimizer behavior |
| AdaLoRA | rank allocation across modules and time | low-rank update family | importance scores, singular components, rank budget schedule |
| rsLoRA | rank-dependent branch scaling | same factor shapes and optimizer interface | scale rather than |
| LoRA+ | optimization rate of the two factors | same forward equation | separate optimizer groups and learning-rate ratio |
| LoRA-FA | trainable-factor set and adapter activation retention | same two-factor forward equation | freeze random projection-down ; train projection-up |
| PiSSA | initialization and frozen residual decomposition | same low-rank branch architecture after setup | SVD-derived factors and residual base weight |
| LoftQ | joint quantization and low-rank initialization | quantized base plus trainable factors | alternating quantization/factor initialization |
| DoRA | weight magnitude/direction parameterization | low-rank directional update | trainable magnitude and column normalization |
These methods are not mutually exclusive in principle. Implementations may combine, for example, quantized-base training with rank-stable scaling or DoRA with quantization. Compatibility must be checked at the actual framework and kernel level.
0x02 QLoRA: Quantize The Frozen Base, Not The Learning Signal
QLoRA addresses a different memory object from vanilla LoRA.
Vanilla LoRA:
base:
frozen, commonly fp16/bf16
adapter:
trainable
QLoRA:
base storage:
frozen 4-bit quantized weights
base compute:
dequantized into a higher compute dtype for matrix multiplication
adapter:
trainable low-rank factors, usually in a floating dtype
gradient:
passes through the dequantized base computation into activations
and into adapter parameters
The defining equation is conceptually:
where:
W_q:
packed quantized values
q:
scale, zero-point, block, or codebook metadata
Dequant(W_q, q):
compute-time approximation of the original frozen W
QLoRA does not train the 4-bit codes as ordinary dense parameters. It backpropagates through the frozen quantized-base computation to the trainable adapters.

Source: QLoRA, Figure 1. The diagram separates the 4-bit frozen base, higher-precision adapter path, and paged optimizer state. It describes the training-memory design, not a required inference format.
0x02A Freeze The QLoRA Representation Before Discussing Memory
“The model is four bit” is not a sufficient representation manifest. It does not identify the codebook, block boundaries, scale hierarchy, compute dtype, adapter dtype, optimizer owner, or page residency. For one adapted linear operator, freeze at least:
| Object | Logical shape | Stored representation | Trainable? | Lifetime |
|---|---|---|---|---|
| base matrix | two NF4 codes per byte | no | persistent | |
| first-level block scales | direct floating scales or nested codes | no | persistent | |
| second-level scales and offset | quantizer-dependent | higher-precision metadata | no | persistent |
| dequantized base view | tile or | compute dtype | no | forward/backward ephemeral |
| adapter | floating training dtype | yes | persistent | |
| adapter | floating training dtype | yes | persistent | |
| adapter gradients | same as | gradient dtype | optimizer input | backward ephemeral or accumulated |
| optimizer moments | two states per scalar for AdamW | optimizer-state dtype | updated | logically persistent; residency may move |
The QLoRA paper’s single-layer operator makes the storage/compute split explicit:
BF16 is the paper’s common compute contract, not a universal implementation
law. The reference script derives compute_dtype from its fp16/bf16
flags and passes it separately from load_in_4bit, quant_type, and
double_quant. A reproducible run therefore records all four fields rather
than inferring compute from storage.
The pinned 2023 implementation path is:
QLoRA qlora.py @ 7f4e95a
BitsAndBytesConfig(
load_in_4bit = bits == 4,
bnb_4bit_compute_dtype = compute_dtype,
bnb_4bit_use_double_quant = double_quant,
bnb_4bit_quant_type = quant_type,
)
-> Transformers 4.31.0 creates bitsandbytes Linear4bit modules
-> bitsandbytes 0.40.0 Params4bit packs W and retains quant_state
-> PEFT 0.4.0 freezes base parameters and injects trainable LoRA factors
-> Trainer selects paged_adamw_32bit for adapter optimizer state
This is versioned implementation evidence. It is not a promise that a modern Transformers, PEFT, or bitsandbytes release has the same internal tuple layout.
0x02B Why NF4 Uses Nonuniform Levels
The QLoRA paper motivates NormalFloat 4-bit for weights that are approximately normally distributed after normalization.
Uniform 4-bit quantization allocates equally spaced levels:
This spends as many representable levels in low-density tails as in the high-density region near zero.
A quantile-oriented codebook instead chooses boundaries so intervals carry more nearly equal probability mass under a reference distribution. If is the standard-normal quantile function, the paper first defines midpoint representatives:
This formula explains the nonuniform spacing: equal probability intervals in the normal reference distribution do not have equal numerical width. It does not yet solve exact zero.
The resulting levels are denser where normalized Gaussian-like weights are dense. QLoRA also needs an exact representation of zero. A naively symmetric even-sized quantile codebook has no single central zero level, so the paper constructs negative and positive quantile sets separately, joins them, and removes one duplicate zero. The resulting NF4 codebook is asymmetric even though the reference weight distribution is zero-centered.
That construction is why this shorthand is incomplete:
NF4 = 16 ordinary standard-normal quantiles
The full contract includes:
reference distribution:
zero-centered normal
block normalization:
absolute-maximum scaling into the codebook range
codebook:
quantile-derived, normalized, with an exact zero
stored metadata:
packed 4-bit codes plus block scales
At the pinned bitsandbytes 0.40.0 implementation, the normalized NF4 table is:
[-1.0000000, -0.6961928, -0.5250731, -0.3949175,
-0.2844414, -0.1847734, -0.0910500, 0.0000000,
0.0795803, 0.1609302, 0.2461123, 0.3379152,
0.4407098, 0.5626170, 0.7229568, 1.0000000]
The table is asymmetric around the exact zero. Deriving 16 values from a different probability grid can produce a different datatype even if both are called “normal four bit.” Codebook identity is checkpoint state.
The safe claim is not that every weight tensor is perfectly normal. It is that NF4 is designed for the empirical distributional structure QLoRA targets and was validated in that training system.
0x02C Blockwise Quantization Tensor Trace
Suppose a flattened weight block contains values:
W_block: [G]
Compute a block scale:
Normalize:
Map each normalized value to a 4-bit code:
Store:
codes:
[G] values at 4 bits each
scale:
one higher-precision value c for the block
During compute:
The quantization residual is:
The LoRA update must learn the downstream task while operating on , not the original full-precision . That is why quantization-aware initialization methods such as LoftQ become relevant.
The Loop 2 executable fixture uses a deliberately small matrix so every stored nibble can be inspected. It uses row-major flattening, , and three blocks:
| Block | Full-precision values | absmax | NF4 code indices | Packed bytes, low nibble first |
|---|---|---|---|---|
| 0 | ||||
| 1 | ||||
| 2 |
For example, byte stores code in the low nibble and code in the high nibble. Reversing the nibble convention preserves the byte count but reconstructs the wrong values. Shape, flatten order, block membership, codebook, and nibble order are therefore one representation contract.
The teaching fixture uses only to make the trace readable. The paper and pinned reference path use a base-weight block size of 64 for the reported double-quantization ledger.
0x02D Double Quantization
Blockwise quantization introduces many scale constants. If each scale is stored at high precision, metadata becomes visible for small block sizes.
For:
P:
number of base parameters
G:
values per quantization block
b_c:
bytes per scale
scale storage is approximately:
Double quantization quantizes those quantization constants as well. The second level adds its own grouping metadata but reduces average scale storage. The mechanism is not “quantize the LoRA adapter twice”; it is quantization of the first-level quantization constants.
Let the positive first-level scales be . The paper centers them before the second quantizer because a symmetric 8-bit quantizer otherwise wastes half its signed range:
For a second-level group with absmax and signed range , a transparent teaching quantizer is:
The executable fixture has , so , , and . It reconstructs those three scales exactly. This small signed-int8 example verifies the metadata dependency graph; it does not reproduce the CUDA kernel’s 8-bit code map.
The QLoRA paper’s source-reported ledger makes the metadata cost concrete. With a first-level block size of 64 and 32-bit scale constants:
With 8-bit first-scale codes, 256 first scales per second-level FP32 scale, and 64 weights per first-level scale, the metadata becomes:
and the derived saving is:
The reported “about 0.373 bit” follows from this geometry; it is not an intrinsic constant of nested quantization. A complete storage ledger also includes packed-container padding, the offset, codebook identity, tensor shape, and any serialization metadata.
The nested dequantization path is:
second-level codes + second-level scales
-> reconstruct first-level block scales
-> reconstruct base weight blocks from NF4 codes
-> cast/use in the matrix-multiplication compute dtype
0x02E Paged Optimizers
LoRA reduces persistent optimizer state, but long sequences and activation peaks can still create transient memory spikes. QLoRA uses paged optimizers backed by CUDA unified-memory behavior to move optimizer pages when needed.
This changes the failure mode:
without paging:
transient peak exceeds device memory
-> allocation failure
with paging:
some optimizer pages migrate
-> training may survive
-> transfer and page-fault latency can appear
Paged memory is pressure relief, not free capacity. A training profile should still record page migration, step-time variance, and peak resident memory.
The accounting identity is:
Paging can change the two terms on the right over time. It does not reduce the logical Adam moment tensors on the left. For adapter scalars and two FP32 Adam moments:
The Loop 2 fixture has 14 adapter scalars, so its logical moments occupy 112 bytes. A teaching snapshot with 56 bytes resident on the GPU still has 112 logical bytes; the other 56 are backed elsewhere. The paper did not establish a universal paging-latency bound, so migration frequency and step-time tails remain measured runtime properties.
0x02F QLoRA Training Step
def qlora_linear(x, packed_weight, quant_meta, A, B, scale):
# Dequantization may be fused into the base matmul kernel.
base_y = quantized_linear(
x,
packed_weight,
quant_meta,
compute_dtype=torch.bfloat16,
)
adapter_hidden = F.linear(x, A)
adapter_y = F.linear(adapter_hidden, B)
return base_y + scale * adapter_y
Trainability assertion:
assert not packed_weight.requires_grad
assert A.requires_grad
assert B.requires_grad
Memory ownership:
GPU persistent:
packed base
quantization metadata
adapter parameters
currently resident optimizer pages
autograd:
activations needed for adapter and input gradients
CPU/unified backing:
optimizer pages that may migrate under pressure
The backward path still needs the input gradient through the frozen base:
but does not allocate a trainable gradient for the packed base weights:
computed:
dX
dA
dB
not computed as an optimizer parameter gradient:
dW_q
That distinction explains why QLoRA reduces persistent model/optimizer memory without eliminating activation memory or backward compute through the base operator.
For , , and upstream , the local adapter gradients are:
and the input gradient is:
The dequantized base participates in even though packed codes and scale metadata are not optimizer parameters. That is the precise meaning of “backpropagating through the quantized model”: the graph differentiates the input-side computation while optimizer ownership stops at and .
The liveness consequence is configuration-dependent:
persistent:
packed codes, quantization metadata, A, B, logical optimizer moments
forward/backward ephemeral:
dequantized weight tile or matrix, X, adapter hidden U, outputs
optimizer gradients:
dA, dB
not optimizer gradients:
d(packed codes), d(first-level scales), d(second-level scales)
A fused 4-bit matrix multiplication may reconstruct only tiles rather than a full dense . The algebra is identical; peak temporary memory and traffic are not. The executable oracle therefore proves the operator and state ownership, not one production kernel’s liveness schedule.
The QLoRA experiments also change the adaptation surface relative to the original LoRA paper’s common query/value setup. The paper reports that applying LoRA to all linear Transformer-block layers was important in its evaluated configurations for matching its 16-bit baselines. This is source-reported evidence, not a theorem that every task needs every linear layer, but it blocks an oversimplified recipe:
QLoRA = quantize base + always adapt q_proj and v_proj only
Target modules remain a training design choice with parameter, memory, and quality consequences.
0x02G Executable Representation And Failure Oracle
The checked evidence bundle at
docs/numinens-evidence/m6-4-adaptation-design-space/ executes this contract
without requiring a GPU. It:
- assigns the exact bitsandbytes 0.40.0 NF4 levels to a matrix;
- packs two 4-bit codes into each byte and reconstructs nested scales;
- executes the dequantized base plus floating LoRA forward path;
- checks the equivalent dense update in the dequantized compute domain;
- checks analytical against finite differences;
- derives packed, metadata, adapter, gradient, optimizer, and page-residency ledgers;
- rejects one-field mutations that collapse storage, compute, optimizer, or deployment state.
The oracle’s exact result is a teaching proof, not a paper reproduction. Its and second-level group of three scales make every code auditable; paper geometry remains separately frozen at and .
| Invalid implementation | Why it can appear plausible | Broken contract |
|---|---|---|
| mark packed base codes trainable | they are represented by a parameter wrapper | optimizer must own only adapter factors |
| quantize and with the base | ”everything is four bit” sounds memory-efficient | QLoRA keeps the learning signal in floating factors |
| change flatten or nibble order | byte counts and tensor shapes still match | reconstructed weights differ |
| omit scale centering or offset | nested codes still decode to numbers | first-level scales reconstruct incorrectly |
| count paged-out moments as removed | GPU residency falls | logical optimizer state is unchanged |
| commit a merged delta directly into packed nibbles | packed storage looks mutable | merge requires an explicit dequantize/update/requantize path |
| generalize all-linear targeting to every task | it matched the reported configuration | target scope is an empirical design choice |
0x02H QLoRA Is Not An Inference Format Decision
QLoRA specifies a training-memory path. After training, deployment can choose:
keep the supported quantized base and live adapters
merge through a supported high-precision path and requantize
export a different quantization format
serve the adapter separately
The best training representation and the best inference representation need not be identical. M8 owns the final compression decision; M6.5 owns live adapter serving.
0x03 AdaLoRA: Allocate Rank Where The Update Matters
Vanilla LoRA usually assigns the same rank to every selected matrix. AdaLoRA asks whether that uniform allocation is the best use of a global rank budget. Its owner question is narrower than “how should LoRA be improved?”:
How does a training loop estimate the importance of individual low-rank components, reduce one global budget over time, project that budget back into module-local tensors, and preserve enough state to resume or export the result correctly?
This section owns the SVD-like triplet, score state, cubic budget, global mask, and masked-versus-compact artifact boundary. It does not own rank-stable scaling, live heterogeneous-rank serving, or general structured pruning; those belong to 0x04, M6.5, and M6.11 respectively.
0x03A Uniform Rank Is An Allocation Policy
For adapted matrices, fixed-rank LoRA sets:
before observing a task gradient. That is a valid baseline, not a consequence of low-rank algebra. The AdaLoRA paper motivates a different policy with module- and layer-selection experiments: under one reported 0.28M-parameter budget, different DeBERTaV3-base modules and layers did not contribute equally on MNLI-m.

Source: AdaLoRA v2, Figure 1. These are source-reported ablations for one model, task, and budget. They motivate adaptive allocation; they do not prescribe a universal decoder-only rank pattern.
AdaLoRA defines the scheduled budget as the number of retained singular values:
That unit must not silently become an exact scalar-parameter budget. A retained triplet for a matrix physically contains:
factor scalars. After physical compaction, the adapter scalar count is:
Therefore equal rank units have equal scalar cost only when their matrix dimensions match. The paper’s budget-matching tables choose average ranks for the evaluated adaptation surface; the rank counter alone is not a universal byte ledger.
0x03B One Triplet Is Three Coupled Tensor Slices
The paper parameterizes one update as:
with:
where . The -th allocation unit is the triplet:
The pinned reference code names these tensors differently:
| Paper object | Reference field | Shape | Rank axis |
|---|---|---|---|
lora_A | rows | ||
lora_E | rows | ||
lora_B | columns |
That mapping determines every reduction and export axis. The live branch in the reference implementation is:
hidden = dropout(x) @ (lora_A * lora_E).T
delta_y = hidden @ lora_B.T
y = base_linear(x) + delta_y * lora_alpha / (ranknum + 1e-5)
lora_E broadcasts over the rows of lora_A. Masking entry of lora_E
removes exactly from the update without zeroing the two
vector factors. The pinned reference keeps ranknum at the initialized rank in
this core path, so the scale is not automatically recomputed from the current
number of nonzero entries. Rank-dependent scale alternatives belong to 0x04.
Initialization also differs from ordinary two-factor LoRA:
lora_A / Q:
random Gaussian
lora_B / P:
random Gaussian
lora_E / lambda:
zeros
result:
Delta W = 0 even though both vector factors are nonzero
Keeping the vector factors nonzero matters later: a masked singular value can become nonzero again after subsequent optimizer and allocation steps.
0x03C Orthogonality Makes Triplet Projection Better Defined
The parameterization resembles an SVD but is not an exact SVD computed after every optimizer step. AdaLoRA instead adds:
and trains with:
Why add this term? If columns of and rows of are strongly dependent, zeroing one factor pair can perturb directions also represented by neighboring pairs. Orthogonality pressure reduces that coupling, making a singular-value mask closer to an interpretable rank projection. It does not prove the learned factors are the exact singular vectors of the dense task update.
The alternative of recomputing an exact SVD of every dense update has cost on the order of:
per matrix and allocation event. AdaLoRA pays instead for trainable triplets, orthogonality loss, and score state.
0x03D Derive Sensitivity From The Removal Operation
For one trainable scalar , a first-order loss expansion is:
Removing the scalar means , so the magnitude of the predicted loss change is:
This explains the weight-gradient product. It is a local first-order proxy, not the measured loss after retraining without that scalar. A mini-batch makes the proxy noisy, so the paper maintains two exponential states:
The second equation centers the deviation on the newly updated smoothed sensitivity. The element score is:
and one triplet score combines the singular scalar with the means of both vector slices:
The means prevent a wider vector from winning only because it contains more entries. Summing those slices, omitting , or reducing the wrong axes changes the allocation while preserving superficially plausible tensor shapes.
This state is not ordinary Adam state. The pinned allocator keeps ipt,
exp_avg_ipt, and exp_avg_unc for every LoRA factor scalar. If the adapter has
full-shape scalars, these dictionaries add up to score
scalars before considering optimizer moments.
0x03E The Cubic Budget Has Three Phases
The endpoint-consistent expression implemented by both the pinned AdaLoRA reference and PEFT v0.19.1 is:
The code truncates the middle value to an integer and materializes a new mask
only when step % deltaT == 0; final fine-tuning reapplies the fixed target
pattern. This produces three different phases:
| Phase | Budget | Importance state | Mask action |
|---|---|---|---|
| initial warmup | initial | updated | no allocation mask |
| reduction | cubic, integer | updated | only at deltaT intervals |
| final warmup | target | frozen | fixed pattern reapplied |
There is a source discrepancy worth preserving. AdaLoRA v2 Appendix A prints:
inside the cubic term. For , that expression can exceed one at and therefore exceed the initial budget, contradicting the surrounding prose. For the checked fixture , , , , the printed expression gives at ; the pinned code gives . This article uses the code expression for its executable schedule and records the printed equation rather than silently attributing the correction to the paper.
0x03F Projection Is Global, Periodic, And Threshold-Sensitive
At a mask event, all triplet scores from all adapted matrices are concatenated. For target budget , the projection is conceptually:
The pinned implementations obtain the -th smallest score as a threshold and retain scores strictly greater than it:
all_scores = concat(score[module] for module in adapted_modules)
threshold = kth_smallest(all_scores, initial_budget - current_budget)
for module in adapted_modules:
module.lora_E.masked_fill_(triplet_score[module] <= threshold, 0.0)
This is global top-budget allocation, not one top- operation per module. It permits rank zero for a module unless a separate floor is added.
The strict comparison also creates a versioned tie behavior. With scores
[10, 8, 5, 5] and requested budget 3, the threshold is 5 and strict > 5
retains only two entries. The paper’s mathematical “top-” contract and this
implementation’s exact cutoff behavior are therefore identical only when the
boundary score is not tied. A production allocator should define whether it
accepts underfill or applies a deterministic tie-fill policy.

Source-local visual reused from Transformer Series A22, which combines AdaLoRA Algorithm 1 with the and orthogonality context. English reading contract: compute gradients; update sensitivity, smoothed sensitivity, and uncertainty; score every triplet; update ; then project under the scheduled global budget. The source image’s top annotation is Chinese, so the equations and loop are transcribed in this section rather than left image-only.
0x03G Paper Algorithm And Runtime Call Order Are Not Identical
The paper’s Algorithm 1 presents this logical order:
forward and task plus orthogonality loss
-> backward gradients
-> sensitivity and score-state update
-> parameter update
-> global projection of lambda
The pinned reference README and PEFT example show:
(task_loss + orthogonal_regularizer).backward()
optimizer.step()
allocator.update_and_mask(model, global_step)
optimizer.zero_grad()
update_ipt then evaluates abs(parameter * parameter.grad): the gradient is
from the just-completed backward pass, while the parameter may already contain
the optimizer update. This code path is reproducible, but it is not
numerically identical to scoring the pre-update parameter in the paper’s
pseudocode. A training report must record the implementation and call order,
not cite Algorithm 1 as if it uniquely fixes both.
The final phase adds another state transition. PEFT v0.19.1 stops refreshing
importance state, forces one target-budget pattern, stores that Boolean pattern
in the adapter config, resets allocator score dictionaries, and reapplies the
mask on later steps. Calling zero_grad() before allocation, omitting the
global step, or resuming with a reset allocator in the reduction phase changes
the learned rank pattern.
0x03H Worked Global Allocation Trace
The checked Loop 3 fixture adapts q_proj and v_proj, each with initial rank
three. It observes two mini-batch sensitivity snapshots with
. After the second update, the exact triplet scores are:
| Global order | Triplet | Score | Projection at |
|---|---|---|---|
| 1 | v_proj[0] | 5.0625 | retain |
| 2 | v_proj[1] | 3.515625 | retain |
| 3 | q_proj[0] | 3.375 | retain |
| 4 | q_proj[1] | 2.25 | mask at strict threshold |
| 5 | v_proj[2] | 1.6875 | mask |
| 6 | q_proj[2] | 0.5625 | mask |
The rank pattern is therefore:
q_proj: [true, false, false] -> active rank 1
v_proj: [true, true, false] -> active rank 2
global active rank -> 3
For the same fixture, the pinned schedule yields:
| Step | Budget | Materialize mask? | Phase |
|---|---|---|---|
| 0 | 6 | no | initial warmup |
| 2 | 6 | no | initial boundary |
| 3 | 4 | no | reduction between intervals |
| 4 | 3 | yes | reduction and allocation |
| 8 | 3 | yes | end of reduction |
| 9 | 3 | yes | final fixed pattern |
The executable oracle in
docs/numinens-evidence/m6-4-adaptation-design-space/ derives every score from
actual factor values and gradients, checks both EMA states, applies the global
threshold, and reconstructs the update from masked-full and compact factors.
It is a mechanism proof, not a reproduction of the paper’s task results.
0x03I Masked Training State Is Not A Compact Artifact
In the fixture, each update starts with:
factor scalars. Two modules therefore keep 30 factor scalars during masked training even though only three of six singular values are active. The allocator adds:
sensitivity/EMA/uncertainty scalars, and two Adam moments add another 60
logical scalars. Zeroed lora_E entries do not delete their factor rows,
columns, optimizer slots, or checkpoint storage.
Only an explicit compaction that selects retained rows of lora_A, retained
entries of lora_E, and retained columns of lora_B reduces this fixture to:
factor scalars. The oracle proves the full-shape masked and compact tensors produce the same .
The original reference lora_state_dict filters keys containing lora_; it
does not slice away masked triplets. Its NLU example writes rank_pattern.json
as separate metadata. PEFT v0.19.1 contains
resize_modules_by_rank_pattern and resize_state_dict_by_rank_pattern
helpers, but its training transition deliberately leaves module resizing
commented out and continues to reapply masks. The existence of a resize helper
must not be rewritten as automatic training-time compaction.
Resume therefore has three levels:
| Resume point | Required state |
|---|---|
| after final pattern is fixed | factor tensors, rank pattern, scale/config, global step, optimizer/scheduler state, RNG state |
| during budget reduction | above plus score EMAs, uncertainty state, mask interval phase |
| compact inference export | compact factors or merged weight plus exact per-module rank metadata |
In the pinned implementations, allocator dictionaries are ordinary Python state rather than ordinary adapter parameters. A generic adapter-only save is not proof of exact mid-schedule resumability.
0x03J Alternatives Change Different Contracts
| Design | Allocation signal | Projection object | Recovery after masking | Main cost/risk |
|---|---|---|---|---|
| fixed-rank LoRA | none | none | not applicable | uniform budget may be suboptimal |
| singular-value magnitude | $ | \lambda_i | $ | |
| AdaLoRA sensitivity/uncertainty | score over | vectors remain trainable | score state, schedule, and global coordination | |
| prune LoRA doublets | score over | both factor slices | difficult if both slices are zeroed | non-orthogonal doublets can be coupled |
| repeated exact SVD | dense update spectrum | exact singular triplet | depends on implementation | prohibitive repeated dense decomposition |
These are not interchangeable names for “dynamic rank.” They differ in what is scored, what is zeroed, whether inactive directions keep trainable state, and whether the result is immediately compact.
0x03K Failure And Runtime Closure
| Failure | Plausible symptom | Broken contract |
|---|---|---|
| rank each module independently | every module receives some capacity | budget is global, not per-module |
| reduce vector scores by sum | wider matrices dominate | triplet score uses vector means |
| mask factor rows and columns | active rank appears smaller | recovery path is destroyed |
call allocator after zero_grad() | scores vanish or fail | sensitivity requires retained gradients |
| restore tensors but not step/score state | training resumes without load error | budget and allocation trajectory change |
| count nonzero as resident parameters | parameter ledger looks smaller | training tensors and moments remain full-shape |
| call rank units exact scalar budget | rank totals reconcile | heterogeneous matrix dimensions change scalar cost |
| assume cutoff ties always fill budget | ordinary random runs look correct | strict threshold can underfill |
| rescale by current active rank in the pinned path | output remains finite | algorithm changed into another scale policy |
After finalization, heterogeneous ranks complicate kernel grouping, adapter batching, hotswap compatibility, and static compilation. M6.5 owns those live serving consequences. AdaLoRA’s result handed to that article must include at least adapter identity, target modules, finalized rank pattern, scale rule, factor dtype, and whether the stored tensors are masked-full or physically compact.
0x04 rsLoRA: Rank Stability Is A Learning-Trajectory Contract
0x04A Scale Is Part Of The Learning Parameterization
For one adapter, write the branch without hiding its rank-dependent scale:
Increasing changes at least three objects:
capacity:
the maximum rank of BA
state and live work:
r(d_in + d_out) factor scalars
r(d_in + d_out) MACs per token for an unmerged branch
learning parameterization:
the scale gamma_r multiplying every forward and backward path
The usual LoRA convention and the rank-stabilized convention are:
They have identical factor shapes and parameter counts. They do not define the same rank sweep. Holding fixed while changing changes the optimization signal differently under the two rules. A comparison that records rank but omits and the scale convention is underspecified.
0x04B Define Rank Stability Before Deriving A Rule
The rsLoRA v1 paper does not define “stable” as “higher rank always produces a better benchmark.” Its theorem is an asymptotic moment statement. In expectation over initialization, it asks for two directions of the adapter to remain order one as grows:
- entrywise input moments in should produce adapter-output moments in ;
- entrywise adapter-output gradients in should produce input-gradient entries in .
The argument assumes:
A_0 entries:
iid, zero mean, variance sigma_A independent of rank
B_0:
exactly zero
gamma_r:
tends to zero as rank tends to infinity
inputs and upstream gradients:
have the stated rank-independent moments
Those assumptions matter. The result is not a distribution-free theorem about arbitrary initializers, optimizers, normalization stacks, data, or trained features. It identifies the scale class that prevents the paper’s leading forward and backward terms from vanishing or exploding under its model.
0x04C Zero- Initialization Makes The First Update Auditable
Let at training step . Matrix calculus gives:
At exact initialization, . Therefore:
but generally:
This removes one misleading explanation of rsLoRA: its branch is not “larger at initialization” under zero- initialization. Both branches emit zero. The scale first appears in the nonzero gradient and then appears a second time when that learned is used in the scaled forward branch.
For one SGD step with learning rate :
The first learned, scaled dense update is therefore:
The two powers of come from different places: one from optimizing , one from executing the resulting adapter.
0x04D Derive The Law
The paper extends the first-step calculation along the SGD trajectory. To leading order:
Substitute both into the branch:
The iid initialization supplies the rank factor:
Consequently, the leading learned adapter is:
The same coefficient reaches the backward path. For a new upstream gradient :
under the paper assumptions. Forward -th moments scale as:
Avoiding both collapse and growth requires:
This is the derivation behind the final square-root rule; it is not a heuristic replacement of one denominator by another.
0x04E One Exponent Separates Collapse, Stability, And Growth
Write a family of rules as:
Then the leading learned-signal factor is:
| Rule | Leading factor | Asymptotic behavior in this model | |
|---|---|---|---|
| LoRA, | collapses | ||
| rsLoRA, | rank-stable | ||
| weak divisor, | grows | ||
| over-divisor, | collapses faster |
The paper evaluates the and alternatives as ablations. Their role is diagnostic: a scale above the stabilized class can become unstable, while a more aggressive divisor can collapse learning faster.
0x04F Exact Rank Sweep: Same Initial Function, Different Learned Signal
The article-local oracle uses a deterministic substitute for the paper’s expectation. For each , repeat the rows:
Then exactly:
so there is no sampling noise in the rank comparison. With , , , and , the oracle checks the initial output, both first gradients, one-step dense update, probe output, and input gradient.
| Rank | LoRA | rsLoRA | rule | rule |
|---|---|---|---|---|
| 4 | ||||
| 16 | ||||
| 64 | ||||
| 256 |
The rank-256 to rank-4 ratio is for standard LoRA, for rsLoRA, for the weak divisor, and approximately for the over-divisor. Meanwhile parameter bytes and live branch MACs still grow linearly with rank. Stabilizing the learned signal does not make high rank free.
def one_step_scaled_delta(A, x, output_grad, eta, alpha, rank, p):
gamma = alpha / rank**p
B0 = zeros([output_grad.size, rank])
initial_output = gamma * B0 @ A @ x # exactly zero
grad_B = gamma * outer(output_grad, A @ x)
grad_A = gamma * outer(B0.T @ output_grad, x) # exactly zero
B1 = B0 - eta * grad_B
delta_1 = gamma * B1 @ A
return initial_output, grad_A, grad_B, delta_1
The checked fixture is an algebra oracle, not a paper-scale training reproduction. Its semantic report hash freezes the exact tensor and scale contract used by this section.
0x04G Initialization Scaling Is Not Adapter Scaling
One alternative is to divide by while retaining another forward scale rule. That changes , but it does not apply the same coefficient at every later execution of the learned branch. The rsLoRA paper reports two relevant ablations:
- scaling only the initialization and using no branch scale equalized an initial gradient comparison but became unstable for the high-rank run;
- scaling the initialization while retaining branch scaling reproduced the weak high-rank learning behavior.
This is source-reported evidence under the paper’s setup. Mechanically, it also shows why these choices cannot be collapsed:
initialization rule:
chooses the starting A_0 distribution
adapter scaling rule:
multiplies every forward and backward use of the branch
PiSSA and LoftQ later in this article own structured initialization. They do not silently replace rsLoRA’s scale contract.
0x04H Paper Evidence And Ablations
The main rsLoRA experiment fine-tunes Llama 2 7B on the first 20,000 OpenOrca examples with AdamW, a constant learning rate, batch size 32, context length 512, and adapters on all linear attention and MLP modules. It sweeps ranks . All results below are source-reported from the pinned v1 paper.

Source: rsLoRA v1, Figure 1. In this experiment, standard-LoRA rank curves converge similarly while higher-rank rsLoRA curves improve. This is evidence for the evaluated configuration, not a universal quality ordering.

Source: rsLoRA v1, Figure 2. Standard-LoRA gradient norms separate by rank; rsLoRA norms remain in a comparable order of magnitude. The plot reports average parameter-gradient norms, not every tensor entry in the theorem.
The appendix checks several alternative explanations: SGD instead of AdamW; GPT-J on GSM8K with Adafactor; attention-only targets; initialization-only scaling; a low-rank learning-rate sweep; and the and scale rules. Those ablations broaden the paper’s evidence surface, but they still do not prove that every model, task, rank, or optimizer benefits monotonically from larger .
The paper also reports benign averaged activation moments for both methods and offers architecture, normalization, small-magnitude, and averaging effects as possible explanations. That observation should remain visible: a clean aggregate activation plot does not falsify rank-dependent parameter-gradient collapse, and neither plot alone proves the full theorem inside a Transformer.
0x04I Pinned PEFT Scale, Pattern, Merge, And Hotswap Trace
At
PEFT v0.19.1,
LoraConfig records use_rslora. During module creation, LoraModel first
resolves rank_pattern and alpha_pattern; LoraLayer.update_layer then
stores:
rank = rank_pattern.get(module_key, default_rank)
alpha = alpha_pattern.get(module_key, default_alpha)
if use_rslora:
scaling[adapter_name] = alpha / math.sqrt(rank)
else:
scaling[adapter_name] = alpha / rank
This order matters. The denominator uses the effective per-module rank, not necessarily the global default. For the checked fixture:
| Module | Effective rank | Effective alpha | LoRA scale | rsLoRA scale |
|---|---|---|---|---|
q_proj | 64 | 16 | 0.25 | 2 |
v_proj | 16 | 32 | 2 | 8 |
o_proj | 4 | 32 | 8 | 16 |
The live linear path multiplies the low-rank branch by the stored scale. The merge path forms the same scaled delta:
Changing the rule only at merge would break live/merged parity. PEFT’s hotswap
path also resolves incoming rank and alpha patterns, recomputes
when use_rslora=True, and updates the module’s stored scale.
Therefore use_rslora is artifact and runtime identity, not a disposable
training comment.
The same tensors + wrong rule = wrong adapter.
0x04J Conversion, Checkpoint, And Runtime Boundary
PEFT’s initialized-adapter conversion path can double rank when converting a PiSSA-, CorDA-, OLoRA-, or LoRA-GA-style difference into standard LoRA factors. Preserving the scale requires different alpha transformations:
The pinned code implements exactly those multipliers. It also rejects this rsLoRA conversion when nonempty rank or alpha patterns are combined with the conversion path, rather than pretending a single global adjustment preserves every module-specific scale.
A resumable or serveable rsLoRA artifact therefore needs:
adapter identity
target modules
factor tensors and dtypes
default rank and alpha
per-module rank and alpha patterns
use_rslora scale identity
merge state and base-model identity
M6.5 owns multi-adapter admission, batching, and live hotswap behavior. This section hands it the scale identity and pattern metadata; it does not infer that every runtime supports rsLoRA merely because it supports two LoRA matmuls.
0x04K Failure And Claim Closure
| Failure | Plausible symptom | Broken contract |
|---|---|---|
| compare ranks while omitting alpha or scale rule | larger rank appears ineffective | rank and learning parameterization were conflated |
| say rsLoRA has nonzero initial output | zero- unit test disagrees | stabilization begins in the update path |
| derive only one power of | predicted exponent is wrong | gradient scale and forward scale were collapsed |
| call universally optimal | one benchmark sweep looks favorable | theorem assumptions and feature quality were generalized |
| scale initialization only | initial norm looks matched | persistent branch scale is a different object |
| apply global rank in a patterned adapter | some modules have wrong output magnitude | effective per-module rank was ignored |
| merge without stored scale | live and merged outputs differ | scale is part of the operator |
| hotswap tensors but retain old scale | shapes may still load | incoming adapter identity was not restored |
| double rank and alpha identically for both rules | converted adapter changes scale | and denominators transform differently |
| claim high rank is free under rsLoRA | quality curve improves | parameters, optimizer state, and live MACs still grow with rank |
The defensible conclusion is narrow and useful: under the paper’s assumptions, the learned forward and input-gradient moments carry a factor, so is the rank-stable class. Whether the extra rank improves a real task remains an empirical question, and whether that adapter can be served correctly remains a runtime compatibility question.
0x05 LoRA+ And LoRA-FA: Optimizer And Backward-State Contracts
M6.3 established that and are asymmetric under the common random-, zero- initialization. Loop 4 then froze the adapter scale as part of learning, merge, checkpoint, and runtime identity. Two methods now preserve the low-rank forward form while changing different training objects:
| Method | Forward operator | Changed training object | Added experiment identity |
|---|---|---|---|
| LoRA+ | unchanged | optimizer groups and factor learning rates | group order, LRs, scheduler, moments |
| LoRA-FA | unchanged | frozen , trainable , corrected gradient | frozen , correction, pairing, moments |
Neither method is merely a different rank. LoRA+ changes the trajectory without changing the tensor family. LoRA-FA changes the trainable factor set, backward liveness, and the subspace in which the induced dense update can move.
0x05A LoRA+ Starts From Factor-Asymmetric Feature Updates
For one token representation , define the two LoRA features used by the LoRA+ paper:
After an optimizer update, write and . Expanding the product gives
changes the coordinates supplied by while holding the old directions fixed. changes the directions while holding the old coordinates fixed. is their multiplicative interaction. The paper calls learning efficient when both linear contributions remain order one, rather than allowing one factor to become asymptotically inert.
With , the ordinary gradients are
At ,
is generally nonzero. The first step is therefore driven by ; changing cannot change it. This finite, directly testable result is separate from the infinite-width argument.
0x05B Derive The Width Exponents Before Choosing A Ratio
Let width be , hold rank fixed, and write
for the entrywise scale of a quantity. The paper assumes one trainable LoRA layer, stable pretrained features, Adam-type processed gradients with entries, and an alignment condition on the processed gradient and layer input. It calls the general theorem “physics level of rigor” and omits technical assumptions; this is not a distribution-free optimizer law.
For the two linear feature contributions to remain order one, its exponent ledger is
The factor-state recurrences reduce to
Combining the efficiency equations gives
Equal learning rates assign both exponents . The paper then uses the initialization-specific recurrences to show that this does not keep both linear updates efficient and the factor features stable. Its stable efficient assignment is
and therefore
That is an asymptotic class, not a finite value. It does not derive , nor say that production code should use embedding width as the literal ratio.
0x05C Finite LoRA+ Is A One-Dimensional Search
The practical method fixes
then tunes . This changes a two-dimensional sweep into a one-dimensional search while retaining factor asymmetry. The finite absorbs constants omitted by notation.

Source: LoRA+, Figure 5 in the pinned source. Each box summarizes for the four runs with the best final test loss for one model/task pair. It shows finite optima vary; it does not establish one universal ratio.
The paper reports that its second initialization often favored a ratio near for RoBERTa, standard random-/zero- initialization often favored roughly to , and its Llama experiments roughly to . It also reports little benefit on some easier tasks. These are source-reported experiments, not a guarantee or a theorem for .
0x05D Pinned PEFT Uses Four Groups, Not Merely A/B
The pinned
create_loraplus_optimizer
from PEFT v0.19.1 classifies every trainable parameter:
for name, parameter in model.named_parameters():
if not parameter.requires_grad:
continue
if owning_module_is_peft_embedding(name):
group = "embedding"
elif "lora_B" in name or parameter.ndim == 1:
group = "groupB" if name in decay_parameters else "groupB_no_decay"
else:
group = "groupA"
It constructs four groups:
| Group | Learning rate | Weight decay | Membership rule |
|---|---|---|---|
groupA | LoRA+ decay | remaining trainable parameters | |
embedding | dedicated embedding LR | LoRA+ decay | PEFT LoRA embedding parameters |
groupB | LoRA+ decay | decayed lora_B and 1-D parameters | |
groupB_no_decay | non-decayed lora_B and 1-D parameters |
The parameter.ndim == 1 branch makes the high-rate groups broader than the
mathematical factors. A trainable one-dimensional bias or normalization
parameter can receive the learning rate. Reproduction therefore requires
more than the phrase “LoRA+ ratio 16.”
The exact fixture uses and . It obtains
for both groups, places an embedding adapter at
, sends a trainable non-LoRA bias to groupB_no_decay, and excludes
a frozen tensor. For the explicitly named 8-bit optimizer classes, the helper
also asks bitsandbytes to keep embedding optimizer state at 32 bits.
0x05E Scheduler And Exact-Resume Identity
If one scheduler multiplies every group by the same factor , then
A scheduler that rewrites groups differently does not preserve the ratio. Exact resume therefore requires:
ordered parameter names
ordered optimizer groups and membership
current LR and weight decay of every group
optimizer moments and step
scheduler class, state, and group mapping
rank, alpha, and Loop 4 scale identity
Restoring identical tensors into equal-LR groups resumes a different training algorithm. The merged operator can be identical at that instant; the future trajectory is not.
0x05F LoRA-FA Freezes A, But That Is Only Half The Method
LoRA-FA keeps the projection-down factor fixed and trains :
W [d_out,d_in]: frozen
A [r,d_in]: random, frozen, checkpointed
B [d_out,r]: usually zero-initialized, trainable

Source: LoRA-FA, Figure 1. The figure shows trainable and frozen tensors. It does not alone prove activation savings or equality with full fine-tuning; those require the following derivations.
Let a flattened token batch be and define
For , ordinary autograd gives
Freezing removes and its optimizer state. The paper also
changes the gradient supplied to the optimizer. Merely setting
A.requires_grad=False implements frozen-factor LoRA, not the complete
corrected-gradient LoRA-FA contract.
0x05G Derive The Corrected B Gradient As A Projection
The dense gradient for under this article’s orientation is
If an optimizer applies a matrix to , its corresponding first-order update in dense-weight coordinates is . LoRA-FA asks for the closest representable dense gradient:
Differentiate with respect to :
The normal equation is
When has full row rank,
Ordinary autograd already produced
so the correction can be computed without materializing :
This is a right preconditioner in rank space. Its induced dense gradient is
where
is the orthogonal projector onto the row space of fixed . The unrepresentable component is
The corrected update equals the arbitrary dense gradient only when every row of already lies in . Freezing a random does not provide universal full-gradient equivalence. Broad paper language about preserving expressivity must be read against this fixed-subspace condition.
The correction remains a descent direction when is positive definite because
For singular or ill-conditioned , the inverse must be replaced by a pseudoinverse or regularized solve. The result is then tied to that tolerance, solve policy, and dtype.
0x05H Exact Tiny-Tensor Projection Trace
The executable fixture uses
and obtains
For its exact and upstream ,
while the corrected factor update induces
The oracle checks exact equality between and , but
That nonzero residual is deliberate. A fixture whose dense gradient already lies inside the row space could pass while hiding the method’s main restriction.
0x05I Activation Liveness Is Adapter-Local And Rank-Dependent
The gradient needs . The gradient additionally needs . With bytes per saved activation element:
| Method | Trainable adapter parameters | Adapter-local saved activation | Two FP32 optimizer moments |
|---|---|---|---|
| standard LoRA | bytes | ||
| LoRA-FA | bytes | ||
| LoRA-FB | bytes |
For the square-layer, 16-bit convention used in the paper, with batch , sequence , and width :
LoRA-FA removes the need to retain full-width for the adapter’s gradient. It does not prove that attention, normalization, residuals, MLP nonlinearities, the base path, or an earlier trainable layer no longer need state. It still retains , so adapter activation grows linearly with rank.

Source: LoRA-FA, Figure 4(a). The paper reports Llama2-7B at rank 64, global batch 8, maximum sequence length 1024, on one 80 GB A800. LoRA-FA is shown at 52.2 GB while compared methods cross the capacity line. This is source-reported system evidence, not a reproduced or hardware-independent memory guarantee.
The forward still computes . Freezing changes autograd
liveness and optimizer work; it does not algebraically delete the projection-
down matmul. Any reported kernel compute saving depends on a concrete fused
implementation and cannot be inferred from requires_grad=False alone.
0x05J Paper Algorithm And PEFT v0.19.1 Differ
The paper’s Algorithm 1 proposes precomputing
once because is frozen. The pinned
LoraFAOptimizer
instead executes this inside each optimizer step:
AA_T = A @ A.T
AA_T_inv = torch.linalg.pinv(AA_T + 1e-8 * eye(rank))
grad_B = (1 / scaling_factor**2) * (grad_B_raw @ AA_T_inv)
Its pinned contract also includes:
- Every name containing
lora_Ais frozen. - A and B are paired by named-parameter iteration order, not an explicit adapter-key join.
- Only receives LoRA-FA moments; non-LoRA trainable parameters follow an ordinary AdamW-style path.
- The helper receives one global
r,lora_alpha, anduse_rslora, then computes one scale or . - The correction uses , so Loop 4’s scale identity is part of the optimizer as well as the forward.
- The inverse path adds , uses a pseudoinverse, may execute under BF16 autocast, and converts the corrected gradient to the raw dtype.
The global helper arguments do not represent arbitrary per-module rank or alpha patterns. Pairing order, regularization, solve policy, and scale are compatibility and exact-resume state, not incidental code details.
0x05K Frozen Does Not Mean Disposable
LoRA-FA trains only , but frozen still defines the forward projection , the row-space projector , the Gram correction, the merged delta , and the next optimizer update. A resumable artifact needs:
base-model and adapter identity
frozen A tensor, name, shape, dtype, and order
trainable B tensor, name, shape, dtype, and order
rank, alpha, and standard/rsLoRA scale rule
correction mode, regularization, and solve policy
B optimizer moments and step
non-LoRA trainable parameters and their state
Saving only is not a smaller equivalent checkpoint. It loses both the operator and the subspace in which the next update is defined.
0x05L Alternatives And Composition Boundaries
LoRA-FB freezes and trains . Its gradient still needs full-width , so it does not obtain LoRA-FA’s adapter-local activation advantage. It also needs nonzero frozen : freezing the usual zero- initialization leaves both adapter output and gradient at zero.
LoRA+ and LoRA-FA are not naively additive labels. Once is frozen, has no effect and a “LoRA+ ratio” merely renames the effective learning rate; the two-factor efficiency theorem no longer describes the training algorithm. A meaningful combination needs a new contract and ablation, not string concatenation.
| Combination | Required reconciliation |
|---|---|
| rsLoRA + LoRA-FA | preserve stored in forward, merge, and correction |
| QLoRA + LoRA-FA | separate quantized-base storage from adapter activation and correction state |
| AdaLoRA + LoRA-FA | rederive allocation and compaction when is fixed and rank changes |
| M6.5 serving | serve the final operator and metadata; do not import optimizer state into request scheduling |
0x05M Failure And Claim Closure
| Failure | Plausible symptom | Broken contract |
|---|---|---|
| call a theorem | one default works | asymptotic width scaling became a finite constant |
group only names containing lora_B | optimizer runs | pinned PEFT also assigns trainable 1-D parameters the B rate |
| restore tensors but rebuild equal-LR groups | checkpoint loads | future trajectory changed |
| schedule groups differently | initial ratio is right | drifts |
| freeze but use raw | memory drops | corrected LoRA-FA optimizer is absent |
| claim every dense gradient is recovered | one projection passes | was ignored |
| invert singular | NaNs or failure | full-row-rank assumption broke |
| discard frozen | remains | forward, merge, subspace, and correction were lost |
| claim all activation disappears | adapter ledger shrinks | whole-model liveness was generalized |
| call LoRA-FA rank-independent | memory seems small | saved and correction work still grow with rank |
| say paper and PEFT precompute alike | values look close | PEFT recomputes a regularized pseudoinverse per step |
| combine LoRA+ and LoRA-FA by name | one LR remains | is frozen, so the two-factor theorem no longer applies |
The useful conclusion is precise. LoRA+ changes how two trainable factors move, making optimizer groups part of exact resume. LoRA-FA removes the adapter’s -gradient liveness and preconditions the gradient, but the induced dense update remains inside a fixed row space. Both eventually produce ; they are still different training algorithms.
0x06 PiSSA: Initialize From The Principal Subspace
Vanilla LoRA preserves the pretrained function by making one trainable factor zero. That contract also delays one factor’s first update:
vanilla LoRA at step 0:
A0 = random
B0 = 0
s B0 A0 = 0
gradient_A = 0
gradient_B is generally nonzero
PiSSA v4 asks a different question:
Can both low-rank factors begin as a meaningful, nonzero part of the pretrained weight while the combined layer still computes exactly the pretrained function?
Its answer changes three identities at once. The original weight is split into a frozen residual and a trainable principal component; both adapter factors start nonzero; and a native checkpoint is now paired with the residual base. This is more than a random-seed choice, even though the live low-rank operator still has the same shapes as LoRA.
0x06A Derive The Principal And Residual Split
Use the M6.3 weight convention:
Let the economy singular value decomposition be
with singular values ordered . Partition the first components from the tail:
Then
The Eckart-Young-Mirsky theorem gives the exact Frobenius contract behind the word “principal”:
and
That is a matrix-reconstruction result. It does not prove that the principal subspace is optimal for every downstream loss. The paper’s own limitations request more theory for PiSSA’s advantage, so task-level superiority remains an empirical claim.
0x06B The Adapter Scale Belongs Inside Initialization
The paper writes the PiSSA decomposition with an unscaled product. M6.3 owns a general LoRA branch
Therefore the factors must satisfy
not merely . Split each singular value symmetrically after dividing by the stored scale:
Then
Define the actual frozen base by subtraction:
The initialization identity is now explicit:
The PEFT v0.19.1 implementation does exactly this: it divides retained singular values by the adapter scale, takes square roots, initializes both factors, and subtracts the scaled product from the base weight. The paper’s experiments set , so its scale is one; copying the paper factors into a non-unit-scale implementation without this adjustment is wrong.

Source: PiSSA v4, Figure 1. The paper uses an naming convention; Transformer System keeps M6.3’s convention. The semantic contract is the same: principal factors remain trainable and the residual matrix is frozen.
0x06C Exact Tensor Trace And Spectral Ledger
Use the checked fixture
with
For and ,
Therefore
and
The fixture separates captured energy from residual error:
while
The machine-checked reconstruction, orthogonality, gradient, dropout, and conversion results live in the M6.4 evidence bundle. This tiny matrix is an algebra oracle, not evidence for paper-scale quality.
0x06D Both Factors Receive A First Gradient
For
and output gradient
the chain rule gives
and
Vanilla zero- initialization makes at the first step. PiSSA generally has and , so neither gradient is forced to zero.
For the fixture inputs
the low-rank feature is
and the checked first gradients are
Both are nonzero. This is the precise first-step distinction; it is stronger than saying that PiSSA “starts closer” without naming the computation.
0x06E Principal Initialization Is Not A Permanent Subspace Constraint
Let a finite optimizer step produce
The effective dense change relative to initialization is
The first two terms form the tangent update of the rank- factorization; the last is the finite-step cross term. Columns of need not stay in , and rows of need not stay in . PiSSA initializes from principal directions; ordinary factor optimization can rotate away from them.
In the oracle, one gradient step introduces a nonzero third coordinate in and new first and third coordinates in . The exact dense update equals tangent plus cross term to machine precision. Calling the method a permanent “principal-only” optimizer would therefore describe the initial state as though it were the entire trajectory.
0x06F Exact SVD, Fast SVD, Dtype, And Function Parity
PiSSA exposes two different questions:
- Did initialization recover the exact top- singular subspace?
- Does the initialized residual-plus-adapter operator reproduce the input weight?
Exact SVD can answer the first under the selected arithmetic. A randomized low-rank SVD gives an approximation whose quality depends on rank, oversampling, iteration count, spectrum, and arithmetic. But if code defines
then
still holds algebraically. Approximate subspace fidelity and initial function identity are different tests.
The paper’s Fast SVD appendix reports a
source-specific time/error/loss tradeoff as niter changes. In pinned PEFT:
init_lora_weights = "pissa"
-> torch.linalg.svd
init_lora_weights = "pissa_niter_N"
-> torch.svd_lowrank(..., niter=N)
Pinned PEFT accepts source weights in FP32, FP16, or BF16, converts the SVD input to FP32, and casts the residual back to the source dtype. Therefore the parity gate should be dtype-aware:
def pissa_init(weight, rank, scale, niter=None):
source_dtype = weight.dtype
assert source_dtype in (torch.float32, torch.float16, torch.bfloat16)
work = weight.float()
if niter is None:
U, S, Vh = torch.linalg.svd(work, full_matrices=False)
U, S, Vh = U[:, :rank], S[:rank], Vh[:rank, :]
else:
U, S, V = torch.svd_lowrank(work, q=rank, niter=niter)
Vh = V.T
root = torch.sqrt(S / scale)
B0 = U * root[None, :]
A0 = root[:, None] * Vh
residual = (work - scale * (B0 @ A0)).to(source_dtype)
reconstructed = residual.float() + scale * (B0 @ A0)
assert_close(reconstructed, weight.float(), dtype_tolerance(source_dtype))
return residual, A0, B0
Initialization time, peak workspace, host/device placement, random seed for
fast SVD, niter, compute dtype, cast dtype, and reconstruction tolerance are
all reproducibility state.
0x06G Training Mode Adds A Dropout Contract
The parity proof assumes the same reaches the residual and principal paths. If adapter dropout transforms only the low-rank input, then at initialization
Relative to the pretrained output, the samplewise difference is
It is generally nonzero for a nonidentity dropout mask. The PiSSA paper’s
reported training setup uses lora_dropout = 0 and . A framework
may allow other values, but “initially the same function” must then be scoped
to evaluation mode or to the expectation justified by that dropout rule, not
claimed as samplewise training-mode identity.
0x06H Native State And Portable Conversion Are Different Artifacts
After training, let the factors be . A native PiSSA layer computes
That adapter is not portable by itself to the original . Since
the equivalent update relative to is
Factor it by concatenation:
so that
The portable adapter has rank at most , not . Saving only and applying them to double-counts the initialized principal component. The oracle’s wrong artifact differs from the native trained weight by squared Frobenius error , exactly the energy of the omitted subtraction in its rank-one principal component.
The PiSSA conversion appendix derives
this rank-doubled adapter. Pinned PEFT implements it as
subtract_mutated_init, requiring an adapter snapshot taken immediately after
initialization. It also preserves the branch scale when rank doubles:
| Scale rule | Original | Converted rank | Converted alpha | Scale after conversion |
|---|---|---|---|---|
| classic LoRA | ||||
| rsLoRA |
PEFT v0.19.1 rejects the rsLoRA conversion path when rank or alpha patterns
are also active. It also rewrites the converted configuration’s
init_lora_weights to ordinary LoRA initialization; otherwise loading the
saved initial snapshot would subtract the principal component again.
0x06I Quantized Residuals Break Naive Conversion Equivalence
Quantization is nonlinear. In general,
Pinned PEFT emits this warning during conversion. A native QPiSSA artifact can pair the quantized residual with trained factors; a portable converted LoRA adapter on the quantized original base can have a numerical gap. This does not turn PiSSA into LoftQ:
| Method | Matrix decomposed at initialization | Object optimized |
|---|---|---|
| PiSSA | original pretrained | principal factors, with residual frozen |
| QPiSSA | original , then quantize | principal factors over quantized residual |
| LoftQ | quantization residual under a chosen quantizer | coupled quantized base and low-rank compensation |
Loop 7 owns LoftQ’s alternating quantization-aware objective. This section only freezes the artifact boundary needed to avoid treating the methods as synonyms.
0x06J What The Paper Figures Establish

Source: PiSSA v4, Figure 2(a). This is a source-reported toy loss-landscape experiment. It visualizes the paper’s optimization hypothesis; it is not a proof that principal directions minimize every task loss.

Source: PiSSA v4, Appendix M. The plot reports one LLaMA-3-8B MetaMathQA setup and supports an early-step comparison under that protocol. It does not establish a universal convergence ordering.
The paper also compares principal, middle, and minor singular components in its appendix. Those experiments motivate the principal choice on the evaluated settings. MiLoRA v3 later studies the opposite design hypothesis: preserve principal components and adapt minor ones. The comparison is empirical and task-dependent; the SVD reconstruction theorem alone cannot choose between their downstream objectives.
0x06K State, Runtime, And Exact-Resume Contract
PiSSA uses the ordinary two-matmul LoRA branch during training, so it does not remove adapter activation state or optimizer moments. Its distinguishing state is initialization and artifact identity:
initialization manifest:
source checkpoint identity and target module
rank, alpha, and classic/rsLoRA scale rule
exact SVD or randomized SVD with niter and seed
SVD compute dtype, residual storage dtype, device, tolerance
dropout mode
native training checkpoint:
residual base identity or residual tensor
current A and B
initial A0 and B0 snapshot for portable conversion
optimizer and scheduler state
portable converted adapter:
original base identity
rank 2r factors encoding BtAt - B0A0
adjusted rank and alpha metadata preserving scale
ordinary-LoRA initialization metadata
For a merged fixed deployment, materialize once and use the dense operator. For live adapter serving, a residual-base PiSSA adapter cannot be mixed casually with adapters that assume the original base. Convert to the original-base delta contract first, or maintain a separate compatible base identity. M6.5 owns registry, batching, and hotswap policy.
0x06L Failure And Claim Closure
| Failure | Plausible symptom | Broken contract |
|---|---|---|
| omit from singular roots | reconstruction passes only when | scale-aware initialization |
| call fast SVD exact | function recomposes | subspace fidelity confused with subtraction identity |
| compare residual after FP16 cast at FP64 tolerance | tiny parity failure | dtype boundary omitted |
| enable adapter dropout and claim samplewise identity | training output changes at step zero | branch inputs differ |
| say PiSSA remains in the initial principal subspace | early vectors look aligned | factor gradients can rotate both sides |
| call principal directions task-optimal by theorem | reconstruction error is minimal | matrix norm theorem generalized to downstream loss |
| save trained factors against original | model loads but output shifts | initial principal product was not subtracted |
| convert without initial snapshot | only final factors remain | portable delta is trained minus initial product |
| keep rank after portable conversion | shapes look compact | difference of two rank- products needs up to |
| quantize original and residual bases interchangeably | similar file size | nonlinear quantization broke equivalence |
| call PiSSA and LoftQ the same initializer | both use SVD | original weight and quantization error are different objects |
| generalize source plots | one setup improves | source-reported experiment became universal claim |
The precise conclusion is narrower and stronger than “SVD is a better seed.” PiSSA represents the original layer as a frozen residual plus a nonzero, scale-aware principal adapter; this gives both factors first-step gradients. The factors may rotate during training. Native artifacts require the residual base, while portable original-base adapters encode trained-minus-initial state and can require rank .
0x07 LoftQ: Quantization-Error Initialization Is A Coupled State Problem
QLoRA and LoftQ can use the same low-bit vocabulary and still initialize two different functions. Let be one pretrained matrix. A quantizer does not merely return another dense matrix. It produces representation state
such as packed code indices, scales, a codebook or zero points, block metadata, and shape. The matrix consumed by a floating-point execution path is the dequantized value
M8.1 owns how such codes and scales work. This section owns a different question:
Given a fixed low-bit representation family and a rank budget, how should the quantized base and the initial LoRA factors be chosen together so that their initial effective weight remains close to ?
Vanilla QLoRA first quantizes and then installs a zero-output LoRA branch:
Its initial weight error is therefore
For an input batch , the corresponding output error is
The error is already present before any task gradient reaches the adapter. LoftQ changes that initial condition: it gives the low-rank branch a nonzero job at step zero and, in the full algorithm, lets the chosen quantized base change with that branch.
0x07A Derive The Joint Objective From The Executed Weight
M6.3 defined the repository’s LoRA convention as
with
The initializer should make this executed weight approximate the original pretrained matrix. That gives the weight-space objective
Equivalently, if denotes all matrices representable by the selected code, scale, grouping, and backend contract,
The LoftQ paper writes an unscaled product . The extra above is not a new method. It reconciles the paper notation with a framework whose LoRA forward multiplies the branch by or .
This objective is LoRA-fine-tuning-aware in a precise but limited sense. It reserves a rank- additive component while choosing the low-bit base. It does not include task labels, activations, optimizer dynamics, or serving latency.
0x07B The Two Alternating Blocks Have Different Guarantees
Initialize
At alternating step , hold the previous low-rank product fixed and form
The quantizer block produces codes and dequantization metadata:
The ideal block-coordinate update would be
But the paper explicitly says its practical is an efficient approximation, not an exact solution of that subproblem. Dynamic absmax scales, block grouping, clipping, lookup tables, and backend rules make the quantizer a discrete algorithm rather than a symbolic nearest-matrix operator.
Now freeze and define its residual against the original weight:
Take the economy SVD:
where and . By Eckart—Young, the exact best rank- correction for this fixed dequantized base is
Therefore
The two blocks should not be described with the same word “optimal”:
| Block | Fixed state | Update | Guarantee |
|---|---|---|---|
| quantizer | quantize | practical, representation-specific approximation | |
| low-rank | truncated SVD of | exact Frobenius-best rank- matrix |
That distinction is why generic convergence claims are unsafe.
0x07C Rank Recovers Spectral Energy, Not Arbitrary Quantization Error
For the first quantized residual , define the rank- recoverable energy fraction
Then the initial quantized-only error is
whereas a one-step LoftQ correction leaves
If the error is concentrated in a few singular directions, a small adapter can remove much of it. If the spectrum is flat, rank leaves a large floor. A larger parameter count does not by itself prove a useful error geometry.
0x07D Exact Three-By-Three Alternating Trace
The checked Loop 7 oracle uses
rank , and a teaching quantizer with normalized codebook
Each quantizer call recomputes one matrix-wide absmax scale and chooses the nearest normalized code. This is deliberately small enough to audit; it is not claimed to reproduce bitsandbytes NF4.
At , the quantized-only residual has
Its rank-one SVD correction captures
of that squared Frobenius error. The factors in repository orientation are
The exact SVD tail ledger is
Four complete iterations in this witness give:
| error after quantizer, before new SVD | error after rank-one SVD | |
|---|---|---|
| 1 | ||
| 2 | ||
| 3 | ||
| 4 |
Every SVD update lowers the objective relative to the quantized state from the same iteration. But the quantizer moves the previous state to before SVD. Even in a successful trace, the quantizer block is not a descent proof.
The oracle also contains a second valid matrix whose post-SVD objectives are
That counterexample does not refute the paper’s empirical results. It prevents an invalid theorem: this practical alternating map does not guarantee that every complete iteration lowers the objective for every matrix and quantizer.
0x07E T=0, T=1, Full Alternation, And One-Step Replacement
The iteration count changes artifact identity:
| State | Quantized base | Initial branch | What changes |
|---|---|---|---|
| QLoRA baseline | zero-output LoRA | quantization error is uncompensated | |
| LoftQ | rank- SVD of | base equals QLoRA’s initial quantization | |
| full LoftQ | SVD residual matched to that final base | both base and adapter change | |
| PEFT replacement utility | an already quantized base | one SVD fit to streamed original weight | base remains fixed |
For , the paper’s own special-case statement is exact:
For , loading on a separately regenerated is wrong in general because the final base was quantized from , not from .
0x07F The Adapter Scale Must Match The SVD Product
The paper’s factor split for an unscaled branch is
so
If the actual forward computes , those factors reproduce only when . For arbitrary positive , a symmetric scale-aware split is
Then
In the oracle, using the unscaled SVD factors with a configured forward scale leaves squared error
whereas scale-corrected factors recover the best achievable rank-one tail
This is an implementation contract, not a recommendation that every framework must rewrite its initializer. A framework can instead require , divide one factor by , or accept a different initial effective weight. It must state which behavior it implements.
0x07G Quantizer State Is More Than A Dense Matrix
An implementation trace should preserve these tensors separately:
full-precision source:
W [d_out, d_in], initializer compute dtype
quantizer working input:
Z_t = W - s B A [d_out, d_in], usually floating point
stored low-bit state:
code indices packed or backend-native integer representation
scales / absmax per tensor, channel, group, or block
codebook / zero representation metadata
shape / layout unpack and kernel ABI
execution view:
Qhat_t = dequant(C_t) [d_out, d_in], compute dtype
adapter state:
A_t [r, d_in], floating point
B_t [d_out, r], floating point
scale s scalar or adapter metadata
Two artifacts can expose the same dequantized shape and still be incompatible because their group size, packing order, codebook, scales, or backend differ. LoftQ binds its factors to the actual dequantized base produced by that quantizer contract.
The setup workspace is also not free. For one matrix it may hold , the current low-rank product, quantizer working state, , residual , and SVD workspace. The persistent training artifact can be small, while initialization still needs a full-precision source tensor and matrix-level SVD workspace. The paper calls this preprocessing cost negligible because matrices can be processed independently and in parallel; that is a source-reported systems claim, not a universal memory or wall-time guarantee.
0x07H Paper Algorithm, Reference Repository, And PEFT Are Three Contracts
The LoftQ v4 paper specifies quantize-then-SVD
alternation and stores the final integer weight plus lookup metadata with the
final adapters. The pinned
reference repository
routes its model conversion through PEFT, exposes bits, rank, and iter,
saves the modified base and adapter in separate directories, and changes the
saved adapter configuration so LoftQ is not applied again on load.
Pinned PEFT v0.19.1 contains two materially different paths:
| Contract | loftq_init | replace_lora_weights_loftq |
|---|---|---|
| input base | unquantized matrix | already bitsandbytes-quantized PEFT model |
| original | live source tensor | streamed from a safetensors checkpoint |
| iterations | configured positive count | one residual SVD |
| base mutation | yes, assigns returned dequantized LoftQ base | no |
| bits in pinned code | NF4-like 4-bit or int8 path | bitsandbytes 4-bit only |
| callback | none | may keep or roll back each module replacement |
| compute | casts source weight to float32 for initialization | dequantizes base and SVDs float32 residual |
The full pinned helper performs:
res = W.float()
for t in range(num_iter):
Q_state = quantize(res)
Qhat = dequantize(Q_state)
E = W.float() - Qhat
B, A = truncated_svd_factors(E, rank)
if t + 1 < num_iter:
res = W.float() - B @ A
return Qhat.cast_as(W), A, B
The replacement utility instead performs:
for each bitsandbytes Linear4bit target:
W = stream_original_tensor_from_safetensors(name)
Qhat = dequantize(existing_quantized_module.weight)
B, A = truncated_svd_factors(W.float() - Qhat, rank)
install(A, B)
if callback_rejects(module):
restore_previous(A, B)
Calling the replacement utility repeatedly is a greedy series of adapter replacements on a fixed low-bit base. It is not equivalent to Algorithm 1, which re-quantizes the base from the previous low-rank state.
The pinned PEFT factor helper returns the unscaled SVD product and does not divide singular roots by the configured LoRA forward scale. Therefore exact paper-objective recomposition in that pinned path requires scale or an explicit scale-aware adjustment. This statement is version-pinned; it is not a claim about all future PEFT releases.
0x07I Training, Dropout, Merge, And Runtime Integration
After initialization, the paper freezes the quantized backbone and optimizes the floating adapter factors. For one target matrix:
def loftq_linear(x, quantized_base_state, A, B, scale, dropout):
Qhat_x = quantized_linear(x, quantized_base_state)
adapter_x = dropout(x) @ A.T
return Qhat_x + scale * (adapter_x @ B.T)
LoftQ does not remove the live LoRA branch. The runtime still owns adapter matmuls, adapter identity, batching constraints, dtype transitions, and K/V state described by M6.3.
The weight-space objective assumes a deterministic additive branch. In training mode with nonidentity adapter dropout,
which is not samplewise equal to . The oracle’s fixed mask produces squared output error relative to deterministic reconstruction. The expectation may be scale-correct under inverted dropout; individual training steps are not identical.
Merging also has a representation boundary. In floating point one can form
But a low-bit serving artifact needs
which introduces a new quantization error and may use different scales from the LoftQ-initialized base. “Mergeable” does not mean bit-exactly mergeable into the same packed codes.
0x07J Full Artifact And Resume ABI
A reproducible initializer manifest should bind:
source:
original checkpoint identity and tensor name
orientation / fan-in-fan-out convention
quantizer:
bit width and codebook
scale, zero-point, block/group layout
clipping and rounding rule
backend/library version and dtype path
low-rank initializer:
rank r and forward scale s
alternating step count T
SVD implementation, dtype, and tie behavior
target-module set
artifact:
final quantized base codes and metadata
matching A_T and B_T
adapter config and scale
provenance linking base and adapter
After training begins, exact resume additionally requires optimizer moments, scheduler state, step counters, RNG/dropout state, precision/loss-scaling state, and the same base/adapter pairing. Re-running LoftQ is not resume.
The base and adapter are a coupled initialization artifact. They are not two independent files that may be regenerated or exchanged by shape alone.
A deployment admission check should fail when any of these differ:
def admit_loftq_artifact(base, adapter, manifest):
assert base.quantizer_fingerprint == manifest.quantizer_fingerprint
assert base.source_tensor_map == manifest.source_tensor_map
assert adapter.rank == manifest.rank
assert adapter.scale == manifest.scale
assert adapter.target_modules == manifest.target_modules
assert adapter.initialized_against_base_sha256 == base.sha256
0x07K Frobenius Error Is Not A Task Metric
For any input batch,
Reducing weight Frobenius error therefore tightens a generic output-error upper bound for fixed . It does not rank task loss exactly. Real activation covariance can weight directions very differently, nonlinear layers can amplify or damp errors, and fine-tuning changes the adapter after initialization.
A data-weighted alternative would optimize something like
or use a curvature/Fisher proxy. That is a different design choice with a calibration-data contract. LQ-LoRA and later quantization-error methods belong in the comparison taxonomy of Loop 9; they are not silently substituted into LoftQ here.
0x07L Quantize-First And SVD-First Are Different Algorithms
The paper discusses swapping the two updates. Starting from zero states, the primary order is:
quantize W
fit rank-r residual of W - Qhat
The alternative begins:
fit rank-r approximation of W
quantize the remaining residual
In the exact toy fixture, the one-step objectives are:
This witness establishes non-equivalence, not universal dominance. The paper’s Table 6 reports that its quantize-first method outperformed the swapped order on the selected 2-bit DeBERTaV3 tasks. That comparison remains source-reported.
0x07M What The Paper Figures Establish

Source: LoftQ v4, Figure 2. The paper measures spectral- and Frobenius-norm initialization discrepancy for one randomly selected BART-large weight matrix under uniform and NormalFloat quantization. In this source-local example LoftQ reduces the discrepancy, especially at 2 bits. It does not prove an all-layer or task-quality theorem.

Source: LoftQ v4, Figure 3 left. This is source-reported uniform 2-bit DeBERTaV3-base MNLI accuracy. is QLoRA; are LoftQ settings. The selected run improves sharply at , peaks at , then decreases at . It is evidence for sensitivity, not monotonicity.

Source: LoftQ v4, Figure 3 right. This source-reported NF4 BART-large result peaks at among the plotted settings and then declines. More alternating steps are neither free nor guaranteed to improve downstream quality.
0x07N PiSSA, QLoRA, And LoftQ Change Different Initial States
| Question | QLoRA | PiSSA | LoftQ |
|---|---|---|---|
| base representation | quantized | full-precision spectral residual | quantized residual state matched to adapter |
| initial branch | zero output | principal component of original | top-r component of quantization residual |
| quantization required | yes | no | yes |
| full method changes base | quantization only | subtracts principal component | may re-quantize each alternating step |
| owned objective | training-memory-efficient adaptation | spectral initialization geometry | joint low-bit base plus low-rank reconstruction |
PiSSA and LoftQ both use SVD, but SVD is a tool, not the method identity. PiSSA decomposes the original weight into principal and residual components. LoftQ decomposes the error left by a particular dequantized base. QPiSSA and other hybrids require their own state contract.
0x07O Failure And Claim Closure
| Failure | Why it is wrong | Required check |
|---|---|---|
| call practical quantization an exact coordinate minimizer | the paper itself labels the update approximate | pin quantizer algorithm and avoid convergence theorem |
| assume every lowers error | dynamic discrete quantization can increase the full objective | record per-iteration objective and stop policy |
| load full-LoftQ factors on fresh | factors are coupled to a modified final base | bind adapter to base fingerprint |
| ignore LoRA scale | paper factors reconstruct , while runtime executes | require or scale-aware factors |
| call PEFT replacement full LoftQ | it keeps the existing base and performs one residual SVD | name path and version explicitly |
| discard codebook/scales/layout | dequantized shape does not identify quantized state | persist quantizer ABI |
| claim weight error proves task quality | objective is input-agnostic Frobenius error | measure outputs and downstream tasks |
| assume dropout preserves initialization per sample | dropout changes branch inputs | separate eval and training-mode tests |
| call adapter branch free at serving | LoftQ initializes LoRA; it does not erase its matmuls | measure live or requantized-merge path |
The Loop 7 publish gate is:
paper objective and repository orientation reconciled
quantizer and SVD guarantees separated
rank-r residual floor derived
exact alternating and nonmonotonic witnesses checked
T=0, T=1, T>1, and replacement paths separated
LoRA scale included in reconstruction
paper, reference repo, and pinned PEFT behavior distinguished
quantized base, adapter, and quantizer metadata bound as one artifact
dropout, merge, runtime, and resume boundaries explicit
paper figures labeled source-reported
0x08 DoRA: Magnitude-Direction Coordinates Change Forward, Backward, And Merge
LoRA’s additive rule is deliberately simple:
The same low-rank product must account simultaneously for changes in each weight vector’s length and orientation. The DoRA paper v6 asks whether those two jobs should have separate coordinates. Its motivation draws on weight normalization, but the adaptation contract is different: DoRA starts from a pretrained weight, freezes its dense directional base, makes a vector of magnitudes trainable, and applies LoRA to the directional update.
That sentence hides four contracts that cannot be compressed into “LoRA plus a norm”:
mathematical contract:
which weight vectors are normalized, and along which tensor axis?
optimization contract:
does backward differentiate through the normalization denominator?
runtime contract:
is the adapter live, dropped out, cached, quantized, or merged?
artifact contract:
which magnitude, factor, base, scale, cache, and resume states are required?
This section owns those contracts for a linear layer. It does not claim that
DoRA is merely a larger-rank LoRA, that the learned object named magnitude
remains nonnegative, or that a live DoRA adapter has the same serving cost as a
merged dense weight.

Source: DoRA v6, Figure 1. The figure shows the paper’s column-vector parameterization and the low-rank directional branch. It does not specify a framework’s storage orientation, detached-norm backward, dropout path, cache policy, or unmerge preconditions.
0x08A Paper Columns And PyTorch Rows Are Transpose-Equivalent, Not Axis-Identical
The paper writes
and treats each column as one weight vector. With
the decomposition is
The paper abbreviates this as
where the broadcasting is over columns.
PyTorch stores an ordinary Linear.weight as
and executes row-input batches as
Each output neuron is therefore one row of weight. In that orientation,
the transpose-equivalent DoRA vector norm is
which is torch.linalg.norm(U, dim=1), not dim=0. The magnitude state is
The conversion ledger is:
| Contract | Stored matrix | Vector being normalized | Norm axis | Magnitude length |
|---|---|---|---|---|
| DoRA paper | each column | paper column axis | ||
PyTorch Linear | each output row | dim=1 | ||
| relation | paper column = PyTorch row after transpose | transpose conversion | same logical vectors |
Saying only “column norm” while showing a PyTorch-shaped tensor is an implementation bug waiting to happen. The Loop 8 oracle computes both orientations and obtains zero maximum difference after transposing back.
0x08B Derive The Scale-Aware Forward From The Executed Weight
Keep the repository’s vanilla-LoRA factor convention:
The framework scale is part of the directional state:
For every output row, define
Stacking rows gives
and the effective DoRA weight is
The row-input linear layer therefore executes
This derivation answers two common ambiguities:
- must be inside the norm because the normalized object is the actual directional weight .
- is one scalar per normalized weight vector, not a rank- object.
The trainable-parameter ledger for one PyTorch linear is
versus
The extra parameter count is small relative to , but the forward is not just two thin adapter matmuls: it also needs the current dense directional norm and output-wise factor unless those values are safely cached or the adapter is merged.
def dora_linear_weight(W0, A, B, magnitude, scale):
# PyTorch Linear.weight convention: [d_out, d_in].
U = W0 + scale * (B @ A)
c = torch.linalg.vector_norm(U, dim=1) # [d_out]
if torch.any(c == 0):
raise ValueError("zero-norm DoRA direction row")
f = magnitude / c # [d_out]
return f[:, None] * U
The pinned PEFT v0.19.1 path does not clamp c with an epsilon. Adding an
epsilon may be a defensible alternative design, but it changes forward values,
gradients, merge parity, and the artifact contract. It must not be silently
attributed to that implementation.
0x08C Initialization Preserves The Function But Opens Two First-Step Paths
At installation, DoRA takes the pretrained row norms:
and uses an ordinary no-op LoRA factor initialization, conventionally
with nonzero. Then
so
This is exact function preservation in the chosen dtype when every row norm is finite and nonzero. It does not imply zero gradients. As the next derivation shows, both the magnitude vector and can receive first-step gradients, while
under the standard convention. DoRA therefore preserves vanilla LoRA’s first-step factor asymmetry while adding a separate first-step magnitude path.
0x08D The Full Normalization Jacobian Projects Direction Gradients Onto A Tangent Space
The matrix formula is easiest to audit one output vector at a time. Drop the row index and let
For an infinitesimal perturbation ,
Differentiate the normalized vector:
Substitute and :
Now let
Because
the loss differential is
Therefore
and
The projector removes the radial component:
Thus the directional update is tangent to the unit sphere under the full normalization Jacobian. This is the precise optimization geometry behind the paper’s discussion of projected and rescaled gradients. The paper’s statements about improved conditioning and stability are theoretical interpretation plus source-reported experiments; they are not a theorem that DoRA dominates LoRA on every objective.
The factor chain rule is still required. Since
and is frozen,
and
def dora_full_backward(U, magnitude, upstream_G):
c = vector_norm(U, dim=1) # [d_out]
q = U / c[:, None] # [d_out, d_in]
radial = (q * upstream_G).sum(dim=1) # q_i dot g_i
grad_m = radial
grad_U = (magnitude / c)[:, None] * (
upstream_G - q * radial[:, None]
)
assert allclose((q * grad_U).sum(dim=1), 0)
return grad_m, grad_U
0x08E Detaching The Norm Preserves Forward Values, Not The Exact Gradient
The paper also proposes a lower-memory implementation that treats the current norm as a constant in backward. The forward still evaluates the same
but the derivative no longer includes . Its gradients are
and
The difference is exactly the removed radial correction:
Consequently,
which is generally nonzero. Calling this detached rule “the exact gradient of the normalized parameterization” would be wrong. It is an alternative backward contract with the same forward values.
The DoRA paper reports that this modification reduced training memory by about 24.4% in one LLaMA setup and 12.4% in one VL-BART setup with negligible or no reported accuracy change under those experiments. Those are source-reported measurements, not universal memory ratios. PEFT v0.19.1 implements the detached-norm path for its DoRA variants.
0x08F Exact Three-By-Three Forward And Backward Trace
The checked Loop 8 oracle uses
The negative third entry is intentional. The paper interprets as a magnitude, but PEFT stores an unconstrained trainable parameter initialized from positive norms. Without a positivity parameterization, optimizer updates do not mathematically guarantee .
The low-rank product is
Therefore
Its row norms and DoRA factors are
The merged effective weight is
For the oracle’s two-row input, decomposed live execution and dense merged execution both produce
with zero maximum difference at the checked precision.
For a fixed upstream weight gradient , the exact full-normalization oracle obtains
and
Central finite differences agree within
for and
for . The checked tangent products are exactly zero after report rounding. The detached-norm gradient differs from the full gradient by Frobenius norm
and has nonzero radial components
At no-op initialization and
the oracle verifies
effective-weight error: 0
grad(A): exactly zero
grad(B): nonzero
grad(m): nonzero
This trace checks operator algebra and gradient contracts. It does not reproduce the paper’s training runs.
0x08G Pinned PEFT v0.19.1 Executes A Decomposed Correction
The official DoRA repository and modern PEFT are related implementations, not
one timeless code path. For a versioned framework claim, this article pins
PEFT v0.19.1 at commit
ba6a19060d6ab54a87538a6e77e3e4d5a907375b.
Its DoraLinearLayer
does the following for a linear layer:
- dequantizes the base module weight when necessary;
- obtains a dense LoRA weight, using identity-through-/ evaluation
rather than direct
B @ Ain one path because of the pinned code’s FSDP compatibility concern; - computes
norm(weight + scaling * lora_weight, dim=1); - detaches the LoRA weight for the norm and detaches the resulting norm;
- forms ;
- returns a correction to be added to the already-computed base result.
Ignoring bias for one line, the correction is
The wrapper then adds it to :
With bias, the pinned path subtracts the base bias from the reused result inside the DoRA correction, so the outer linear bias remains exactly once.
def peft_v0191_dora_eval(x, base_layer, lora_A, lora_B, magnitude, scale):
base_result = base_layer(x)
lora_weight = materialize_lora_weight_for_norm(lora_A, lora_B)
base_weight = dequantize_module_weight(base_layer)
c = row_norm(base_weight + scale * stop_gradient(lora_weight))
f = magnitude / stop_gradient(c)
lora_result = lora_B(lora_A(x))
base_no_bias = remove_bias_once(base_result, base_layer.bias)
correction = (f - 1) * base_no_bias + f * scale * lora_result
return base_result + correction
The implementation’s optional DoRA cache is disabled by default. In this
version it is an ad hoc cache, active only under explicit enablement, eval mode,
and an adapter name; entering training clears it. It is not state_dict
checkpoint state. The code also uses ephemeral GPU offload in DoRA
initialization; that flag should not be generalized into a claim that every
live forward is automatically offloaded.
0x08H Adapter Dropout Changes The Executed Training Graph
When dropout is identity or the module is in eval mode, PEFT can reuse the
already-computed base result. During training with nontrivial adapter dropout,
the DoraLinearVariant
forward
instead applies dropout to and asks the DoRA layer to recompute the base
linear map on that dropped input.
Let be the sampled, scaled dropout input and omit bias. The total pinned training path is
This is not, sample by sample,
At no-op initialization, however, and , so the dropout terms cancel exactly:
The oracle checks both facts: trained dropout differs from merged eval, while initial dropout preserves the base output. A weight-space parity test that ignores training dropout is therefore insufficient.
0x08I Merge Is A State Transition; Exact Unmerge Needs Cached Pre-Merge Geometry
Define the already-scaled delta
the pre-merge directional norm
and
The merged weight is
This gives ordinary dense execution for one fixed adapter and is the condition under which a no-additional-inference-branch claim is meaningful.
But cannot generally be recomputed from because normalization
and magnitude scaling have changed the matrix. The pinned
merge_safe, merge_unsafe, and unmerge
paths
cache the pre-merge directional norm and recover
Exact invertibility requires:
cached c corresponds to the same W0, delta, adapter, scale, and merge order
m and A/B remain unchanged while the adapter is merged
every f_i is finite and nonzero
merge and unmerge use compatible orientation and dtype rules
stacked adapter merges unwind in the framework's required order
If , then : merge can produce a finite zero row, while unmerge’s division by is undefined. PEFT’s safe merge checks whether the merged weight is finite, but that check alone does not prove later unmerge invertibility. A production wrapper should reject zero/nonfinite direction norms and zero/nonfinite DoRA factors before mutating the base.
def merge_dora(W0, delta_scaled, magnitude):
c = row_norm(W0 + delta_scaled)
require_all_finite_nonzero(c)
f = magnitude / c
require_all_finite_nonzero(f)
cache = {"premerge_direction_norm": c}
return f[:, None] * (W0 + delta_scaled), cache
def unmerge_dora(Wmerged, delta_scaled, magnitude, cache):
c = cache["premerge_direction_norm"]
f = magnitude / c
require_all_finite_nonzero(f)
return Wmerged / f[:, None] - delta_scaled
The Loop 8 oracle recovers with zero maximum error for its checked fixture. That is an operator test under explicit preconditions, not proof that every dtype, quantized base, or stacked-adapter path is lossless.
0x08J State, Checkpoint, And Runtime ABI
The minimum portable DoRA adapter is larger than a vanilla-LoRA factor pair:
portable adapter state:
A[r, d_in]
B[d_out, r]
magnitude m[d_out]
rank, alpha, and exact scale rule
target module names and weight orientation
base checkpoint identity and expected dtype/backend
exact training resume adds:
optimizer moments for A, B, and m
scheduler state and global step
gradient-scaler / precision state
RNG and data-order state
distributed sharding and ownership metadata
runtime-only state:
optional eval norm / dense-delta cache
merge-unmerge cache keyed by adapter and merge order
The runtime cache is neither sufficient nor appropriate as a portable training checkpoint. Conversely, omitting from an adapter export silently turns the artifact into a different operator even if and load without shape errors.
For adapted linear modules, trainable adapter storage is
Optimizer state multiplies that trainable ledger according to optimizer and precision. Live PEFT may additionally dequantize the base for norm evaluation, materialize a dense -equivalent tensor for the norm path, retain -length norm and factor vectors, and execute the ordinary LoRA branch. Those temporary and compute costs do not appear in the adapter file size.
M6.5 owns adapter registries, request batching, hotswap, and admission policy.
The pinned PEFT linear path rejects per-sample adapter_names when a DoRA
adapter is enabled; this is a versioned integration fact, not a universal DoRA
limitation.
0x08K Design Alternatives Must Name Which Contract Changes
DoRA admits several implementation choices. They are not interchangeable optimizations:
| Choice | Forward effect | Backward effect | Runtime/artifact consequence |
|---|---|---|---|
| paper column vs PyTorch row orientation | transpose-equivalent if converted correctly | corresponding axis conversion | store orientation explicitly |
| full norm Jacobian | exact normalized parameterization | tangent projection present | larger backward graph |
| detached norm | same forward values | radial projection removal absent | paper/PEFT memory-saving path |
| epsilon/clamped norm | changes values near small norms | changes gradients near clamp | epsilon becomes ABI/config state |
| unconstrained | permits signed scale | ordinary scalar gradient | unmerge must reject |
| positive parameterization of | enforces magnitude semantics | chain rule through softplus/exp | different checkpoint and optimizer geometry |
| live adapter | adapter remains selectable | training possible | norm/factor/LoRA runtime work remains |
| cached live eval | same values only if invalidation is correct | eval-only | cache identity and invalidation state |
| merged adapter | one dense weight | not a training-dropout path | no live hotswap; unmerge cache required |
| quantized base / QDoRA | dequantization and quantizer state enter norm | backend-specific | crosses Loop 2 and M8 contracts |
The paper’s QDoRA experiments motivate composition with quantized backbones, but generic quantized-number representation remains M8 work and QLoRA’s frozen low-bit training state remains Loop 2. This section only states the magnitude-direction compatibility boundary.
0x08L Paper, Reference Repository, And PEFT v0.19.1 Are Three Contracts
| Surface | Paper v6 | Official NVlabs reference repository | PEFT v0.19.1 |
|---|---|---|---|
| orientation in explanation/code | columns in | PyTorch rows in implementation | PyTorch rows, with fan_in_fan_out transpose helper |
| magnitude initialization | pretrained vector norms | weight_m_wdecomp copied from row norms | trainable DoraLinearLayer.weight initialized from current row norms |
| norm backward | derives full projector; proposes detach alternative | dora_simple selects detached versus full-style path | detached norm in the integrated DoRA forward |
| scale inside norm | paper notation omits framework-specific detail | implementation-specific LoRA scaling | explicitly includes current adapter scaling |
| quantized initialization | QDoRA evaluated | repository-specific paths | dequantizes module weight; pinned init special-cases Linear4bit copy |
| live cache | not an algorithm theorem | implementation-specific | optional ad hoc cache, disabled by default |
| dropout | experiment/training configuration | reference code behavior | explicit dropped-input recomputation path |
| merge/unmerge | merged inference claim | reference integration | cached pre-merge norm required for exact unmerge |
| mixed adapter names | not a paper contract | not generalized here | rejected for DoRA by pinned linear wrapper |
| supported module classes | method-level description | repository task integrations | code has version-specific linear, embedding, and convolution variants; oracle is linear-only |
The official DoRA repository at the pinned
commit
uses a distinct PEFT fork with weight_m_wdecomp and a dora_simple switch.
The modern PEFT implementation uses integrated LoRA variant hooks. Neither code
surface should be quoted as if it were the other, and neither should be
generalized beyond its pinned revision.
0x08M What The Source-Reported Figures Establish

Source: DoRA v6, weight-decomposition analysis figure for query projections in the paper’s VL-BART case study. Each panel reports layer/checkpoint pairs under that protocol. The differing fitted slopes motivate the separate-coordinate hypothesis; they do not prove that a negative slope is universally optimal or that the three methods used equal budgets.
The paper defines magnitude change as an average absolute difference of vector norms and direction change from cosine distance. Those are diagnostics over merged weights, not training objectives. A method can move to a different point in this plot because of target modules, rank, scale, optimizer, data, or checkpoint timing as well as parameterization.

Source: DoRA v6, layer-wise query projection comparison in the paper’s LLaMA2-7B commonsense-reasoning case study. The plotted gaps are source-reported observations for that setup. They do not establish a universal update-size ordering or replace task, runtime, and ablation measurements.
0x08N Why This Is Not Merely Higher-Rank LoRA
Increasing expands the set of additive matrices . DoRA changes the map from trainable state to effective weight:
LoRA:
effective W = W0 + s B A
factor gradient sees the ordinary additive weight gradient
DoRA:
effective W = diag(m / row_norm(W0 + s B A)) (W0 + s B A)
trainable m owns vector scale
factors act through a normalized directional coordinate
backward may use full tangent projection or detached-norm approximation
Rank and parameterization are independent controls. A higher-rank LoRA may be more expressive as an additive delta; that does not make its gradients, magnitude state, dropout graph, merge cache, or runtime path equal to DoRA.
0x08O Failure And Claim Closure
| Failure | Plausible symptom | Broken contract |
|---|---|---|
normalize dim=0 on PyTorch Linear.weight | shapes broadcast, output differs | paper columns confused with repository rows |
| omit inside and its norm | parity holds only for | executed directional weight changed |
| add an undocumented epsilon | rare small-norm drift | operator and merge ABI changed |
| call detached norm the exact Jacobian | forward tests pass | tangent projection silently removed |
| initialize from the wrong axis | no-op test fails | magnitude does not reconstruct |
| save but omit | checkpoint loads partially | adapter operator changed |
| assume learned stays positive | training seems normal | unconstrained parameter can cross zero |
| merge with | finite zero row | later unmerge divides by zero |
| unmerge without cached pre-merge norm | approximate-looking recovery | normalization is not algebraically inverted |
| mutate while merged | unmerge returns wrong base | cache and adapter generation diverged |
| treat training dropout as one merged weight | eval parity passes | sampled training graph omitted |
| call live DoRA zero-overhead | adapter file is small | dense norm and branch work omitted |
| use runtime norm cache as resume state | eval is fast after warmup | optimizer/RNG/training state missing |
| enable per-sample adapter names in pinned PEFT | request batch fails | versioned mixed-batch restriction ignored |
| generalize paper plots | one setup resembles FT | source-reported evidence made universal |
| call QDoRA generic quantization ownership | methods compose | M8 representation boundary collapsed |
The precise conclusion is broader than “DoRA learns magnitude separately.” DoRA reparameterizes each weight vector as a learned scalar times a normalized direction, sends the low-rank factors through that direction, and thereby changes both the factor gradients and the runtime state machine. Full and detached normalization have identical forward values but different backward operators. A fixed merge can recover ordinary dense inference, while exact unmerge requires cached pre-merge geometry and nonzero factors.
0x09 Composition Is A Contract Vector, Not A Compatibility Checkbox
The preceding loops deliberately changed one object at a time. Real training recipes rarely remain that clean. A run may use a 4-bit base, rsLoRA scaling, PiSSA initialization, DoRA coordinates, and a factor-specific optimizer in one configuration. The tempting conclusion is that independently valid methods are automatically valid when their switches are enabled together.
That conclusion is false.
Two methods can have compatible tensor shapes while disagreeing about which base weight exists, which scale is inside the update, which parameters receive gradients, which optimizer owns them, or what must be saved. A framework may accept both flags yet ignore one. It may execute a forward path for which no paper derives the backward or export contract. It may also reject a combination before constructing a layer.
The owner question for this loop is therefore:
When several LoRA variants are stacked, which exact algebra, configuration, execution, checkpoint, merge, runtime, and evidence contracts remain valid?
This section answers for the operators frozen in Loops 2 through 8 and for Hugging Face PEFT v0.19.1. It does not claim that another PEFT version, another backend, or every layer type behaves identically.
0x09A A Stack Must Name Every Object It Changes
Represent one variant stack as
where:
| Axis | Question | Examples in this article |
|---|---|---|
| what represents the frozen base? | dense floating tensor, NF4 payload plus metadata | |
| who owns rank and its schedule? | fixed rank, AdaLoRA budget and ranknum | |
| how is the low-rank branch scaled? | , | |
| what operator creates the initial base and factors? | zero-, PiSSA, LoftQ | |
| what coordinates define the effective weight? | additive LoRA, normalized DoRA | |
| who owns factor gradients and optimizer groups? | AdamW, LoRA+, LoRA-FA | |
| native pair or converted/exported state? | coupled residual base, portable LoRA conversion | |
| how many initialized adapters mutate or share a base? | one, multiple |
This tuple prevents an acronym such as “QDoRA” from hiding two distinct operators. The quantized base controls how becomes a compute tensor; DoRA controls how that compute tensor and become a normalized effective weight. Neither name alone defines the optimizer, conversion path, or serving artifact.
0x09B Compatibility Has Eight Independent Coordinates
For one stack, record the compatibility vector
The coordinates answer different questions:
- Algebra: does one unambiguous effective-weight operator exist?
- Configuration: does the pinned constructor accept the flags, warn, or reject?
- Forward: is there an executable layer path for the representation and parameterization?
- Backward: are all trainable coordinates and their gradients defined?
- Artifact: can the exact state be saved, identified, and reconstructed?
- Merge: is a supported dense or representation-specific export defined?
- Runtime: can the pinned backend execute the resulting state?
- Evidence: is the composition supported by a primary method source, official code/test, component-only reasoning, or no evidence beyond shape?
“Compatible” is a lossy projection of this vector. For example, the pinned
AdaLoRA configuration inherits use_rslora and accepts it, so
passes. Its SVD layer still computes
lora_alpha / ranknum, not , so the intended forward and
backward rsLoRA coordinates are shadowed. A green configuration cell would
hide the central fact.
The evidence ladder used below is:
primary composition source + pinned implementation/test
stronger than
pinned implementation path only
stronger than
component-level derivation with an explicit missing contract
stronger than
same shape or accepted flags
No lower rung is promoted to a higher one by prose.
0x09C Composition Order Is Part Of The Operator
The generic additive branch is
but that equation is not yet a stack. Initialization may replace the base by a residual, quantization may round that residual, DoRA may normalize , and an optimizer may freeze one factor. A useful execution order is
1. resolve base checkpoint and target-module orientation
2. construct or load the base representation
3. run any base-mutating initializer (PiSSA or LoftQ contract)
4. install rank/allocation and the declared scale rule
5. wrap the resulting direction with additive LoRA or DoRA coordinates
6. construct exactly one optimizer/backward owner per trainable parameter
7. derive the union artifact and its conversion/merge path
8. admit only a runtime that implements that final operator
These operations generally do not commute. The Loop 9 oracle uses the same matrix and a deterministic quantization step in two orders:
where is a best rank-one approximation. The exact fixture gives
Both paths contain a quantizer and a rank-one correction. They do not define
the same initial model. A manifest that records only rank=1 and bits=4
cannot distinguish them.
0x09D QDoRA Has A Defensible Two-Layer Contract
QDoRA is the clearest sourced composition in this design space. DoRA v6 explicitly discusses replacing the LoRA component inside a QLoRA-style frozen low-bit backbone, and the official QDoRA reproduction directory pins a bitsandbytes/FSDP execution path. PEFT v0.19.1 dispatches a DoRA variant for supported quantized linear layers.
Let
and let contain one learned magnitude per PyTorch output row. The effective weight is
The quantized payload is not normalized directly as packed integers. The runtime obtains a compute value , adds the scaled low-rank direction, and applies DoRA’s row geometry. In the deterministic fixture,
Wq row 1 = [1.0, -0.5, 0.5]
s = alpha / r = 2.0
(Wq + sBA) row 1 = [1.22, -0.68, 0.50]
initial magnitude = ||Wq row 1|| = 1.224744871392
effective row 1 = [1.007198734693, -0.561389458681, 0.412786366677]
That state requires the union
quantized base payload + quantizer ABI + scale metadata + compute dtype
LoRA A/B + rank + alpha + scale rule
DoRA magnitude + normalization axis + runtime variant
base checkpoint + target-module identity
It is source-supported, but its accuracy bars remain source-reported rather than reproduced here.

Source: the official NVlabs/DoRA QDoRA materials, also discussed in DoRA v6 Figure 4. The bars report the authors’ LLaMA2-7B and LLaMA3-8B Orca-Math setup. They do not prove that QDoRA universally beats QLoRA or full fine-tuning, and this article does not reproduce the experiment.
0x09E Explicit Or Bounded Framework Compositions
Several other stacks have a narrow, defensible contract when their exact scope is named.
QLoRA Plus rsLoRA
QLoRA changes ; rsLoRA changes only
For a fixed-rank ordinary LoRA layer, the forward composition is therefore
The runtime path is straightforward, but the artifact is still coupled to the quantizer ABI. It is not a license to merge directly into the packed NF4 payload without a defined dequantize/merge/requantize export.
LoRA-FA Plus rsLoRA
The pinned create_lorafa_optimizer helper accepts use_rslora and computes
; its test suite exercises that option. The Loop 5 backward
remains valid because rsLoRA changes the scalar multiplying the frozen-,
trainable- branch. The artifact must retain frozen even though it has no
optimizer state.
PiSSA Plus Fixed-Rank rsLoRA Conversion
PiSSA’s principal/residual split must use the actual scale. With fixed rank,
PEFT can convert the mutated-base PiSSA artifact into a portable LoRA delta
while preserving rsLoRA scaling. If rank_pattern or alpha_pattern is also
present, configuration emits a warning and save_pretrained later rejects the
conversion. Runtime training may have worked; portable export still fails.
Quantized-Base AdaLoRA
The pinned PEFT tree includes SVDLinear4bit. That establishes a framework
path for AdaLoRA factors and allocation state over a bitsandbytes 4-bit base.
It does not make the method LoftQ: no alternating quantization-error
initializer follows merely from using a quantized AdaLoRA layer. The pinned
path also does not expose an ordinary dense merge contract.
0x09F Executable Does Not Mean Paper-Verified
Some combinations are constructible and differentiable in the pinned code yet remain conditional research stacks.
LoRA+ Plus DoRA
The pinned LoRA+ helper groups parameters using names and dimensionality:
if "lora_A" in name:
group = groupA
elif "lora_B" in name or parameter.ndim == 1:
group = groupB_no_decay
DoRA’s magnitude vector is one-dimensional. It therefore receives the same high learning-rate, no-decay group as in that helper. This is observable framework behavior, not a DoRA or LoRA+ paper result. A different classifier could assign its own learning rate and weight decay, producing a different optimizer.
PiSSA Plus DoRA
The pinned construction order can run PiSSA initialization before installing the DoRA magnitude variant. Algebraically, if PiSSA creates
and DoRA initializes , then
The oracle checks zero reconstruction error. That proves the no-op initialization for the declared operator. It does not prove that PEFT’s PiSSA-to-portable-LoRA conversion also preserves DoRA magnitude and runtime identity; no primary composition contract was found for that export.
LoftQ Plus DoRA
The same distinction applies after LoftQ. Let
be the coupled initialized direction. Setting makes DoRA initially reproduce that direction exactly. The fixture verifies zero error. It does not turn the result into a standalone adapter: the quantized base, quantizer ABI, LoftQ factors, and DoRA magnitude remain coupled.
0x09G Rejected, Conflicting, And Shadowed Stacks
The following failures are qualitatively different and must not share one “unsupported” label.
| Stack | Pinned result | Why |
|---|---|---|
| AdaLoRA + DoRA | hard configuration rejection | AdaLoraConfig rejects use_dora |
| AdaLoRA + LoftQ | hard configuration rejection | AdaLoraConfig rejects loftq_config |
| AdaLoRA + rsLoRA | accepted but shadowed | SVD layer executes rather than |
| LoRA+ + LoRA-FA | optimizer-constructor conflict | LoRA+ trains with separate rates; LoRA-FA freezes and owns a custom update |
| LoRA-FA + DoRA | missing backward derivation | the frozen- helper does not derive DoRA normalization and magnitude gradients |
| PiSSA + patterned rsLoRA conversion | training/config warning, export rejection | portable conversion cannot reconcile the patterned scaling contract |
| multiple native PiSSA adapters on one base | unsafe shared-base mutation | each initialization can claim a different residual-base identity |
The AdaLoRA/rsLoRA case is especially important because no exception protects
the reader. AdaLoraConfig inherits the flag, but the pinned SVD layer’s
executed scale remains
The exact oracle reports accepted_but_shadowed at configuration and
shadowed for forward/backward. This is a same-shape counterexample to the
claim that accepted flags prove composition.
LoRA-FA plus DoRA is a mathematical, not merely administrative, gap. Loop 5 derived a -only additive update. Loop 8 showed that DoRA’s full gradient passes through
Freezing does not remove the tangent projection or the gradient of . Until an optimizer derives and tests those terms, reusing the additive LoRA-FA helper would be an unverified new method.
0x09H Artifact Compatibility Is The Union Of Changed State
For a stack , define
The union is necessary but not always sufficient. Interaction fields can be new. A QDoRA artifact needs both quantizer and magnitude identities. A PiSSA/rsLoRA conversion needs the initial adapter and exact scale convention. LoRA+ plus DoRA needs an optimizer-group policy for , which neither method’s short name specifies.
| Changed mechanism | Additional portable or resume state |
|---|---|
| NF4 base | packed payload, quantizer type, block size, scales/double-quant metadata, compute dtype |
| AdaLoRA | rank pattern, ranknum, schedule; importance and optimizer state for exact resume |
| rsLoRA | explicit scale rule and rank/alpha used to reconstruct it |
| PiSSA | residual-base identity, initial adapter identity, conversion rule |
| LoftQ | quantizer ABI and coupled quantized-base identity |
| DoRA | magnitude vector, normalization axis, DoRA runtime variant |
| LoRA+ | parameter-group classifier and learning-rate ratio |
| LoRA-FA | frozen- payload/identity and FA scale rule |
A load test that checks only tensor keys can still accept the wrong semantics. The loader must validate base identity, orientation, target modules, rank and scale convention, initializer/conversion lineage, quantizer ABI, coordinate parameterization, and optimizer schema when resuming.
0x09I Paper, Repository, And Framework Answer Different Questions
| Evidence surface | What it can establish | What it cannot establish alone |
|---|---|---|
| method paper | equations, intended algorithm, source-reported experiments | behavior of a later PEFT release |
| official method repository | one concrete integration and reproduction path | all frameworks, layers, and pairwise variants |
| pinned PEFT source | accepted/rejected flags and executed code path | scientific validity or equivalence to paper pseudocode |
| pinned PEFT tests | behavior actually asserted by maintainers | untested export and cross-method guarantees |
| Loop 9 oracle | exact tiny-matrix identities and counterexamples | paper benchmark reproduction or large-model quality |
DoRA v6 says DoRA is compatible with LoRA variants and presents QDoRA. That is positive evidence for the compositions actually described. It is not a proof over the Cartesian product of AdaLoRA, LoRA+, LoRA-FA, PiSSA, LoftQ, every quantizer, and every runtime.
Likewise, official code can prove a hard rejection or a shadowed flag without proving that the rejected mathematical combination is impossible. It means the combination is not the pinned framework contract and would require a new owner, derivation, implementation, and test.
0x09J A Decision Procedure That Preserves Uncertainty
def audit_variant_stack(stack, pinned_framework, target_layer):
axes = normalize_changed_object_tuple(stack)
algebra = derive_effective_weight_in_execution_order(axes)
config = inspect_constructor_accept_warn_reject(axes, pinned_framework)
forward = trace_exact_layer_dispatch(axes, target_layer, pinned_framework)
backward = derive_all_trainable_gradients_and_optimizer_owners(axes)
artifact = union_component_state_and_interaction_state(axes)
merge = derive_export_and_unmerge_preconditions(algebra, artifact)
runtime = trace_supported_representation_and_layer_path(axes)
evidence = grade_primary_repo_framework_test_or_component_only(axes)
contracts = [algebra, config, forward, backward,
artifact, merge, runtime, evidence]
if any(contract.status in {"rejected", "conflict", "missing_derivation"}
for contract in contracts):
return reject_or_open_new_method_owner(contracts)
if any(contract.status in {"conditional", "shadowed", "unverified"}
for contract in contracts):
return require_explicit_manifest_and_targeted_oracle(contracts)
return admit_for_end_to_end_reload_testing(contracts)
The final line hands the stack to Loop 10. Loop 9 establishes whether a coherent candidate exists; it does not yet prove that training, checkpoint, export, reload, and resumed optimization preserve it end to end.
0x09K Executable Oracle And Negative Fixtures
The repository evidence bundle contains a deterministic composition oracle:
docs/numinens-evidence/m6-4-adaptation-design-space/
variant_composition_fixture.json
invalid_variant_composition_fixtures.json
variant_composition_oracle.py
variant_composition_report.json
It evaluates sixteen named stacks over all eight compatibility coordinates. It also checks:
- classic and rsLoRA scale values for the same and ;
- QDoRA execution over a dequantized base value;
- exact PiSSA-plus-DoRA and LoftQ-plus-DoRA initialization identities;
- non-commutation of quantization and spectral correction;
- the pinned LoRA+ name/dimensionality classifier, including DoRA magnitude;
- artifact-field unions for every stack;
- hard-rejected, shadowed, conflicting, and unverified cases separately;
- 66 one-field-invalid fixtures, all of which must fail validation.
The oracle intentionally reports PiSSA-plus-DoRA and LoftQ-plus-DoRA initialization identities as exact while leaving their portable artifact evidence false. A numerical identity must not erase a missing source or runtime contract.
0x09L Composition Failure Closure
| Failure | Plausible symptom | Broken coordinate |
|---|---|---|
| treat accepted config as proof | run starts, intended rsLoRA behavior absent | configuration confused with forward |
| infer compatibility from equal shapes | tensors load, gradients follow wrong operator | algebra/backward |
| apply DoRA to packed integers | finite output with wrong geometry | representation/forward |
| reuse LoRA+ grouping for without declaration | magnitude trains at accidental high LR | optimizer/evidence |
| reuse LoRA-FA helper under DoRA | memory improves, gradient is incomplete | backward |
| convert patterned PiSSA/rsLoRA as ordinary LoRA | export fails or scale drifts | artifact |
| call quantized AdaLoRA LoftQ | 4-bit layer runs, intended initialization absent | initializer/evidence |
| save factors without quantizer ABI | adapter loads against a different dequantized base | artifact/runtime |
| save DoRA factors without | shapes partially match, effective weight changes | parameterization/artifact |
| initialize multiple PiSSA adapters against one mutated base | adapter order changes function | base identity |
| generalize QDoRA bars | one paper setup becomes a universal ranking | evidence |
| claim version-independent support | upgrade changes validation or dispatch | runtime/evidence |
The decision rule is deliberately conservative: a stack advances only when its changed-object tuple is complete, every compatibility coordinate has an owner, and uncertainty remains visible. More acronyms do not imply a better method; they imply a larger proof and artifact surface.
0x09M Boundary To End-To-End Execution And Multi-Adapter Serving
Loop 10 owns one complete training/checkpoint/export/reload/resume path after a stack passes this decision surface. It must validate state-dict keys, optimizer ownership, conversion output, and numerical reload parity.
M6.5 owns multiple independently named adapters at serving time: registry, residency, request routing, heterogeneous batching, hotswap, eviction, and KV compatibility. M6.9 owns learned routing, shared factors, composition policies, and continual adapter systems. M8 owns generic low-bit deployment formats and quantization release decisions. This loop uses those mechanisms only to audit one training-stack contract.
0x0A End-To-End Variant Lifecycle: Train, Resume, Export, Reload, Release, Roll Back
Loop 9 answered a composition question: is a proposed stack coherent across algebra, configuration, forward, backward, optimizer, artifact, runtime, and evidence coordinates? That is necessary, but it is not a lifecycle proof. A stack can be mathematically coherent and still fail when a training job resumes, when adapter namespaces are rewritten, when a native initialization is converted, or when a release is rolled back.
This section therefore follows four admitted stacks through one bounded but complete transaction:
| Stack | Why it is included | Changed lifecycle surface |
|---|---|---|
| QLoRA + rsLoRA | quantized/dequantized base plus rank-stabilized additive branch | quantizer ABI, scaling metadata, dense export boundary |
| QDoRA | low-bit base plus normalized magnitude/direction parameterization | detached-normalization backward, magnitude state, normalized export |
| LoRA-FA + rsLoRA | frozen , trainable | optimizer ownership differs from portable artifact ownership |
| PiSSA + fixed-rank rsLoRA | training mutates the base/factor decomposition | native residual-base checkpoint must be converted for the original base |
They are not a claim that these are the four best methods. They are selected because each exposes a different failure class. The executable oracle uses small deterministic float64 tensors, not a paper training reproduction or a replacement for the pinned PEFT runtime.
0x0AA Seven Checkpoints, Not One save_pretrained
The transaction is divided into seven checkpoints:
| Checkpoint | Required state | Question it answers |
|---|---|---|
| immutable manifest | what exact base, quantizer, scale, initializer, namespace, and optimizer does this run mean? | |
| exact-resume snapshot after update one | can optimization restart rather than merely inference? | |
| uninterrupted state after update two | what is the reference continuation? | |
| reload , then apply the same update two | is resumed state identical to uninterrupted state? | |
| slot-neutral portable adapter, reloaded under another slot name | does namespace translation preserve the function? | |
| representation-specific release | what payload actually executes after export? | |
| immutable-base rollback with no adapter | can the release be removed without subtracting rounded deltas? |
The first distinction is between three payload classes:
exact resume:
model/base identity + trainable parameters + required frozen adapter state
+ optimizer moments + optimizer step + scheduler/RNG state in a real run
portable adapter:
inference parameters + base/scale/quantizer metadata
- optimizer moments
- training slot name
release:
the representation consumed by the serving runtime
(dense weight, live adapter, or a separately validated low-bit package)
The reduced oracle has no stochastic layers or scheduler, so its exact-resume payload contains the base tensors, adapter tensors, AdamW moments, and step counter. A real manifest must additionally own RNG streams, data position, gradient scaler, scheduler, and distributed-shard metadata.
0x0AB The Common Two-Step Optimization Trace
All four transactions use the same shape contract:
W0, Wq, W_eff : [d_out=3, d_in=3]
A : [r=2, d_in=3]
B : [d_out=3, r=2]
magnitude : [d_out=3] # QDoRA only
X, G : [tokens=2, 3]
Y = X W_eff^T : [tokens=2, 3]
For the scalar oracle loss
the effective-weight adjoint is
Each trainable coordinate owns independent AdamW moments. With ,
The subscript on and matters. QDoRA’s magnitude
vector can use a different optimizer group; LoRA-FA has no optimizer slot for
at all. Saving only tensors named lora_A and lora_B cannot reproduce
either optimizer contract.
The exact-resume test is intentionally stronger than an output tolerance:
state_1 = adamw_step(initial_state, batch_1)
resume_payload = json_round_trip(all_resume_state(state_1))
state_2_direct = adamw_step(state_1, batch_2)
state_2_reload = adamw_step(restore(resume_payload), batch_2)
assert state_2_direct == state_2_reload
assert sha256(state_2_direct) == sha256(state_2_reload)
The JSON encoding retains Python float round-trip precision; it is not rounded for the resume path. All four hashes match exactly. That proves the oracle’s serialized float64 state machine, not bitwise parity across GPU kernels, distributed reductions, or framework releases.
0x0AC QLoRA Plus rsLoRA: Coupled Base Identity, Separate Release Identity
The QLoRA transaction begins from a stored low-bit payload whose execution value is represented by . Its additive path is
For and , the oracle records . The persistent training state includes:
immutable base identity nf4_payload_v1
quantizer ABI nf4_block64_double_quant_v1
adapter A[2,3], B[3,2]
optimizer m_A, v_A, m_B, v_B, step
scale contract alpha=4, r=2, alpha/sqrt(r)
The quantizer ABI is not decorative metadata. The portable factors reconstruct the same function only against the same dequantized base contract. A loader that silently changes block size, codebook, double-quant metadata, or base revision changes before the adapter executes.
The oracle’s payload removes the training slot:
local:
base_model.model.proj.lora_A.default.weight
base_model.model.proj.lora_B.default.weight
portable:
proj.lora_A.weight
proj.lora_B.weight
reloaded local namespace:
base_model.model.proj.lora_A.task_blue.weight
base_model.model.proj.lora_B.task_blue.weight
It then reconstructs and from that portable payload, binds them to the immutable identity, and obtains zero weight and output error relative to the trained state.
The oracle release is deliberately a dequantized dense weight,
That is not an in-place low-bit merge. Producing a low-bit serving artifact would require a new quantization pass, calibration and error checks, kernel compatibility, and release acceptance owned by M8. Calling the dense material- ization “merging into NF4” would erase an entire representation transition.
At , rollback restores the immutable quantized runtime base plus no adapter. It does not restore the pre-quantized , and it does not compute .
0x0AD QDoRA: The Forward Geometry And Training Adjoint Are Separate Contracts
QDoRA adds a learned row magnitude around the low-bit direction:
The declared initializer uses and . Therefore
This identity is tested before optimization. Reusing the nonzero illustrative from another stack would violate the initializer even though all tensor shapes still match.
For one output row, let . The full normalization adjoint is
The bracket projects the gradient onto the tangent space of the unit sphere. The pinned PEFT DoRA path uses a detached weight norm in the low-rank branch; the corresponding pedagogical training adjoint omits that radial projection:
Those are intentionally not described as the same gradient. The oracle finite-difference checks the full forward derivative and obtains maximum error below ; separately, it executes the detached-normalization training rule. Their largest elementwise difference in the toy state is , making the implementation choice visible instead of hiding it behind the name DoRA.
The QDoRA exact-resume payload must contain moments for , , and . The portable inference payload excludes those moments but includes all three parameter tensors, base identity, quantizer ABI, normalization parameterization, and scale. Omitting produces a shape-plausible LoRA artifact with the wrong function.
Its release materializes
As with QLoRA, this is a dense normalized release, not proof of a supported low-bit in-place merge.
0x0AE LoRA-FA Plus rsLoRA: Frozen Is Not Absent
LoRA-FA keeps fixed and updates only :
The optimizer owns only
B, m_B, v_B, step
but both training continuation and portable inference still depend on . The resulting ownership table is deliberately asymmetric:
| State | Trainable? | Optimizer moments? | Saved for exact resume? | Saved for portable adapter? |
|---|---|---|---|---|
| no | no | yes | yes | |
| yes | yes | yes | yes | |
| base identity | no | no | yes | referenced |
| scale rule | no | no | yes | yes |
This is why “save all trainable parameters” is not a sufficient artifact rule. Dropping frozen destroys even though no optimizer ever updated it. Conversely, placing fake AdamW moments beside would misrepresent the optimization state and complicate exact resume.
The oracle confirms that the optimizer key set is only B, while the
portable key set contains both lora_A and lora_B. Its dense release
reproduces the live branch exactly, and rollback restores immutable
rather than subtracting the learned update.
0x0AF PiSSA Plus Fixed-rank rsLoRA: Native And Portable Coordinates Differ
PiSSA begins with a scale-aware rank- factorization:
Training keeps fixed and changes the factors to :
That native artifact cannot be interpreted as an ordinary adapter on the original , because already contains . Substitute the initial decomposition:
The difference of two rank- products has rank at most . A portable ordinary-LoRA representation is therefore
The conversion doubles the stored rank. Under rsLoRA, simply changing the metadata from to would change the scale. To preserve , the converted alpha must satisfy
For the fixture, becomes and becomes
, while remains
. The converted payload reloads under task_blue against immutable
with zero weight and output error.
This stack produces two distinct components:
- a rank-doubled portable adapter on ;
- a dense materialization of the same effective weight.
The dense component contains no live adapter keys. The portable component does. Combining those statements into “the release has no adapter” would be false. Rollback uses the immutable original plus no adapter; the training-time residual is not an archival rollback checkpoint by itself.
0x0AG Namespace Translation Is A State-Dict Operation, Not Algebra
Adapter slot names are runtime registry coordinates. They should not be baked
into a portable artifact as if default were part of the learned function.
The loader performs an explicit translation:
def portable_to_local(portable_state, local_prefix, reload_slot):
local = {}
for portable_key, tensor in portable_state.items():
stem = strip_portable_prefix(portable_key)
local_key = f"{local_prefix}.{stem}.{reload_slot}.weight"
local[local_key] = tensor
return local
Translation is admitted only after validating base identity, quantizer ABI,
rank, alpha, scale rule, initializer/conversion status, and parameterization.
Renaming keys does not authorize rebasing an adapter, changing its quantizer,
or dropping DoRA magnitude. The oracle proves default is absent from portable
keys and task_blue is present after reload; it also reconstructs the output
from the translated tensors rather than reusing the in-memory trained model.
0x0AH Export Is A Derived Artifact, Not The Resume Checkpoint
The four export rules are:
| Stack | Native training execution | Portable/runtime artifact | Dense release rule |
|---|---|---|---|
| QLoRA + rsLoRA | + quantizer/base/scale ABI | materialize in declared dense dtype | |
| QDoRA | + quantizer/base/normalization ABI | materialize normalized effective weight | |
| LoRA-FA + rsLoRA | , frozen | + base/scale ABI | materialize |
| PiSSA + rsLoRA | rank- converted on | materialize either equivalent expression |
None of these portable artifacts contains optimizer moments. None is therefore an exact-resume checkpoint. Conversely, an exact-resume checkpoint can be a poor serving artifact because it contains optimizer state, training namespaces, native residual coordinates, or a training-oriented quantizer layout.
Release acceptance checks the function at the boundary:
portable = export_slot_neutral_adapter(trained_state)
reloaded = load_against_immutable_base(portable, slot="task_blue")
dense = materialize_representation_specific_release(reloaded)
assert max_abs(reloaded.weight - trained.weight) <= tolerance
assert max_abs(X @ dense.T - X @ trained.weight.T) <= tolerance
assert dense_contains_no_live_adapter_keys(dense)
The last assertion applies to the dense component, not to a bundle that also ships a portable adapter.
0x0AI Rollback Restores Identity; It Does Not Invert Floating-point History
Arithmetic unmerge looks attractive:
But it depends on retaining the exact factors and scale, matching dtype and rounding order, and avoiding any intervening quantization or normalization. QDoRA is not additive in the released coordinate at all. A requantized QLoRA release is also not invertible by subtracting a floating-point delta from its packed payload.
The lifecycle rule is therefore:
rollback = load(immutable_base_identity) + activate(no_adapter)
For low-bit stacks, that identity is the immutable quantized runtime base. For
dense LoRA-FA and converted PiSSA, it is the immutable dense . All four
oracle transactions report zero rollback error and explicitly report
uses_arithmetic_unmerge = false.
0x0AJ Rejected And Bounded Lifecycle Cases Stay Rejected
Loop 10 does not turn Loop 9’s unknown or conflicting stacks into supported methods merely by writing generic save code:
| Stack | Stop point | Why no end-to-end transaction is claimed |
|---|---|---|
| AdaLoRA + DoRA | configuration | pinned configuration rejects the composition |
| AdaLoRA + LoftQ | configuration | pinned initialization path does not establish the combination |
| LoRA+ + LoRA-FA | optimizer construction | separate-factor rates conflict with frozen- ownership |
| LoRA-FA + DoRA | backward derivation | no admitted -only normalized-direction adjoint |
| patterned PiSSA + rsLoRA | portable export | conversion cannot preserve an undeclared per-pattern scale transformation |
| quantized AdaLoRA | merge | supported merge/release path is not established |
“Rejected” means the proof surface stops at the named stage. It does not mean the combination is mathematically impossible forever. Implementing one would require a new owner contract, backward derivation, artifact schema, runtime path, and evidence bundle.
0x0AK Executable Oracle And Measured Closure
The repository evidence bundle is executable:
docs/numinens-evidence/m6-4-adaptation-design-space/
variant_lifecycle_fixture.json
invalid_variant_lifecycle_fixtures.json
variant_lifecycle_oracle.py
variant_lifecycle_report.json
It checks:
- four selected stack transactions over ;
- full-forward finite-difference gradients, separately from QDoRA’s detached training adjoint;
- exact direct-versus-resumed state hashes after the second AdamW update;
- portable state with optimizer exclusion and slot-neutral keys;
- reload under a different adapter name from the portable payload itself;
- PiSSA rank doubling and rsLoRA alpha conversion;
- dense release output parity and component-specific adapter-key accounting;
- immutable-base rollback without arithmetic unmerge;
- six rejected or bounded stack cases;
- 95 one-field-invalid manifests, all of which must fail validation.
The maximum full-forward finite-difference error is . Every direct/resume state error, portable reload weight error, portable reload output error, dense export output error, and immutable rollback error is zero in the deterministic fixture. These are oracle results, not model-quality, throughput, convergence, low-bit kernel, or cross-release compatibility measurements.
0x0AL Training, Artifact, And Runtime Comparison
| Method | Extra training state | Forward-path change | Standard dense merge possible? | Serving caveat |
|---|---|---|---|---|
| LoRA | and optimizer state | two low-rank matmuls | yes | adapter identity/rank affects batching |
| QLoRA | quant metadata and possible paged optimizer behavior | quantized base kernel plus LoRA | only through declared materialize/requantize path | training format may not be serving format |
| AdaLoRA | importance statistics, schedule, SVD-like factors | low-rank branch with changing active components | after final structure is fixed | heterogeneous ranks complicate kernels |
| rsLoRA | no new tensor family | different scalar scale | yes | scaling convention must travel with checkpoint |
| LoRA+ | optimizer groups and learning-rate ratio | unchanged | yes | optimizer state changes; inference algebra does not |
| LoRA-FA | optimizer state for only; portable artifact retains | additive branch with frozen | yes | frozen state is still required state |
| PiSSA | SVD initialization and residual base | low-rank branch over residual base | yes after correct conversion | native and portable coordinates differ |
| LoftQ | quantizer state and alternating initialization | quantized base plus LoRA | implementation-dependent export | preserve quantizer ABI and coupled base identity |
| DoRA | magnitude vector and normalization | magnitude/direction reconstruction | yes after materializing normalized weight | live runtime needs the matching DoRA path |
0x0AM Boundary To Multi-Adapter Serving And Generic Deployment
This loop follows one selected adapter at a time. M6.5 owns adapter registries, multiple resident adapters, heterogeneous-request batching, hotswap, eviction, request routing, and KV compatibility. M6.9 owns learned routing, shared factors, adapter composition, and continual systems. M8 owns generic dense-to- low-bit release formats, calibration, target-hardware evaluation, packaging, release promotion, and rollback across deployment representations.
0x0B Failure Closure, Complete Sources, Figures, Links, And Reproducibility
A list of plausible mistakes is not yet a failure contract. A publishable method comparison must say which invariant failed, which executable observation detects it, what state becomes untrustworthy, and which component owns recovery. That is especially important here because many failures preserve tensor shape: a wrong scale, stale quantizer ABI, missing frozen factor, or incompatible base can all load successfully and still execute the wrong function.
0x0BA A Failure Record Needs Five Coordinates
Every failure in the machine-readable closure manifest has five coordinates:
failure id and category:
a stable identity and the alarm family that owns it
invariant:
the algebraic, representation, optimizer, artifact, or lifecycle fact
that must remain true
detector:
an executable equality, hash, conservation law, state-schema check,
finite-difference comparison, or bounded discrepancy
consequence:
the first state or claim that can no longer be trusted
recovery owner:
reject configuration, rebuild initialization, restore immutable base,
reload exact resume state, regenerate export, or narrow the claim
The recovery owner matters. A quantizer-ABI mismatch is not repaired by rescaling the adapter. A missing optimizer moment is not repaired by reloading a portable inference artifact. A source-reported curve is not made reproducible by rerunning the tiny algebra oracle.
0x0BB Same Shape Does Not Mean Same Semantics
Shape checks are necessary, but they cannot establish method identity. The following counterexamples preserve the expected matrix dimensions while violating a different coordinate:
| Same-shape state | Hidden semantic mismatch | Required detector | Recovery |
|---|---|---|---|
| NF4 payload with the expected packed byte count | codebook order or nested-scale metadata changed | quantizer ABI plus exact dequantized-value hash | reject the artifact and restore the declared quantized base |
| AdaLoRA triplets with the expected maximum rank | importance EMA, uncertainty, or budget step omitted | replay the schedule and global threshold against the recorded step | reload exact allocator state or restart allocation from a declared boundary |
| rsLoRA factors with unchanged shapes | rank changed while alpha or scale exponent stayed stale | recompute and the branch-output checksum | reject or rescale under an explicit conversion contract |
| LoRA+ optimizer with all expected parameter names | and groups use the same learning rate | inspect group identity and scheduler-adjusted rates | rebuild optimizer groups before the next update |
| LoRA-FA checkpoint with a valid trainable | frozen absent or paired with another base | hash frozen and compare the induced projector | restore the exact frozen factor; do not synthesize one |
| PiSSA factors of rank | residual base paired with the original pretrained base or portable rank- payload mislabeled as native | reconstruct the initial effective weight and inspect artifact schema | reload the matching residual base or run the declared conversion |
| LoftQ adapter with valid low-rank factors | quantized base came from another alternating step or quantizer | evaluate the coupled reconstruction objective and base hash | restore the coupled base/adapter pair |
| DoRA magnitude vector with the expected length | magnitude belongs to another normalized direction or row/column convention | reconstruct executed rows and compare live/merge output | reject the pair and reload matching magnitude-direction state |
| portable adapter whose keys parse correctly | base revision, target slice, scale, or representation identity differs | slot-neutral reload plus effective-weight checksum | fail admission before graph mutation |
| dense release with the expected tensor shapes | release was formed from stale live state or arithmetic unmerge | compare release components and output against the immutable manifest | regenerate release from the admitted checkpoint |
Output equality at one probe is also insufficient. A zero- LoRA branch and a missing branch both produce the base output at initialization, but only the former owns trainable state and the first-step gradient asymmetry. QDoRA’s full normalization derivative and detached-norm training adjoint share the same forward tensor yet implement different backward contracts. Detection must therefore inspect the coordinate that defines the method, not merely one output.
0x0BC Failures Belong To Different Alarms
The closure manifest groups thirty-six records across Loops 2 through 10:
| Alarm family | Representative invariant | Detector | Canonical recovery owner |
|---|---|---|---|
| representation and precision | packed base, codebook, scale hierarchy, compute dtype, and quantizer ABI agree | exact dequantization trace and representation hash | artifact admission or immutable-base restore |
| allocation and schedule | rank budget, importance state, mask interval, and optimizer step are synchronized | schedule replay, global projection count, and exact-resume state hash | allocator/checkpoint owner |
| scaling and optimization | branch scale, factor groups, frozen state, and backward operator match the declared variant | analytical/finite-difference gradient and optimizer-group trace | configuration or optimizer reconstruction |
| spectral and initialization | principal/residual or quantization-error coordinates reconstruct the declared initial function | SVD residual, objective, and initial-output equality | initialization/conversion owner |
| composition and lifecycle | union artifact, namespace translation, release, and rollback preserve representation identity | slot-neutral reload, component inventory, output equality, and immutable hash | export/release controller |
| evidence and scope | a paper plot, teaching oracle, framework trace, and production claim keep distinct evidence classes | provenance record and claim firewall | editorial/source owner |
No alarm substitutes for another. A finite-difference gradient can validate a local backward formula while saying nothing about a missing RNG state at resume. A successful portable reload can validate inference state while saying nothing about optimizer continuity. A paper figure can motivate a method while proving neither this article’s oracle nor a target deployment.
0x0BD Complete Source, Link, Visual, And Negative-Test Surface
Loop 11 closes the static publication surface rather than sampling it:
28 unique source records
3 digest-pinned local owners
11 version-pinned primary papers
1 unversioned QLoRA arXiv landing link kept by a figure caption
13 pinned official implementation or documentation surfaces
25 unique external URLs published by this article
5 normalized local post routes
53 A22 figure dispositions, including all 18 M6.4-owned source figures
31 rendered visual elements and 41 static desktop/mobile asset routes
36 typed failure records across Loops 2-10
9 prior invalid-fixture families with 484 one-field mutation cases
18 new one-field publication-surface mutations
The source manifest and published URL set are exact peers: an external URL in
the article without a record is uncovered evidence, while a record absent from
the article is stale publication metadata. The A22 disposition remains complete
even when a source-local image is replaced, deferred, or superseded by a primary
paper figure. Every article image route must resolve, carry nonempty alternative
text, have cumulative provenance, and, for SVG, expose role="img", a
viewBox, <title>, and <desc>.
These are static guarantees. They do not prove that an external host is live, that MathJax completed in a browser, that a mobile table does not overflow, or that dark-mode contrast is acceptable. Loop 12 owns normalized desktop/mobile, light/dark rendering and live-route acceptance.
0x0BE Reproducibility Is A Chain Of Named Artifacts
A serious variant comparison records:
base checkpoint and immutable revision
target module path, object identity, packed slice, and storage alias
rank or rank budget per module
alpha, scale rule, and rank-pattern overrides
initialization method and any residual-base conversion
adapter, accumulation, normalization, and compute dtype
quantizer type, codebook, group size, scale hierarchy, and metadata dtype
optimizer class, factor groups, factor-specific learning rates, and scheduler
which factors are frozen and which activations are retained
rank-allocation schedule, importance smoothing, and projection step
dropout, clipping, sequence length, and activation checkpointing
framework, kernel, and quantizer ABI revision
base, quantizer, adapter, frozen-factor, and optimizer-state hashes
local, resume, portable, and release state-dict schemas
optimizer moments, step, scheduler, scaler, RNG, sampler, and counter ownership
native-to-portable conversion rule and output metadata
release component inventory and target runtime capability
rollback base identity and generation transition
evidence class for every reported number or figure
The executable chain is equally explicit:
Loop 1 manifest and owner firewalls
-> Loops 2-8 method-specific tensor/state oracles
-> Loop 9 composition classifier
-> Loop 10 train/resume/export/reload lifecycle oracle
-> Loop 11 static source, figure, failure, and publication audit
-> Loop 12 normalized browser and cross-article acceptance
Without that chain, two runs both labeled “QLoRA rank 16” can be materially different systems even when their adapter tensors have identical shapes.
0x0BF Final Formula, Rendering, Accessibility, And Boundary Closure
The final audit reconciles five surfaces that cannot substitute for one another:
| Surface | Exact closure | What it does not prove |
|---|---|---|
| source | 298 source-ordered display formulas, 52 tables, 89 fenced code blocks, 31 rendered visual elements backed by 41 desktop/mobile asset routes, 25 external URLs, and five normalized local post routes | formal correctness of every derivation or future availability of an external host |
| generated route | every source display formula becomes one display MathJax source, while every inline and display source completes without a MathJax error | compatibility with every renderer, font override, browser, or assistive technology |
| responsive images | ten picture elements select their mobile source below the declared breakpoint and their desktop source above it; the remaining 21 images retain one source | perceptual quality under every zoom level, color-vision condition, or user stylesheet |
| four browser profiles | desktop/mobile and light/dark profiles load every image and local owner route, preserve unique heading targets, contain article-owned overflow, and produce no article console exception | framework execution, GPU kernels, model quality, memory, latency, throughput, or live third-party endpoint health |
| boundaries | concrete M6.3, M6.5, M6.7, M6.9, and M8.1 owners resolve without long exact prose duplication | that those neighboring owners are already publication-complete |
Browser acceptance does not promote a paper figure, source trace, or teaching oracle into production evidence. It proves only that this built M6.4 snapshot exposes the declared formulas, links, tables, alternatives, and responsive figures without article-local publication defects under the normalized profiles. The source manifest still owns claim provenance; Loops 2 through 10 still own their narrow tensor, optimizer, composition, and lifecycle contracts; and M6.5, M6.7, M6.9, and M8 retain their deferred runtime, theory, continual, and deployment responsibilities.
0x0D Boundary To M6.5 And M8
M6.4 ends after training and export state are defined.
M6.5 owns:
adapter registry and residency
live branch kernels
heterogeneous ranks in one batch
merge, unmerge, and hotswap
adapter paging and eviction
request/KV compatibility
latency and memory telemetry
M6.9 owns learned adapter routing, shared factors, composition, and continual systems.
M6.10 owns distillation and model transfer; M6.11 owns pruning and structural compression.
M8.1 begins M8, the quantization track, which carries low-bit representations through packaging, hardware-specific formats, release promotion, and rollback.
0x0E Publish Gate
| Check | Status |
|---|---|
| Vanilla LoRA state, quantization, rank, initialization, and runtime axes precede the variant map | pass |
| Every variant is organized by the mechanism it changes | pass |
| QLoRA base, adapter, gradient, and optimizer state are separated | pass |
| NF4, double quantization, and paging are explained mechanistically | pass |
| NF4’s asymmetric exact-zero construction is distinguished from naive normal quantiles | pass |
| Double-quantization metadata savings are derived with their source-specific block assumptions | pass |
| Frozen base gradients are separated from input and adapter gradients | pass |
| AdaLoRA rank budget, schedule, importance state, and runtime consequence are present | pass |
| rsLoRA scaling is derived and compared numerically | pass |
| LoRA+ is identified as an optimizer change | pass |
| LoRA-FA trainable state, backward equations, and activation-saving boundary are explicit | pass |
| PiSSA’s principal/residual split is scale-aware and preserves the initial function under the declared dtype tolerance | pass |
| PiSSA factor gradients, tangent rotation, exact/fast SVD distinction, and dropout boundary are derived | pass |
| Native residual-base PiSSA and portable rank-doubled conversion artifacts are separated | pass |
| LoftQ objective derives the executed low-bit base plus scaled low-rank branch | pass |
| LoftQ’s approximate quantizer update and exact fixed-base SVD update are separated | pass |
| T=0, T=1, full alternation, and PEFT one-step replacement are not collapsed | pass |
| LoftQ scale, quantizer ABI, coupled base/adapter artifact, dropout, merge, and resume contracts are explicit | pass |
| Alternating-step and downstream monotonicity are not overclaimed | pass |
| DoRA magnitude/direction tensors and reconstruction are explicit | pass |
| Variant composition is audited over algebra, configuration, forward, backward, artifact, merge, runtime, and evidence independently | pass |
| QDoRA is derived over the dequantized base value and its source-reported evidence remains scoped | pass |
| Hard rejection, optimizer conflict, missing derivation, and accepted-but-shadowed flags are not collapsed | pass |
| Composition order and the union artifact are explicit, including a numerical non-commutation witness | pass |
| The executable oracle classifies sixteen stacks and rejects all 66 one-field-invalid fixtures | pass |
| End-to-end execution separates immutable manifest, exact resume, uninterrupted reference, resumed continuation, portable renamed reload, release, and rollback | pass |
| QLoRA and QDoRA bind portable state to the declared base identity and quantizer ABI | pass |
| QDoRA full normalization gradient and detached-norm training adjoint remain separate contracts | pass |
| LoRA-FA saves frozen while assigning optimizer moments only to trainable | pass |
| PiSSA fixed-rank rsLoRA conversion doubles rank and adjusts alpha to preserve scale | pass |
| Portable renamed reload reconstructs effective weights from the portable payload rather than the live training model | pass |
| Exact-resume direct and reloaded second-update hashes match for all four selected stacks | pass |
| Dense release components contain no live adapter keys and preserve oracle outputs | pass |
| Immutable rollback is representation-specific and never uses arithmetic unmerge | pass |
| The lifecycle oracle closes four transactions and rejects all 95 one-field-invalid manifests | pass |
| Training, artifact, release, and runtime consequences are compared | pass |
| Source-reported results are not generalized | pass |
| Thirty-six typed failures bind invariants to detectors, consequences, and recovery owners | pass |
| All 28 source records, 25 external URLs, five local routes, 53 A22 figure dispositions, and 41 static asset routes reconcile | pass |
| Nine prior invalid-fixture families contain 484 one-field failures across Loops 2-10 | pass |
| Eighteen one-field publication-surface mutations fail closed | pass |
| Static Loop 11 closure remains distinct from browser and live-link evidence | pass |
| Multi-adapter runtime is deferred to M6.5 | pass |
0xFF References
- Transformer Series A22 - LoRA
- M6.3 - LoRA Foundations
- LoRA v2
- QLoRA v1
- AdaLoRA v2
- A Rank Stabilization Scaling Factor for Fine-Tuning with LoRA v1
- LoRA+ v2
- LoRA-FA v3
- PiSSA v4
- PiSSA official repository
- MiLoRA v3
- LoftQ v4
- LoftQ reference repository
- Hugging Face PEFT v0.19.1
- DoRA v6
- DoRA official repository
- Official QDoRA reproduction instructions
- Hugging Face PEFT LoRA documentation