ArtificialGuyBR

Home / Blog / Training LoRAs

How LoRAs Work and How to Use Them in Stable Diffusion

Understand LoRA mechanics: weight changes at inference, strength controls, stacking multiple adapters, matching base models, and proper installation.

4 sources cited Training LoRAs

How LoRAs Work and How to Use Them in Stable Diffusion

A LoRA (Low-Rank Adaptation) is a small patch that modifies Stable Diffusion models without replacing them. Instead of downloading an entirely new checkpoint, you load a LoRA file that injects trainable adjustments into specific layers. This article explains the math behind LoRAs, how to control their strength, and how to match them to your base model.

For hands-on guidance on preparing your first dataset and training, see our train your first LoRA free tutorial. If you're building a style library, our LoRA library management guide covers organization and versioning. For SDXL-specific tips, see SDXL photoreal LoRA tips.

TL;DR


How LoRA Works at Inference Time

The Mathematical Foundation

When you load a LoRA, you are not replacing base model weights. You are adding small, trainable adjustments to them.

The update follows a simple formula:

$$h = W_0 x + BAx$$

Each term:

The original LoRA paper found that model weights live on a low-intrinsic-dimension manifold, meaning weight updates can be represented with far fewer parameters than the original weights.

"We hypothesize that the change in weights during model adaptation also has a low 'intrinsic rank' during adaptation." — https://arxiv.org/abs/2106.09685

Why This Matters for Stable Diffusion

For Stable Diffusion's UNet attention layers, standard weight matrices are full-rank (e.g., 768×768 for SDXL). Instead of updating 768² parameters, LoRA updates only r×768 + 768×r = 1536r parameters.

With r = 8, that is 12,288 trainable parameters versus 589,824 full-rank weights—a 48× reduction.

"At inference: zero additional latency versus a fully fine-tuned model by construction." — https://arxiv.org/abs/2106.09685

Most UIs permanently merge the LoRA into the base model during loading. The $W_0 + BA$ update is computed once and stored as new weights. This eliminates runtime overhead—merged weights are normal model parameters with no additional memory cost.


Strength Controls: Alpha versus Weight

Confusing "alpha" and "weight" is the most common mistake when using LoRAs. They operate at different levels:

Training-time alpha (α):

Inference-time weight (the number in <lora:model:1>):

The original paper establishes scaling as (α/r)·BA. Different implementations handle this differently—the cloneofsimo repository suggests the inference weight replaces alpha scaling entirely, while other implementations multiply both.


How Multiple LoRAs Stack

When you apply multiple LoRAs, their effects sum:

$$h = W_0 x + \frac{\alpha_1}{r_1} B_1 A_1 x + \frac{\alpha_2}{r_2} B_2 A_2 x$$

If two LoRAs both target the same attention layer (e.g., both modify Wq), their updates add together.

Chaining LoRAs

ComfyUI: Chain LoraLoader nodes sequentially:

LoraLoader node 1 → LoraLoader node 2 → [...]

Each node adds its own low-rank matrices to the base weights. Reference: https://comfyanonymous.github.io/ComfyUI_examples/lora/

Diffusers: Use set_adapters() for weighted control:

pipeline.set_adapters(["style1", "style2"], adapter_weights=[0.7, 0.8])

Advanced Merging: PEFT's add_weighted_adapter() supports TIES and DARE methods for offline combination.

"LoRA is orthogonal to many other parameter-efficient methods and can be combined with many of them, such as prefix-tuning." — https://arxiv.org/abs/2106.09685

Matching LoRAs to Base Models

LoRA matrices are shaped to match the architecture dimensions of the base model they were trained on. An SD1.5 LoRA has B/A matrices sized for SD1.5's UNet attention dimensions; an SDXL LoRA has larger dimensions.

Architecture mismatch examples:

"LoRAs also need to be used with another model." — https://huggingface.co/docs/diffusers/main/en/using-diffusers/loading_adapters

Different base models also have varying numbers of attention layers and may target different layer types (self-attention versus cross-attention).


Where to Install LoRA Files

UIPath
ComfyUImodels/loras/
AUTOMATIC1111 / Forgemodels/Lora/
Diffusers (code)Any path; loaded via load_lora_weights("path/to/loras")
kohya-ss trainingSpecified by --output_dir

Reference: https://comfyanonymous.github.io/ComfyUI_examples/lora/


Common Errors and Fixes

ErrorLikely CauseFix
LoRA has no visible effectWeight set to 0 or LoRA not activated in UICheck <lora:name:1> syntax; ensure weight > 0
Architecture mismatch errorSDXL LoRA loaded into SD1.5 model (or vice versa)Verify base model matches LoRA training architecture
Second LoRA overrides firstStacking not enabled in UIChain LoraLoader nodes (ComfyUI) or use set_adapters() (Diffusers)
Corrupted file errorIncomplete download or wrong formatRe-download .safetensors file from a trusted source

Frequently Asked Questions

How much VRAM does a LoRA add? The LoRA matrices themselves are small (1–6 MB for low-rank, up to ~200 MB for higher ranks). The base model loads normally. After merging, there is no additional VRAM cost.

Can I apply LoRAs to non-attention layers? In principle, LoRA can target any weight matrix. In practice, most SD LoRAs target attention layers only (Wq, Wk, Wv, Wo). kohya-ss supports Conv2d layers via LoRA-C3Lier (reference: https://github.com/kohya-ss/sd-scripts/blob/main/docs/train_network.md).

What is the optimal rank for LoRAs? The original paper tested ranks 4–8 for language models. For SD, ranks 8–128 are common; lower ranks (4–16) trade quality for speed and VRAM efficiency.

How many LoRAs can I stack? No hard limit. Each LoRA adds small matrices to the same layers. Diminishing returns appear as more LoRAs modify the same weight matrices, but practical stacking of several LoRAs is common.

Do I need special software to use LoRAs? Any UI that supports LoRAs works—AUTOMATIC1111, ComfyUI, Forge, and Diffusers all handle them natively.

How do I know if a LoRA will work with my base model? Check the model card or description. Most list compatible base models (e.g., "SDXL v1.0 base", "SD 1.5"). When in doubt, inspect the .safetensors file dimensions.


Sources

ClaimSource
LoRA freezes weights and injects trainable rank decomposition matriceshttps://arxiv.org/abs/2106.09685
Mathematical formulation h = W₀x + BAxhttps://arxiv.org/abs/2106.09685
Zero inference latency when mergedhttps://arxiv.org/abs/2106.09685
LoRA architecture compatibilityhttps://civitai.com/articles/2099
LoRA installation pathshttps://civitai.com/articles/2099
Alpha vs weight distinctionhttps://github.com/kohya-ss/sd-scripts/blob/main/docs/train_network.md
Rank-Stabilized LoRAhttps://huggingface.co/docs/peft/main/en/conceptual_guides/lora
Weight initialization strategyhttps://arxiv.org/abs/2106.09685
LoRA scaling factor α/rhttps://arxiv.org/abs/2106.09685
LoRA orthogonality to other methodshttps://arxiv.org/abs/2106.09685
PEFT LoRA configuration parametershttps://huggingface.co/docs/peft/main/en/conceptual_guides/lora
ComfyUI loading with LoraLoaderhttps://comfyanonymous.github.io/ComfyUI_examples/lora/
Diffusers load_lora_weightshttps://huggingface.co/docs/diffusers/main/en/using-diffusers/loading_adapters
Diffusers set_adapters chaininghttps://huggingface.co/docs/diffusers/main/en/using-diffusers/merge_loras
Kohya-ss LoRA types and argumentshttps://github.com/kohya-ss/sd-scripts/blob/main/docs/train_network.md
LoRA checkpoint file formathttps://github.com/kohya-ss/sd-scripts/blob/main/docs/train_network.md
Cloneofsimo LoRA merging formulahttps://github.com/cloneofsimo/lora