Why full fine-tuning hurts
Fine-tuning every weight of a large model means storing a gradient and an optimizer state for each one — that's the line item that blows past a single GPU's memory long before the model itself does. LoRA (Low-Rank Adaptation) sidesteps it with a clever bet: freeze the original weights entirely, and learn a pair of small low-rank matrices that get added alongside them. You're training a few hundred thousand parameters instead of hundreds of millions, but the model behaves as if you'd tuned the whole thing.
One line, two big wins
In KerasHub it's backbone.enable_lora(rank=r) — then you call fit() exactly as before and only the adapters update (Code section). The rank is the dial: higher rank means more capacity to adapt but more parameters to train; 4–16 covers most cases. Two payoffs fall out for free. First, memory: trainable params drop by orders of magnitude, so a model that needed a cluster now fits on one card. Second, storage: you save just the tiny adapter weights, not a full model copy — so ten fine-tunes of the same base cost ten small files, not ten full checkpoints.
QLoRA: stack it with quantization
QLoRA goes one step further — first quantize() the frozen backbone to int8 (or int4) to shrink the resident model, then add LoRA adapters on top. The base is tiny and frozen, the adapters are tiny and trainable, and quality stays close to full fine-tuning. This is the combination that put 7B-class fine-tuning on consumer hardware.