# Destilación de consistencia latente

Los [Latent Consistency Models (LCMs)](https://hf.co/papers/2310.04378) son capaces de generar imágenes de alta calidad en solo unos pocos pasos, lo que representa un gran avance, ya que muchos pipelines requieren al menos 25+ pasos. Los LCMs se producen aplicando el método de destilación de consistencia latente a cualquier modelo de Stable Diffusion. Este método funciona aplicando *one-stage guided distillation* al espacio latente e incorporando un método de *skipping-step* para omitir de forma consistente los timesteps y acelerar el proceso de destilación (consulte las secciones 4.1, 4.2 y 4.3 del artículo para más detalles).

Si estás entrenando en una GPU con vRAM limitada, intenta habilitar `gradient_checkpointing`, `gradient_accumulation_steps` y `mixed_precision` para reducir el uso de memoria y acelerar el entrenamiento. Puedes reducir aún más el uso de memoria habilitando la atención eficiente en memoria con [xFormers](../optimization/attention_backends) y el optimizador de 8 bits de [bitsandbytes](https://github.com/TimDettmers/bitsandbytes).

Esta guía explorará el script [train_lcm_distill_sd_wds.py](https://github.com/huggingface/diffusers/blob/main/examples/consistency_distillation/train_lcm_distill_sd_wds.py) para que se familiarice más con él y para que pueda adaptarlo a su caso de uso.

Antes de ejecutar el script, asegúrate de instalar la biblioteca desde el código fuente:

```bash
git clone https://github.com/huggingface/diffusers
cd diffusers
pip install .
```

Luego, navegue a la carpeta de ejemplo que contiene el script de entrenamiento e instale las dependencias requeridas para el script que está utilizando:

```bash
cd examples/consistency_distillation
pip install -r requirements.txt
```

> [!TIP]
> 🤗 Accelerate es una biblioteca para ayudarte a entrenar en varias GPUs/TPUs o con precisión mixta. Configura automáticamente tu configuración de entrenamiento en función de tu hardware y entorno. Echa un vistazo al [Quick tour](https://huggingface.co/docs/accelerate/quicktour) de 🤗 Accelerate para saber más.

Inicializa un entorno de 🤗 Accelerate (prueba a habilitar `torch.compile` para acelerar significativamente el entrenamiento):

```bash
accelerate config
```

Para configurar un entorno predeterminado de 🤗 Accelerate sin elegir ninguna configuración:

```bash
accelerate config default
```

O si su entorno no admite una shell interactiva, como un notebook, puede usar:

```py
from accelerate.utils import write_basic_config

write_basic_config()
```

Por último, si deseas entrenar un modelo con tu propio conjunto de datos, consulta la guía [Crear un conjunto de datos para el entrenamiento](create_dataset) para aprender a crear un conjunto de datos que funcione con el script de entrenamiento.

## Parámetros del script

> [!TIP]
> Las siguientes secciones resaltan las partes del script de entrenamiento que son importantes para entender cómo modificarlo, pero no abordan todos los aspectos del script en detalle. Si te interesa aprender más, no dudes en leer el [script](https://github.com/huggingface/diffusers/blob/main/examples/consistency_distillation/train_lcm_distill_sd_wds.py) e informarnos si tienes alguna pregunta o inquietud.

El script de entrenamiento ofrece muchos parámetros para ayudarte a personalizar tu ejecución de entrenamiento. Todos los parámetros y sus descripciones se encuentran en la función [`parse_args()`](https://github.com/huggingface/diffusers/blob/3b37488fa3280aed6a95de044d7a42ffdcb565ef/examples/consistency_distillation/train_lcm_distill_sd_wds.py#L419). Esta función proporciona valores predeterminados para cada parámetro, como el tamaño del lote de entrenamiento y la tasa de aprendizaje, pero también puedes establecer tus propios valores en el comando de entrenamiento si lo deseas.

Por ejemplo, para acelerar el entrenamiento con precisión mixta usando el formato fp16, añade el parámetro `--mixed_precision` al comando de entrenamiento:

```bash
accelerate launch train_lcm_distill_sd_wds.py \
  --mixed_precision="fp16"
```

La mayoría de los parámetros son idénticos a los de la guía de entrenamiento [Text-to-image](text2image#script-parameters), por lo que en esta guía te centrarás en los parámetros relevantes para la destilación de consistencia latente.

- `--pretrained_teacher_model`: la ruta a un modelo de difusión latente preentrenado para usar como modelo maestro
- `--pretrained_vae_model_name_or_path`: ruta a un VAE preentrenado; se sabe que el VAE de SDXL sufre de inestabilidad numérica, por lo que este parámetro le permite especificar un VAE alternativo (como este [VAE](https://huggingface.co/madebyollin/sdxl-vae-fp16-fix)) de madebyollin que funciona en fp16)
- `--w_min` y `--w_max`: los valores mínimo y máximo de la escala de guía para el muestreo de la escala de guía
- `--num_ddim_timesteps`: el número de pasos de tiempo para el muestreo DDIM
- `--loss_type`: el tipo de pérdida (L2 o Huber) que se calculará para la destilación de consistencia latente; la pérdida de Huber se prefiere generalmente porque es más robusta ante valores atípicos
- `--huber_c`: el parámetro de la pérdida de Huber

## Script de entrenamiento

El script de entrenamiento comienza creando una clase de conjunto de datos, [`Text2ImageDataset`](https://github.com/huggingface/diffusers/blob/3b37488fa3280aed6a95de044d7a42ffdcb565ef/examples/consistency_distillation/train_lcm_distill_sd_wds.py#L141), para preprocesar las imágenes y crear un conjunto de datos de entrenamiento.

```py
def transform(example):
    image = example["image"]
    image = TF.resize(image, resolution, interpolation=transforms.InterpolationMode.BILINEAR)

    c_top, c_left, _, _ = transforms.RandomCrop.get_params(image, output_size=(resolution, resolution))
    image = TF.crop(image, c_top, c_left, resolution, resolution)
    image = TF.to_tensor(image)
    image = TF.normalize(image, [0.5], [0.5])

    example["image"] = image
    return example
```

Para mejorar el rendimiento en la lectura y escritura de grandes conjuntos de datos almacenados en la nube, este script utiliza el formato [WebDataset](https://github.com/webdataset/webdataset) para crear un pipeline de preprocesamiento que aplica transformaciones y crea un dataset y un dataloader para el entrenamiento. Las imágenes se procesan y se envían al bucle de entrenamiento sin necesidad de descargar primero el conjunto de datos completo.

```py
processing_pipeline = [
    wds.decode("pil", handler=wds.ignore_and_continue),
    wds.rename(image="jpg;png;jpeg;webp", text="text;txt;caption", handler=wds.warn_and_continue),
    wds.map(filter_keys({"image", "text"})),
    wds.map(transform),
    wds.to_tuple("image", "text"),
]
```

En la función [`main()`](https://github.com/huggingface/diffusers/blob/3b37488fa3280aed6a95de044d7a42ffdcb565ef/examples/consistency_distillation/train_lcm_distill_sd_wds.py#L768), se cargan todos los componentes necesarios, como el scheduler de ruido, los tokenizers, los codificadores de texto y el VAE. Aquí también se carga el UNet maestro y a continuación se puede crear un UNet estudiante a partir del UNet maestro. El UNet estudiante se actualiza mediante el optimizer durante el entrenamiento.

```py
teacher_unet = UNet2DConditionModel.from_pretrained(
    args.pretrained_teacher_model, subfolder="unet", revision=args.teacher_revision
)

unet = UNet2DConditionModel(**teacher_unet.config)
unet.load_state_dict(teacher_unet.state_dict(), strict=False)
unet.train()
```

Ahora puedes crear el [optimizer](https://github.com/huggingface/diffusers/blob/3b37488fa3280aed6a95de044d7a42ffdcb565ef/examples/consistency_distillation/train_lcm_distill_sd_wds.py#L979) para actualizar los parámetros de UNet:

```py
optimizer = optimizer_class(
    unet.parameters(),
    lr=args.learning_rate,
    betas=(args.adam_beta1, args.adam_beta2),
    weight_decay=args.adam_weight_decay,
    eps=args.adam_epsilon,
)
```

Crea el [dataset](https://github.com/huggingface/diffusers/blob/3b37488fa3280aed6a95de044d7a42ffdcb565ef/examples/consistency_distillation/train_lcm_distill_sd_wds.py#L994):

```py
dataset = Text2ImageDataset(
    train_shards_path_or_url=args.train_shards_path_or_url,
    num_train_examples=args.max_train_samples,
    per_gpu_batch_size=args.train_batch_size,
    global_batch_size=args.train_batch_size * accelerator.num_processes,
    num_workers=args.dataloader_num_workers,
    resolution=args.resolution,
    shuffle_buffer_size=1000,
    pin_memory=True,
    persistent_workers=True,
)
train_dataloader = dataset.train_dataloader
```

A continuación, está listo para configurar el [bucle de entrenamiento](https://github.com/huggingface/diffusers/blob/3b37488fa3280aed6a95de044d7a42ffdcb565ef/examples/consistency_distillation/train_lcm_distill_sd_wds.py#L1049) e implementar el método de destilación de consistencia latente (consulte el Algoritmo 1 del artículo para más detalles). Esta sección del script se encarga de añadir ruido a los latentes, muestrear y crear un embebido de escala de guía, y predecir la imagen original a partir del ruido.

```py
pred_x_0 = predicted_origin(
    noise_pred,
    start_timesteps,
    noisy_model_input,
    noise_scheduler.config.prediction_type,
    alpha_schedule,
    sigma_schedule,
)

model_pred = c_skip_start * noisy_model_input + c_out_start * pred_x_0
```

A continuación, obtiene las [predicciones del modelo maestro](https://github.com/huggingface/diffusers/blob/3b37488fa3280aed6a95de044d7a42ffdcb565ef/examples/consistency_distillation/train_lcm_distill_sd_wds.py#L1172) y las [predicciones del LCM](https://github.com/huggingface/diffusers/blob/3b37488fa3280aed6a95de044d7a42ffdcb565ef/examples/consistency_distillation/train_lcm_distill_sd_wds.py#L1209), calcula la pérdida y luego la retropropaga al LCM.

```py
if args.loss_type == "l2":
    loss = F.mse_loss(model_pred.float(), target.float(), reduction="mean")
elif args.loss_type == "huber":
    loss = torch.mean(
        torch.sqrt((model_pred.float() - target.float()) ** 2 + args.huber_c**2) - args.huber_c
    )
```

Si quieres saber más sobre cómo funciona el bucle de entrenamiento, consulta el [tutorial sobre el entendimiento de pipelines, modelos y programadores](../using-diffusers/write_own_pipeline), que desglosa el patrón básico del proceso de desruido.

## Ejecutar el script

Ahora estás listo para lanzar el script de entrenamiento y comenzar la destilación.

Para esta guía, utilizará `--train_shards_path_or_url` para especificar la ruta al conjunto de datos [Conceptual Captions 12M](https://github.com/google-research-datasets/conceptual-12m) almacenado en el Hub [aquí](https://huggingface.co/datasets/laion/conceptual-captions-12m-webdataset). Establezca la variable de entorno `MODEL_DIR` con el nombre del modelo maestro y `OUTPUT_DIR` con la ubicación donde desea guardar el modelo.

```bash
export MODEL_DIR="stable-diffusion-v1-5/stable-diffusion-v1-5"
export OUTPUT_DIR="path/to/saved/model"

accelerate launch train_lcm_distill_sd_wds.py \
    --pretrained_teacher_model=$MODEL_DIR \
    --output_dir=$OUTPUT_DIR \
    --mixed_precision=fp16 \
    --resolution=512 \
    --learning_rate=1e-6 --loss_type="huber" --ema_decay=0.95 --adam_weight_decay=0.0 \
    --max_train_steps=1000 \
    --max_train_samples=4000000 \
    --dataloader_num_workers=8 \
    --train_shards_path_or_url="pipe:curl -L -s https://huggingface.co/datasets/laion/conceptual-captions-12m-webdataset/resolve/main/data/{00000..01099}.tar?download=true" \
    --validation_steps=200 \
    --checkpointing_steps=200 --checkpoints_total_limit=10 \
    --train_batch_size=12 \
    --gradient_checkpointing --enable_xformers_memory_efficient_attention \
    --gradient_accumulation_steps=1 \
    --use_8bit_adam \
    --resume_from_checkpoint=latest \
    --report_to=wandb \
    --seed=453645634 \
    --push_to_hub
```

Una vez completado el entrenamiento, puedes usar tu nuevo LCM para la inferencia.

```py
from diffusers import UNet2DConditionModel, DiffusionPipeline, LCMScheduler
import torch

unet = UNet2DConditionModel.from_pretrained("your-username/your-model", dtype=torch.float16, variant="fp16")
pipeline = DiffusionPipeline.from_pretrained("stable-diffusion-v1-5/stable-diffusion-v1-5", unet=unet, dtype=torch.float16, variant="fp16")

pipeline.scheduler = LCMScheduler.from_config(pipe.scheduler.config)
pipeline.to("cuda")  # or "mps", "xpu", "cpu"

prompt = "sushi rolls in the form of panda heads, sushi platter"

image = pipeline(prompt, num_inference_steps=4, guidance_scale=1.0).images[0]
```

## LoRA

LoRA es una técnica de entrenamiento para reducir significativamente el número de parámetros entrenables. Como resultado, el entrenamiento es más rápido y es más fácil almacenar los pesos resultantes porque son mucho más pequeños (~100MB). Utilice el script [train_lcm_distill_lora_sd_wds.py](https://github.com/huggingface/diffusers/blob/main/examples/consistency_distillation/train_lcm_distill_lora_sd_wds.py) o [train_lcm_distill_lora_sdxl.wds.py](https://github.com/huggingface/diffusers/blob/main/examples/consistency_distillation/train_lcm_distill_lora_sdxl_wds.py) para entrenar con LoRA.

El script de entrenamiento LoRA se describe con más detalle en la guía de [entrenamiento LoRA](lora).

## Stable Diffusion XL

Stable Diffusion XL (SDXL) es un potente modelo de texto a imagen que genera imágenes de alta resolución y añade un segundo text-encoder a su arquitectura. Utilice el script [train_lcm_distill_sdxl_wds.py](https://github.com/huggingface/diffusers/blob/main/examples/consistency_distillation/train_lcm_distill_sdxl_wds.py) para entrenar un modelo SDXL con LoRA.

El script de entrenamiento de SDXL se describe con más detalle en la guía de [entrenamiento de SDXL](sdxl).

## Próximos pasos

¡Felicidades por destilar un modelo LCM! Para aprender más sobre LCM, lo siguiente puede ser útil:

- Aprende a usar [LCMs para inferencia](../api/pipelines/latent_consistency_models) en texto a imagen, imagen a imagen y con puntos de control de LoRA.
- Lee el artículo de blog [SDXL en 4 pasos con Latent Consistency LoRAs](https://huggingface.co/blog/lcm_lora) para aprender más sobre los SDXL LCM-LoRA para inferencia ultrarrápida, comparaciones de calidad, benchmarks y más.

