Refer from AI Engineering: Customizing LLMs for Business (Fine-Tuning LLMs with QLoRA & AWS),https:/
Refer from AI Engineering: Customizing LLMs for Business (Fine-Tuning LLMs with QLoRA & AWS),https://zerotomastery.io/courses/learn-fine-tuning-llms
1. What is LoRA?
LoRA (Low-Rank Adaptation) is a technique to fine-tune large models efficiently. Instead of updating a full weight matrix W∈Rk×dW \in \mathbb{R}^{k \times d}W∈Rk×d, we keep WWW frozen and learn a low-rank update ΔW=BA\Delta W = BAΔW=BA, where:
- A∈Rr×dA \in \mathbb{R}^{r \times d}A∈Rr×d is a small trainable matrix,
- B∈Rk×rB \in \mathbb{R}^{k \times r}B∈Rk×r is another small trainable matrix,
- r≪min(k,d)r \ll \min(k, d)r≪min(k,d), where kkk is the input dimension of the layer and ddd is the output dimension.
The effective weight becomes:
Weff=W+ΔW=W+BAW_{\text{eff}} = W + \Delta W = W + BAWeff=W+ΔW=W+BA
so only AAA and BBB receive gradient updates.
2. Why Use LoRA?
- Full fine-tuning updates every weight tensor—expensive in memory and compute.
- LoRA reduces the number of trainable parameters by two or more orders of magnitude.
- In practice it achieves competitive downstream accuracy at a fraction of the cost.
3. Numerical Example
Let:
- input dim d=4d = 4d=4, output dim k=4k = 4k=4, rank r=2r = 2r=2.
The initial matrices are:
W=[10−12011−12−2001111],A=[0.10.20.30.4−0.1−0.20.00.1],B=[10000.5−0.5−11]W = \begin{bmatrix} 1 & 0 & -1 & 2 \\ 0 & 1 & 1 & -1 \\ 2 & -2 & 0 & 0 \\ 1 & 1 & 1 & 1 \end{bmatrix}, \quad A = \begin{bmatrix} 0.1 & 0.2 & 0.3 & 0.4 \\ -0.1 & -0.2 & 0.0 & 0.1 \end{bmatrix}, \quad B = \begin{bmatrix} 1 & 0 \\ 0 & 0 \\ 0.5 & -0.5 \\ -1 & 1 \end{bmatrix}W=102101−21−11012−101,A=[0.1−0.10.2−0.20.30.00.40.1],B=100.5−100−0.51
The initial update matrix ΔW\Delta WΔW and the effective weight matrix WeffW_{\text{eff}}Weff are calculated as:
ΔW=BA=[0.10.20.30.4−0.1−0.2−0.2−0.10.10.20.150.15−0.2−0.4−0.3−0.3]\Delta W = BA = \begin{bmatrix} 0.1 & 0.2 & 0.3 & 0.4 \\ -0.1 & -0.2 & -0.2 & -0.1 \\ 0.1 & 0.2 & 0.15 & 0.15 \\ -0.2 & -0.4 & -0.3 & -0.3 \end{bmatrix}ΔW=BA=0.1−0.10.1−0.20.2−0.20.2−0.40.3−0.20.15−0.30.4−0.10.15−0.3
Weff=W+ΔW=[1.10.2−0.72.4−0.10.81.0−0.92.1−1.80.150.150.80.60.70.7]W_{\text{eff}} = W + \Delta W = \begin{bmatrix} 1.1 & 0.2 & -0.7 & 2.4 \\ -0.1 & 0.8 & 1.0 & -0.9 \\ 2.1 & -1.8 & 0.15 & 0.15 \\ 0.8 & 0.6 & 0.7 & 0.7 \end{bmatrix}Weff=W+ΔW=1.1−0.12.10.80.20.8−1.80.6−0.71.00.150.72.4−0.90.150.7
3.1. A Single Gradient Update Step
Now, let’s simulate one step of training. We need an input vector xxx, a target output ytruey_{\text{true}}ytrue, a loss function LLL, and a learning rate α\alphaα.
- Input: x=[1,0,0,0]x = [1, 0, 0, 0]x=[1,0,0,0]
- Target: ytrue=[1,1,1,1]y_{\text{true}} = [1, 1, 1, 1]ytrue=[1,1,1,1]
- Loss Function: L=12∑(yi−ytrue,i)2L = \frac{1}{2} \sum (y_i - y_{\text{true}, i})^2L=21∑(yi−ytrue,i)2 (Sum of Squared Errors)
- Learning Rate: α=0.1\alpha = 0.1α=0.1
-
Forward Pass. First, we compute the predicted output y=xWeffy = x W_{\text{eff}}y=xWeff. With x=[1,0,0,0]x = [1, 0, 0, 0]x=[1,0,0,0], this simply selects the first row of WeffW_{\text{eff}}Weff:
y=[1.1,0.2,−0.7,2.4]y = [1.1, 0.2, -0.7, 2.4]y=[1.1,0.2,−0.7,2.4] -
Compute Loss and Gradients. We calculate the loss and then backpropagate to find the gradients of the loss with respect to AAA and BBB.
Loss L≈2.75\text{Loss } L \approx 2.75Loss L≈2.75
Crucially, since WWW is frozen, we do not compute its gradient. The gradients are computed only for the trainable parameters:
∇AL=∂L∂A,ablaBL=∂L∂B,ablaWL=0\nabla_A L = \frac{\partial L}{\partial A}, \quad
abla_B L = \frac{\partial L}{\partial B}, \quad
abla_W L = 0∇AL=∂A∂L,ablaBL=∂B∂L,ablaWL=0
Via backpropagation, we find the numerical gradients (values are approximate):
ablaAL≈[0.10.2−1.71.40000],ablaBL≈[0.01−0.010.02−0.02−0.170.170.14−0.14]
abla_A L \approx \begin{bmatrix} 0.1 & 0.2 & -1.7 & 1.4 \\ 0 & 0 & 0 & 0 \end{bmatrix}, \quad
abla_B L \approx \begin{bmatrix} 0.01 & -0.01 \\ 0.02 & -0.02 \\ -0.17 & 0.17 \\ 0.14 & -0.14 \end{bmatrix}ablaAL≈[0.100.20−1.701.40],ablaBL≈0.010.02−0.170.14−0.01−0.020.17−0.14
- Update Parameters. We update AAA and BBB using gradient descent. WWW is not updated.
Anew=A−αablaAL,Bnew=B−αablaBL,Wnew=WA_{\text{new}} = A - \alpha abla_A L, \quad B_{\text{new}} = B - \alpha abla_B L, \quad W_{\text{new}} = WAnew=A−αablaAL,Bnew=B−αablaBL,Wnew=W
With α=0.1\alpha = 0.1α=0.1, the new matrices are:
Anew≈[0.9990.00100],Bnew≈[0.090.180.470.260.09880.19760.24440.0832−0.10−0.200.000.10−0.1919−0.3838−0.4747−0.1616]A_{\text{new}} \approx \begin{bmatrix} 0.999 & 0.001 \\ 0 & 0 \end{bmatrix}, \quad B_{\text{new}} \approx \begin{bmatrix} 0.09 & 0.18 & 0.47 & 0.26 \\ 0.0988 & 0.1976 & 0.2444 & 0.0832 \\ -0.10 & -0.20 & 0.00 & 0.10 \\ -0.1919 & -0.3838 & -0.4747 & -0.1616 \end{bmatrix}Anew≈[0.99900.0010],Bnew≈0.090.0988−0.10−0.19190.180.1976−0.20−0.38380.470.24440.00−0.47470.260.08320.10−0.1616
The original weight matrix WWW remains completely unchanged.
- New Effective Weight. Finally, we can see how the effective weight matrix has changed due to the updates to AAA and BBB only.
Weff, new=W+BnewAnewW_{\text{eff, new}} = W + B_{\text{new}} A_{\text{new}}Weff, new=W+BnewAnew
Weff, new≈[10−12011−12−2001111]+[0.090.180.470.260.09880.19760.24440.0832−0.10−0.200.000.10−0.1919−0.3838−0.4747−0.1616]×[0.9990.00100]≈[1.090.18−0.532.26−0.100.801.00−0.902.10−1.800.240.080.810.620.520.84] \begin{aligned} W_{\text{eff, new}} &\approx \begin{bmatrix} 1 & 0 & -1 & 2 \\ 0 & 1 & 1 & -1 \\ 2 & -2 & 0 & 0 \\ 1 & 1 & 1 & 1 \end{bmatrix} + \begin{bmatrix} 0.09 & 0.18 & 0.47 & 0.26 \\ 0.0988 & 0.1976 & 0.2444 & 0.0832 \\ -0.10 & -0.20 & 0.00 & 0.10 \\ -0.1919 & -0.3838 & -0.4747 & -0.1616 \end{bmatrix} \times \begin{bmatrix} 0.999 & 0.001 \\ 0 & 0 \end{bmatrix} \\ &\approx \begin{bmatrix} 1.09 & 0.18 & -0.53 & 2.26 \\ -0.10 & 0.80 & 1.00 & -0.90 \\ 2.10 & -1.80 & 0.24 & 0.08 \\ 0.81 & 0.62 & 0.52 & 0.84 \end{bmatrix} \end{aligned} Weff, new≈102101−21−11012−101+0.090.0988−0.10−0.19190.180.1976−0.20−0.38380.470.24440.00−0.47470.260.08320.10−0.1616×[0.99900.0010]≈1.09−0.102.100.810.180.80−1.800.62−0.531.000.240.522.26−0.900.080.84
After just one update, only the small matrices AAA and BBB have been modified, changing the overall behavior of the layer while keeping the massive original weight matrix WWW frozen.
4. How Training Works
- Forward: compute with Weff=W+BAW_{\text{eff}} = W + BAWeff=W+BA.
- Compute loss.
- Back-propagate gradients only into AAA and BBB.
- Update AAA and BBB; keep WWW frozen.
5. Does LoRA Add New Layers?
No. A LoRA patch lives inside an existing nn.Linear layer.
- The layer’s computation (during forward pass) is rewritten as y=(W+BA)x+by = (W + BA)x + by=(W+BA)x+b, but the call-graph still contains just the original layer.
- AAA and BBB are lightweight matrices, not brand-new modules.
- At inference you can merge them once into WWW and discard the patch: W←W+BAW \leftarrow W + BAW←W+BA.
Thus LoRA changes the parameters a layer holds, not the network topology.
6. LoRA Diagram

7. LoRA Parameter Savings Example
Assume:
- LLaMA-7B contains ≈7\approx 7≈7 billion parameters in total.
- We apply LoRA to its linear layers, which contain the vast majority of its parameters. The total number of weights in these layers is ≈6.48\approx 6.48≈6.48 billion.
- LoRA rank is fixed at r=8r = 8r=8.
For a linear layer of shape (k×d)(k \times d)(k×d) LoRA adds:
A∈Rr×d,B∈Rk×r ⟹ extra params per layer =r(k+d).A \in \mathbb{R}^{r \times d}, \quad B \in \mathbb{R}^{k \times r} \implies \text{extra params per layer } = r(k+d).A∈Rr×d,B∈Rk×r⟹extra params per layer =r(k+d).
With a typical layer size of k=d=4096k = d = 4096k=d=4096:
per layer=8(4096+4096)=8×8192=65,536.\text{per layer} = 8(4096 + 4096) = 8 \times 8192 = 65,536.per layer=8(4096+4096)=8×8192=65,536.
Assuming we patch 100 of the model’s main linear layers (a common practice):
100×65,536=6.55 million parameters.100 \times 65,536 = 6.55 \text{ million parameters}.100×65,536=6.55 million parameters.
Perspective
6.55 M6.48 B≈0.1% (of targeted layers),6.55 M7 B≈0.094% (of the entire model)\frac{6.55 \text{ M}}{6.48 \text{ B}} \approx 0.1\% \text{ (of targeted layers)}, \quad \frac{6.55 \text{ M}}{7 \text{ B}} \approx 0.094\% \text{ (of the entire model)}6.48 B6.55 M≈0.1% (of targeted layers),7 B6.55 M≈0.094% (of the entire model)
LoRA therefore tunes about one-tenth of one percent of the weights it touches and below one-tenth of one percent of the full network—a truly dramatic savings in both memory and compute.
8. What Does Rank Mean in LoRA?
Think of the rank rrr as a dial that controls how much freedom the LoRA patch has.
Linear-algebra view. The rank of a matrix is the count of independent rows or columns, i.e. how many directions it can cover in space.
LoRA view. We replace a full (large) update matrix ΔW∈Rk×d\Delta W \in \mathbb{R}^{k \times d}ΔW∈Rk×d with a product of two skinny ones:
ΔW=BA,B∈Rk×r,A∈Rr×d.\Delta W = BA, \quad B \in \mathbb{R}^{k \times r}, \quad A \in \mathbb{R}^{r \times d}.ΔW=BA,B∈Rk×r,A∈Rr×d.
The middle dimension rrr is the bottleneck size—our dial.
- Small r→r \rightarrowr→ very few new parameters, runs fast, but can only make coarse adjustments.
- Large r→r \rightarrowr→ more parameters and compute, but can learn subtler changes.
In practice people pick:
r∈{4,8,16,32}r \in \{4, 8, 16, 32\}r∈{4,8,16,32}
choosing a higher value for bigger models or harder tasks.
9. Summary
- LoRA injects low-rank matrices, not new layers.
- Only the small patches (A,BA, BA,B) are trained; WWW stays frozen.
- Widely used on
nn.Linearlayers in transformers to enable rapid, memory-efficient adaptation. - Used for fine-tuning.
更多推荐
所有评论(0)