Lesson 26 LoRA & QLoRA
Theme:

Homework

Complete these tasks before Lesson 27. You will need GPU access for Tasks 1 and 2. Task 3 can be completed without a GPU.

Task 1: Rank Ablation Study

Goal: Develop intuition for how LoRA rank affects fine-tuning quality and find the sweet spot for a given dataset.

Instructions

Using the same QLoRA setup from the lab (TinyLlama + dolly-15k subset), train four separate adapters with different rank values:

RunRank (r)AlphaTarget Modules
A48q_proj, v_proj
B816q_proj, v_proj
C1632q_proj, v_proj
D3264q_proj, v_proj

Keep all other hyperparameters identical (learning rate, batch size, epochs, dataset). For each run, record:

  1. Final training loss
  2. Trainable parameter count and percentage
  3. Peak GPU memory usage (from torch.cuda.max_memory_allocated())
  4. Total training time

After training all four, run the same 5 test prompts through each adapter and qualitatively rate the outputs.

Deliverable

A comparison table with all four runs and a 2–3 sentence conclusion about which rank provided the best trade-off for this dataset and task.

Self-check

Task 2: Memory Profiling — LoRA vs QLoRA

Goal: Quantify the exact memory savings of QLoRA compared to standard LoRA, and understand where the savings come from.

Instructions

Write a script that loads the same model in three configurations and reports memory usage for each:

  1. fp16 + LoRA: Load model in fp16, apply LoRA (r=16, q_proj + v_proj)
  2. 4-bit + LoRA (QLoRA): Load model in 4-bit NF4, apply same LoRA config
  3. 4-bit + LoRA + double quant: Same as (2) but with bnb_4bit_use_double_quant=True

For each configuration, record:

Tip: Isolate Measurements

Run each configuration in a separate Python process (or restart the Colab runtime between runs) to get accurate memory measurements. Residual memory from previous model loads will skew the results.

Deliverable

A markdown table or printed comparison showing memory usage across all three configurations, plus a short paragraph explaining where the memory savings come from in each step.

Self-check

Task 3: Target Module Analysis

Goal: Understand which layers in a transformer are most impactful for LoRA adaptation.

Instructions

This task combines code exploration with written analysis. No GPU training is required — you will inspect the model architecture and reason about layer selection.

  1. Load any Llama-family model (even in CPU mode) and print all named modules:
    for name, module in model.named_modules():
        if isinstance(module, torch.nn.Linear):
            print(f"{name}: {module.in_features} x {module.out_features}")
  2. Categorize all linear layers into groups: attention projections (q, k, v, o), MLP layers (gate, up, down), and other (lm_head, embeddings).
  3. For each group, calculate:
    • Total parameters in that group
    • Percentage of total model parameters
    • LoRA trainable params if you applied r=16 to that group
  4. Write a ~200-word analysis explaining:
    • Why attention projections are the default LoRA target
    • When adding MLP layers would be worthwhile
    • Why lm_head is typically not adapted with LoRA

Deliverable

A table of layer groups with parameter counts, plus a 200-word written analysis.

Self-check

Reference Solution

lab_answer.py

Submission

There is no formal submission for this course. These tasks are for your own development. However:

Next lesson: Lesson 27 — API Fine-Tuning — fine-tuning through provider APIs without managing GPU infrastructure.