Phase 08: Generative AI

ControlNet, LoRA y acondicionamiento

El texto solo es una señal de control torpe. ControlNet le permite clonar un modelo de difusión preentrenado y dirigirlo con un mapa de profundidad, esqueleto de pose, escrutinio o imagen de borde. LoRA le permite ajustar un modelo de parámetro 2B mediante el entrenamiento de 10 millones de parámetros. Juntos convirtieron a la difusión estable de un juguete en la tubería de imágenes 2026 que se envía a cada agencia.

Type: Build

Languages: Python

Prerequisites: Phase 8 · 07 (Latent Diffusion), Phase 10 (LLMs from Scratch — for LoRA foundation)

Time: ~75 minutes

El problema

Un mensaje como "una mujer con un vestido rojo caminando con un perro en una calle concurrida" no le da al modelo información sobre dónde está el perro, qué postura está la mujer en, o la perspectiva de la calle.

El entrenamiento de un nuevo modelo condicional desde cero para cada señal (posición, profundidad, ingenioso, segmentación) es prohibitivo.

También quieres enseñar al modelo nuevos conceptos (tu rostro, tu producto, tu estilo) sin volver a entrenar al modelo completo. Quieres un delta 100 veces más pequeño.

ControlNet + LoRA + texto = el kit de herramientas del profesional 2026 La mayoría de las tuberías de imágenes de producción tienen 2-5 LoRA, 1-3 ControlNets y un adaptador IP encima de una base SDXL / SD3 / Flux.

El concepto

!ControlNet clones the encoder; LoRA adds low-rank deltas

ControlNet (Zhang et al., 2023)

Clon la mitad de codificador de la U-Net. Congela el original. Entren el clon para aceptar una entrada de condicionamiento adicional (borda, profundidad, pose). Conecte al clon de nuevo al decodificador de la mitad del original con convolución cero conexiones saltadas (1×1 convs inicializados a cero comienzan como no-op, aprende un delta).

SD U-Net decoder:   ... ← orig_enc_features + zero_conv(controlnet_enc(condition))

El tren en 1M (prompto, condición, imagen) se triplica con la pérdida de difusión estándar.

ControlNets por modalidad se envían como modelos secundarios pequeños (~ 360 M para SDXL, ~ 70 M para SD 1.5).

features += weight_a * control_a(depth) + weight_b * control_b(pose)

Los Estados miembros pueden adoptar medidas de seguridad en el marco de la aplicación de la presente Directiva.

Para cualquier capa lineal W ∈ R^{d×d}en el modelo, congelación Wy añadir un delta de bajo rango:

W' = W + ΔW,  ΔW = B @ A,  A ∈ R^{r×d},  B ∈ R^{d×r}

conr << d.Rango 4-16 es estándar para la atención, rango 64-128 para las tonas finas pesadas.2 · d · ren lugar ded². para la atención de SDXL con d=640¿ Qué ?r=16Por ejemplo, el modelo de la base de 5GB es de 20-200 MB.

En la inferencia se puede escalar la LoRA: W' = W + α · B @ A- ¿ Qué ?α = 0.5-1.5Los LRA múltiples se apilan de forma aditiva (con la advertencia habitual de que interactúan de manera no lineal).

Adaptador IP (Ye et al., 2023)

Un pequeño adaptador que acepta una imagen como condicionamiento (junto con texto). Utiliza el codificador de imagen CLIP para producir tokens de imagen, inyectándolos en atención cruzada junto con tokens de texto. ~ 20 MB por modelo base. Permite "generar una imagen en el estilo de esta referencia" sin un LoRA.

Matriz de composibilidad

ToolWhat it controlsSizeWhen to use
ControlNetSpatial structure (pose, depth, edges)70-360MBExact layout, composition
LoRAStyle, subject, concept20-200MBPersonalization, style
IP-AdapterStyle or subject from reference image20MBNo text can describe the look
Textual InversionSingle concept as a new token10KBLegacy, mostly replaced by LoRA
DreamBoothFull fine-tune on a subject2-5GBStrong identity, high compute
T2I-AdapterLighter ControlNet alternative70MBEdge devices, inference budget

ControlNet es espacial, LoRA es semántico, usa ambas cosas.

Construye el mismo

code/main.pysimula los dos mecanismos en 1-D:

  1. LoRA.Una capa lineal preentrenada .W- Congelarlo. Entrenar a un bajo rango.B @ AEs así .W + BAcoincide con una capa lineal objetivo. Muestre quer = 1es suficiente para aprender una corrección de rango 1 perfectamente.
  1. ControlNet-lite.Un predictor de "base congelada" y una "red lateral" que lee una señal adicional. La salida de la red lateral está bloqueada por un escalar aprendizaje inicializado a cero (nuestra versión de cero-conv). Entren y vigila la rampa de la puerta hacia arriba.

Paso 1: Matemáticas de la LORA

pythondef lora(W, A, B, x, alpha=1.0):
    # W is frozen; A, B are the trainable low-rank factors.
    return [W[i][j] * x[j] for i, j in ...] + alpha * (B @ (A @ x))

Paso 2: red lateral de inicio cero

pythonside_out = control_net(x, condition)
gated = gate * side_out  # gate initialized to 0
h = base(x) + gated

En el paso 0 la salida es idéntica a la base.gatelentamente, sin una deriva catastrófica.

Las trampas

  • Over-scaling LoRAs. α = 2o α = 3es un hack común "hacerlo más fuerte" que produce resultados demasiado estilizados / rotos.α ≤ 1.5¿ Qué ?
  • ControlNet weight conflict.Usar una Pose ControlNet con peso 1.0 y una Depth ControlNet con peso 1.0 generalmente se sobrepone.
  • LoRA on the wrong base.Los SDXL LoRA no se operan en silencio en SD 1.5 porque las dimensiones de atención no coinciden.
  • Textual Inversion drift.Los tokens entrenados en un puesto de control se desplazan mal en otro.
  • LoRA weight-merging and storage.Puedes hornear un LoRA en los pesos del modelo base para inferir más rápido (sin adición de tiempo de ejecución), pero pierdes la capacidad de escalar αMantenga ambas versiones.

Usalo

Goal2026 pipeline
Reproduce a brand's art styleLoRA trained on ~30 curated images at rank 32
Put my face in a generated imageDreamBooth or LoRA + IP-Adapter-FaceID
Specific pose + promptControlNet-Openpose + SDXL + text
Depth-aware compositionControlNet-Depth + SD3
Reference + promptIP-Adapter + text
Exact layoutControlNet-Scribble or ControlNet-Canny
Background replaceControlNet-Seg + Inpainting (Lesson 09)
Fast 1-step styleLCM-LoRA on SDXL-Turbo

Envío

Salva .outputs/skill-sd-toolkit-composer.md. La habilidad toma una tarea (activos de entrada: instantáneo, imagen de referencia opcional, pose opcional, profundidad opcional, escríbalo opcional) y saca la pila de herramientas, pesos y un protocolo de semilla reproducible.

Los ejercicios

  1. Easy.En elcode/main.py, varían el rango de la LoRA r¿En qué rango el LoRA coincide exactamente con un delta objetivo de rango 2?
  2. Medium.Entrenar dos LoRAs separadas en dos transformaciones de objetivo. cargarlos juntos y mostrar su interacción aditiva. ¿Cuándo la interacción rompe la linealidad?
  3. Hard.Utilice difusores para apilar: SDXL-base + Canny-ControlNet (peso 0.8) + un estilo LoRA (α 0.8) + IP-Adaptador (peso 0.6).

Términos clave

TermWhat people sayWhat it actually means
ControlNet"Spatial control"Cloned encoder + zero-conv skips; reads a conditioning image.
Zero convolution"Starts as identity"1×1 conv initialized to zero; ControlNet starts as no-op.
LoRA"Low-rank adapter"W + B @ A, r << d; 100x fewer params than a full fine-tune.
rank r"The knob"LoRA compression; 4-16 typical, 64+ for heavy personalization.
α"LoRA strength"Runtime scaling of the LoRA delta.
IP-Adapter"Reference image"Small image-conditioning adapter via CLIP-image tokens.
DreamBooth"Full subject fine-tune"Train the full model on ~30 images of a subject.
Textual Inversion"New token"Learn a new word embedding only; legacy, mostly replaced.

Nota de producción: intercambios de la LRA, carriles de ControlNet, servicio para varios inquilinos

Un SaaS de texto a imagen real sirve a cientos de LoRA y una docena de ControlNets en el mismo punto de control base. El problema de servicio se parece mucho a la LLM multi-tenancy (la literatura de producción cubre el caso de LLM bajo lotes continuos y LoRAX / S-LoRA):

  • Hot-swap LoRAs, do not merge.FusiónW' = W + α·B·Aen la base da ~ 3-5% más rápido por paso de inferencia pero se congela αMantenga los LRA calientes en VRAM como deltas de rango; los difusores exponenpipe.load_lora_weights()¿ Qué es eso ?pipe.set_adapters([...], adapter_weights=[...])El costo de cambio es el 2 · d · r · num_layersPeso en escala de MB, subsegundo.
  • ControlNet as a second attention lane.El codificador clonado funciona en paralelo con la base. Dos ControlNets con peso 1.0 cada uno = dos pases adicionales hacia adelante por paso, no un pasado fusionado. El tamaño del batch se reduce cuadráticamente. Presupuesto para ~ 1.5 × costo de paso por ControlNet activo.
  • Quantized LoRAs too.Si cuantificó la base (ver Lección 07, Flux en 8GB), el delta LoRA también cuantifica limpiamente a 8 bits o 4 bits.

Flux-specific: la notebook de Niels Flux-on-8GB cuantifica la base a 4 bits; apilar un estilo LoRA (pipe.load_lora_weights("user/style-lora")) en esa base cuantificada en weight_name="pytorch_lora_weights.safetensors"Esta es la receta que la mayoría de las agencias SaaS envían en 2026.

Leer más

This free lesson is part of the AI Engineering from Scratch curriculum. Read the full explanation, run the lesson code, and verify the result in the interactive reader or from the repository source.

Browse the complete course catalog or open this lesson on GitHub.