LoRA Mathematics › LoRA Gradient Computation

Michael BrenndoerferDecember 1, 20258 min read
Language AI HandbookAll chapters
Part 35 of 67Parameter-Efficient Fine-tuning
Chapter 256LoRA Mathematics › LoRA Gradient Computation
Reading section 6 of 12 · LoRA Gradient Computation · 8 minSection 6 of 12 · 8 min

Book contents

Section 6 of 12 · 8 min read

LoRA Mathematics › LoRA Gradient ComputationOne section · Sections in this chapter6 / 12 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Gradient flow through LoRA reveals the training dynamics and connects to the optimization concepts from Part X. The gradient formulas explain why the zero initialization of BB does not prevent learning, how AA and BB co-evolve during training, and why the optimization objective makes LoRA training well-behaved.

Understanding gradients has practical value for LoRA. The specific structure of the gradient formulas determines which parameters learn first, how quickly the two matrices co-adapt, and what happens when you change the scaling factor or rank. Practitioners who understand gradient flow can diagnose training problems more easily and tune LoRA more effectively.

Gradient Derivation

Consider the forward pass for a single layer with LoRA adaptation:

h=W0x+αrBAxh = W_0 x + \frac{\alpha}{r} BA x

where:

  • hh: the output vector of the adapted layer
  • W0W_0: the pre-trained weight matrix (frozen, no gradients computed)
  • xx: the input vector to the layer
  • α\alpha: the scaling factor
  • rr: the rank
  • B,AB, A: the LoRA up-projection and down-projection matrices (both trainable)

Let L\mathcal{L} be the loss function we are minimizing. To update AA and BB via gradient descent, we need ∂L∂A\frac{\partial \mathcal{L}}{\partial A} and ∂L∂B\frac{\partial \mathcal{L}}{\partial B}. The chain rule traces how parameter changes propagate through the computation to affect the loss: a small change in AA changes the intermediate activation AxAx, which changes the LoRA output BAxBAx, which changes the layer output hh, which eventually changes the loss L\mathcal{L}.

First, let us define the upstream gradient. Let ∂L∂h=g∈Rd\frac{\partial \mathcal{L}}{\partial h} = g \in \mathbb{R}^d be the gradient of the loss with respect to the layer's output. This gradient comes from the layers above in the network and tells us how changes in hh affect the loss. It is computed by standard backpropagation through the rest of the network and is the "signal" that drives adaptation in both AA and BB.

For the gradient with respect to BB, we apply the chain rule. The LoRA contribution to hh is αrB(Ax)\frac{\alpha}{r} B(Ax). Treating the product AxAx as a fixed vector (since we are differentiating with respect to BB, not AA), the derivative of B(Ax)B(Ax) with respect to BB has a clean outer product form:

∂L∂B=αr∂L∂h⋅∂h∂B(chain rule)=αrg(Ax)T(derivative of linear map)\begin{aligned} \frac{\partial \mathcal{L}}{\partial B} &= \frac{\alpha}{r} \frac{\partial \mathcal{L}}{\partial h} \cdot \frac{\partial h}{\partial B} && \text{(chain rule)} \\ &= \frac{\alpha}{r} g (Ax)^T && \text{(derivative of linear map)} \end{aligned}

where:

  • L\mathcal{L}: the loss function
  • g=∂L∂hg = \frac{\partial \mathcal{L}}{\partial h}: the upstream gradient vector from layers above
  • AxAx: the intermediate vector (input projected down to rank rr)
  • (Ax)T(Ax)^T: the transpose of the intermediate vector
  • α\alpha: the scaling factor
  • rr: the rank

The gradient of BB is an outer product between the upstream gradient gg and the intermediate representation AxAx. Each entry of the gradient (B)il(B)_{il} measures how much increasing that entry would affect the loss, which depends on how much gradient signal arrives at output dimension ii (captured by gig_i) and how active the corresponding bottleneck dimension ll was (captured by (Ax)l(Ax)_l). Dimensions that were heavily activated and carry strong gradient signal receive large updates, while inactive or gradient-free dimensions receive small updates.

For processing batches efficiently, we extend this to matrix form:

∂L∂B=αrG(AX)T\frac{\partial \mathcal{L}}{\partial B} = \frac{\alpha}{r} G (AX)^T

where:

  • L\mathcal{L}: loss function
  • α\alpha: scaling factor
  • rr: rank
  • G∈Rd×nG \in \mathbb{R}^{d \times n}: matrix of upstream gradients for the batch, with one column per example
  • X∈Rk×nX \in \mathbb{R}^{k \times n}: matrix of input vectors for the batch, with one column per example
  • AA: down-projection matrix

For the gradient with respect to AA, we again apply the chain rule, but now we trace through both the multiplication by BB and the multiplication by xx:

∂L∂A=αrBT⋅∂L∂h⋅xT(chain rule through B)=αrBTgxT(substitute g)\begin{aligned} \frac{\partial \mathcal{L}}{\partial A} &= \frac{\alpha}{r} B^T \cdot \frac{\partial \mathcal{L}}{\partial h} \cdot x^T && \text{(chain rule through B)} \\ &= \frac{\alpha}{r} B^T g x^T && \text{(substitute } g \text{)} \end{aligned}

where:

  • BTB^T: transpose of the up-projection matrix, which back-projects the upstream gradient into the bottleneck space
  • L\mathcal{L}: the loss function
  • α\alpha: the scaling factor
  • rr: the rank
  • gg: the upstream gradient vector
  • xx: the input vector to the layer
  • xTx^T: the transpose of the input vector

This formula shows that the gradient with respect to AA involves two stages: first, the upstream gradient gg is projected back through BB using BTgB^T g, which maps the output-space gradient into the bottleneck space. Then, this bottleneck-space gradient is combined with the input xx to form the outer product that updates AA. In matrix form for batch processing:

∂L∂A=αrBTGXT\frac{\partial \mathcal{L}}{\partial A} = \frac{\alpha}{r} B^T G X^T

where:

  • BTB^T: transpose of the up-projection matrix
  • GG: upstream gradient matrix (one column per batch example)
  • XTX^T: transpose of the input batch matrix

Gradient Flow Properties

Several properties of these gradients are noteworthy and reveal important aspects of LoRA's training dynamics. These properties have direct practical implications for how training progresses and what kinds of convergence behavior you should expect.

Independence from W0W_0: The gradients ∂L∂A\frac{\partial \mathcal{L}}{\partial A} and ∂L∂B\frac{\partial \mathcal{L}}{\partial B} are independent of W0W_0. Frozen weights affect the upstream gradient gg through their contribution to the forward pass, but they never appear explicitly in the LoRA gradient formulas. This separation enables efficient training where W0W_0 is never updated. You do not need to compute or store gradients for the much larger frozen weight matrices, which is the key source of LoRA's memory savings during training.

Coupled dynamics: Although AA and BB are separate parameters, their gradients are intimately coupled:

  • ∂L∂B\frac{\partial \mathcal{L}}{\partial B} depends on AA through the term AxAx
  • ∂L∂A\frac{\partial \mathcal{L}}{\partial A} depends on BB through the term BTgB^T g

This coupling means AA and BB co-evolve during training, with AA's current value determining BB's gradient and vice versa. This is similar to the dynamics in other factorized parameterizations like matrix factorization for recommendation systems, leading to interesting optimization behavior including potential saddle points and multiple stable solutions that represent the same effective weight update through different factorizations.

Zero initialization dynamics: At initialization (B=0B = 0), the gradients behave asymmetrically:

  • ∂L∂B=αrg(Ax)T≠0\frac{\partial \mathcal{L}}{\partial B} = \frac{\alpha}{r} g (Ax)^T \neq 0 (generally non-zero, since AA is random and gg is non-zero)
  • ∂L∂A=αrBTgxT=0\frac{\partial \mathcal{L}}{\partial A} = \frac{\alpha}{r} B^T g x^T = 0 (exactly zero because B=0B = 0)

This asymmetry is important: BB updates immediately from the first gradient step, while AA has zero gradient initially. After the first update step, B≠0B \neq 0, and both matrices begin receiving non-zero gradients. The initial zero-gradient phase for AA is brief, lasting only a single step in theory, though in practice the gradients for AA remain small until BB has moved appreciably away from zero. This "bootstrap" phase, where BB adapts alone before both matrices co-evolve, is a direct consequence of the asymmetric initialization.

Computational Cost of Gradient Computation

LoRA's gradient computations are efficient, requiring operations proportional to the parameter count rather than the full weight matrix size. This efficiency is not accidental; it is a direct consequence of the factorized structure and is the key reason LoRA training is so much faster than full fine-tuning.

Computing ∂L∂B=αrgzT\frac{\partial \mathcal{L}}{\partial B} = \frac{\alpha}{r} g z^T where z=Axz = Ax involves the following costs: during the forward pass, we must store z∈Rrz \in \mathbb{R}^r, adding minimal memory overhead of just rr numbers per training example. The gradient computation itself is an outer product between vectors of dimension dd and rr, requiring O(dr)O(dr) operations and creating a d×rd \times r matrix that is directly usable as the gradient for BB.

Computing ∂L∂A=αrBTgxT\frac{\partial \mathcal{L}}{\partial A} = \frac{\alpha}{r} B^T g x^T requires first computing BTgB^T g, which is a matrix-vector product costing O(dr)O(dr) operations (transforming the dd-dimensional upstream gradient into an rr-dimensional signal using BTB^T), followed by forming the outer product with xTx^T, which costs O(rk)O(rk) operations and produces an r×kr \times k matrix that is the gradient for AA.

The total gradient computation is therefore O(r(d+k))O(r(d + k)), matching the parameter count. This is essentially optimal: we need at least one operation per parameter to compute a gradient, and LoRA achieves this lower bound up to constant factors. This efficiency extends to the memory required for gradient storage, which also scales with r(d+k)r(d+k) rather than dkdk, explaining why LoRA reduces GPU memory requirements by over 99% compared to full fine-tuning for large models.