Buckets:
| # Custom Diffusion | |
| [Custom Diffusion](https://huggingface.co/papers/2212.04488) es una técnica de entrenamiento para personalizar modelos de generación de imágenes. Al igual que Textual Inversion, DreamBooth y LoRA, Custom Diffusion solo requiere unas pocas (~4-5) imágenes de ejemplo. Esta técnica funciona entrenando únicamente los pesos en las capas de atención cruzada y utiliza una palabra especial para representar el concepto recién aprendido. Custom Diffusion es única porque también puede aprender múltiples conceptos al mismo tiempo. | |
| Si estás entrenando en una GPU con vRAM limitada, deberías intentar habilitar xFormers con `--enable_xformers_memory_efficient_attention` para un entrenamiento más rápido con requisitos de vRAM más bajos (16GB). Para ahorrar aún más memoria, añade `--set_grads_to_none` en el argumento de entrenamiento para establecer los gradientes en `None` en lugar de cero (esta opción puede causar algunos problemas, así que si experimentas alguno, intenta eliminar este parámetro). | |
| Esta guía explorará el script [train_custom_diffusion.py](https://github.com/huggingface/diffusers/blob/main/examples/custom_diffusion/train_custom_diffusion.py) para que se familiarice más con él y para que pueda adaptarlo a su propio 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 . | |
| ``` | |
| Navegue hasta la carpeta de ejemplo con el script de entrenamiento e instale las dependencias requeridas: | |
| ```bash | |
| cd examples/custom_diffusion | |
| pip install -r requirements.txt | |
| pip install clip-retrieval | |
| ``` | |
| > [!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: | |
| ```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. | |
| > [!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/custom_diffusion/train_custom_diffusion.py) e informarnos si tienes alguna pregunta o inquietud. | |
| ## Parámetros del script | |
| El script de entrenamiento contiene todos los parámetros para ayudarte a personalizar tu ejecución de entrenamiento. Estos se encuentran en la función [`parse_args()`](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/custom_diffusion/train_custom_diffusion.py#L319). La función viene con valores predeterminados, pero también puedes establecer tus propios valores en el comando de entrenamiento si lo deseas. | |
| Por ejemplo, para cambiar la resolución de la imagen de entrada: | |
| ```bash | |
| accelerate launch train_custom_diffusion.py \ | |
| --resolution=256 | |
| ``` | |
| Muchos de los parámetros básicos se describen en la guía de entrenamiento de [DreamBooth](dreambooth#script-parameters), por lo que esta guía se centra en los parámetros exclusivos de Custom Diffusion: | |
| - `--freeze_model`: congela los parámetros de clave y valor en la capa de atención cruzada; el valor predeterminado es `crossattn_kv`, pero puedes configurarlo como `crossattn` para entrenar todos los parámetros de la capa de atención cruzada | |
| - `--concepts_list`: para aprender varios conceptos, proporciona una ruta a un archivo JSON que contenga los conceptos | |
| - `--modifier_token`: una palabra especial utilizada para representar el concepto aprendido | |
| - `--initializer_token`: una palabra especial utilizada para inicializar los embeddings del `modifier_token` | |
| ### Pérdida de preservación previa | |
| La pérdida de preservación previa es un método que utiliza las propias muestras generadas por un modelo para ayudarlo a aprender a generar imágenes más diversas. Dado que estas imágenes de muestra generadas pertenecen a la misma clase que las imágenes que proporcionaste, ayudan al modelo a retener lo que ha aprendido sobre la clase y a utilizar lo que ya sabe sobre la clase para crear nuevas composiciones. | |
| Muchos de los parámetros para la pérdida de preservación previa se describen en la guía de entrenamiento de [DreamBooth](dreambooth#prior-preservation-loss). | |
| ### Regularización | |
| Custom Diffusion incluye el entrenamiento de las imágenes objetivo con un pequeño conjunto de imágenes reales para evitar el sobreajuste. Como puedes imaginar, esto puede ser fácil de hacer cuando solo entrenas con unas pocas imágenes. Descarga 200 imágenes reales con `clip_retrieval`. El `class_prompt` debe ser la misma categoría que las imágenes objetivo. Estas imágenes se almacenan en `class_data_dir`. | |
| ```bash | |
| python retrieve.py --class_prompt cat --class_data_dir real_reg/samples_cat --num_class_images 200 | |
| ``` | |
| Para habilitar la regularización, añade los siguientes parámetros: | |
| - `--with_prior_preservation`: si se debe usar la pérdida de preservación de la distribución previa | |
| - `--prior_loss_weight`: controla la influencia de la pérdida de preservación del prior en el modelo | |
| - `--real_prior`: si se debe usar un pequeño conjunto de imágenes reales para evitar el sobreajuste | |
| ```bash | |
| accelerate launch train_custom_diffusion.py \ | |
| --with_prior_preservation \ | |
| --prior_loss_weight=1.0 \ | |
| --class_data_dir="./real_reg/samples_cat" \ | |
| --class_prompt="cat" \ | |
| --real_prior=True \ | |
| ``` | |
| ## Script de entrenamiento | |
| > [!TIP] | |
| > Gran parte del código del script de entrenamiento de Custom Diffusion es similar al script de [DreamBooth](dreambooth#training-script). Esta guía se centra, en cambio, en el código relevante para Custom Diffusion. | |
| El script de entrenamiento de Custom Diffusion tiene dos clases de conjunto de datos: | |
| - [`CustomDiffusionDataset`](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/custom_diffusion/train_custom_diffusion.py#L165): preprocesa las imágenes, las imágenes de clase y los prompts para el entrenamiento | |
| - [`PromptDataset`](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/custom_diffusion/train_custom_diffusion.py#L148): prepara los prompts para generar imágenes de clases | |
| A continuación, el `modifier_token` se [añade al tokenizer](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/custom_diffusion/train_custom_diffusion.py#L811), se convierte en ids de tokens y se redimensionan las incorporaciones de tokens para tener en cuenta el nuevo `modifier_token`. Luego, las incorporaciones del `modifier_token` se inicializan con las incorporaciones del `initializer_token`. Todos los parámetros del codificador de texto se congelan, excepto las incorporaciones de tokens, ya que es lo que el modelo intenta aprender a asociar con los conceptos. | |
| ```py | |
| params_to_freeze = itertools.chain( | |
| text_encoder.text_model.encoder.parameters(), | |
| text_encoder.text_model.final_layer_norm.parameters(), | |
| text_encoder.text_model.embeddings.position_embedding.parameters(), | |
| ) | |
| freeze_params(params_to_freeze) | |
| ``` | |
| Ahora necesitarás añadir los [pesos de Custom Diffusion](https://github.com/huggingface/diffusers/blob/64603389da01082055a901f2883c4810d1144edb/examples/custom_diffusion/train_custom_diffusion.py#L911C3-L911C3) a las capas de atención. Este es un paso muy importante para obtener la forma y el tamaño correctos de los pesos de atención y para establecer el número adecuado de procesadores de atención en cada bloque de UNet. | |
| ```py | |
| st = unet.state_dict() | |
| for name, _ in unet.attn_processors.items(): | |
| cross_attention_dim = None if name.endswith("attn1.processor") else unet.config.cross_attention_dim | |
| if name.startswith("mid_block"): | |
| hidden_size = unet.config.block_out_channels[-1] | |
| elif name.startswith("up_blocks"): | |
| block_id = int(name[len("up_blocks.")]) | |
| hidden_size = list(reversed(unet.config.block_out_channels))[block_id] | |
| elif name.startswith("down_blocks"): | |
| block_id = int(name[len("down_blocks.")]) | |
| hidden_size = unet.config.block_out_channels[block_id] | |
| layer_name = name.split(".processor")[0] | |
| weights = { | |
| "to_k_custom_diffusion.weight": st[layer_name + ".to_k.weight"], | |
| "to_v_custom_diffusion.weight": st[layer_name + ".to_v.weight"], | |
| } | |
| if train_q_out: | |
| weights["to_q_custom_diffusion.weight"] = st[layer_name + ".to_q.weight"] | |
| weights["to_out_custom_diffusion.0.weight"] = st[layer_name + ".to_out.0.weight"] | |
| weights["to_out_custom_diffusion.0.bias"] = st[layer_name + ".to_out.0.bias"] | |
| if cross_attention_dim is not None: | |
| custom_diffusion_attn_procs[name] = attention_class( | |
| train_kv=train_kv, | |
| train_q_out=train_q_out, | |
| hidden_size=hidden_size, | |
| cross_attention_dim=cross_attention_dim, | |
| ).to(unet.device) | |
| custom_diffusion_attn_procs[name].load_state_dict(weights) | |
| else: | |
| custom_diffusion_attn_procs[name] = attention_class( | |
| train_kv=False, | |
| train_q_out=False, | |
| hidden_size=hidden_size, | |
| cross_attention_dim=cross_attention_dim, | |
| ) | |
| del st | |
| unet.set_attn_processor(custom_diffusion_attn_procs) | |
| custom_diffusion_layers = AttnProcsLayers(unet.attn_processors) | |
| ``` | |
| El [optimizer](https://github.com/huggingface/diffusers/blob/84cd9e8d01adb47f046b1ee449fc76a0c32dc4e2/examples/custom_diffusion/train_custom_diffusion.py#L982) se inicializa para actualizar los parámetros de la capa de atención cruzada: | |
| ```py | |
| optimizer = optimizer_class( | |
| itertools.chain(text_encoder.get_input_embeddings().parameters(), custom_diffusion_layers.parameters()) | |
| if args.modifier_token is not None | |
| else custom_diffusion_layers.parameters(), | |
| lr=args.learning_rate, | |
| betas=(args.adam_beta1, args.adam_beta2), | |
| weight_decay=args.adam_weight_decay, | |
| eps=args.adam_epsilon, | |
| ) | |
| ``` | |
| En el [bucle de entrenamiento](https://github.com/huggingface/diffusers/blob/84cd9e8d01adb47f046b1ee449fc76a0c32dc4e2/examples/custom_diffusion/train_custom_diffusion.py#L1048), es importante actualizar solo los embeddings del concepto que se está intentando aprender. Esto implica establecer en cero los gradientes de todos los demás embeddings de tokens: | |
| ```py | |
| if args.modifier_token is not None: | |
| if accelerator.num_processes > 1: | |
| grads_text_encoder = text_encoder.module.get_input_embeddings().weight.grad | |
| else: | |
| grads_text_encoder = text_encoder.get_input_embeddings().weight.grad | |
| index_grads_to_zero = torch.arange(len(tokenizer)) != modifier_token_id[0] | |
| for i in range(len(modifier_token_id[1:])): | |
| index_grads_to_zero = index_grads_to_zero & ( | |
| torch.arange(len(tokenizer)) != modifier_token_id[i] | |
| ) | |
| grads_text_encoder.data[index_grads_to_zero, :] = grads_text_encoder.data[ | |
| index_grads_to_zero, : | |
| ].fill_(0) | |
| ``` | |
| ## Ejecutar el script | |
| Una vez que hayas realizado todos tus cambios o estés conforme con la configuración predeterminada, ¡estás listo para lanzar el script de entrenamiento! 🚀 | |
| En esta guía, descargará y usará estas [imágenes de gatos](https://www.cs.cmu.edu/~custom-diffusion/assets/data.zip) de ejemplo. También puede crear y usar su propio conjunto de datos si lo desea (consulte la guía [Crear un conjunto de datos para el entrenamiento](create_dataset)). | |
| Establezca la variable de entorno `MODEL_NAME` en un id de modelo del Hub o en una ruta a un modelo local, `INSTANCE_DIR` en la ruta donde acaba de descargar las imágenes de gatos y `OUTPUT_DIR` en el lugar donde desea guardar el modelo. Usará `<new1>` como palabra especial para vincular las nuevas incorporaciones aprendidas. El script crea y guarda puntos de control del modelo y un archivo pytorch_custom_diffusion_weights.bin en su repositorio. | |
| Para monitorear el progreso del entrenamiento con Weights and Biases, agregue el parámetro `--report_to=wandb` al comando de entrenamiento y especifique un prompt de validación con `--validation_prompt`. Esto es útil para depurar y guardar resultados intermedios. | |
| > [!TIP] | |
| > Si estás entrenando con rostros humanos, el equipo de Custom Diffusion ha encontrado que los siguientes parámetros funcionan bien: | |
| > | |
| > - `--learning_rate=5e-6` - `--max_train_steps` puede estar entre 1000 y 2000 - `--freeze_model=crossattn` - use al menos 15-20 imágenes para el entrenamiento | |
| ```bash | |
| export MODEL_NAME="CompVis/stable-diffusion-v1-4" | |
| export OUTPUT_DIR="path-to-save-model" | |
| export INSTANCE_DIR="./data/cat" | |
| accelerate launch train_custom_diffusion.py \ | |
| --pretrained_model_name_or_path=$MODEL_NAME \ | |
| --instance_data_dir=$INSTANCE_DIR \ | |
| --output_dir=$OUTPUT_DIR \ | |
| --class_data_dir=./real_reg/samples_cat/ \ | |
| --with_prior_preservation \ | |
| --real_prior \ | |
| --prior_loss_weight=1.0 \ | |
| --class_prompt="cat" \ | |
| --num_class_images=200 \ | |
| --instance_prompt="photo of a <new1> cat" \ | |
| --resolution=512 \ | |
| --train_batch_size=2 \ | |
| --learning_rate=1e-5 \ | |
| --lr_warmup_steps=0 \ | |
| --max_train_steps=250 \ | |
| --scale_lr \ | |
| --hflip \ | |
| --modifier_token "<new1>" \ | |
| --validation_prompt="<new1> cat sitting in a bucket" \ | |
| --report_to="wandb" \ | |
| --push_to_hub | |
| ``` | |
| Custom Diffusion también puede aprender múltiples conceptos si proporcionas un archivo [JSON](https://github.com/adobe-research/custom-diffusion/blob/main/assets/concept_list.json) con algunos detalles sobre cada concepto que debe aprender. | |
| Ejecute clip-retrieval para recopilar algunas imágenes reales para usarlas en la regularización: | |
| ```bash | |
| pip install clip-retrieval | |
| python retrieve.py --class_prompt {} --class_data_dir {} --num_class_images 200 | |
| ``` | |
| Luego puedes ejecutar el script: | |
| ```bash | |
| export MODEL_NAME="CompVis/stable-diffusion-v1-4" | |
| export OUTPUT_DIR="path-to-save-model" | |
| accelerate launch train_custom_diffusion.py \ | |
| --pretrained_model_name_or_path=$MODEL_NAME \ | |
| --output_dir=$OUTPUT_DIR \ | |
| --concepts_list=./concept_list.json \ | |
| --with_prior_preservation \ | |
| --real_prior \ | |
| --prior_loss_weight=1.0 \ | |
| --resolution=512 \ | |
| --train_batch_size=2 \ | |
| --learning_rate=1e-5 \ | |
| --lr_warmup_steps=0 \ | |
| --max_train_steps=500 \ | |
| --num_class_images=200 \ | |
| --scale_lr \ | |
| --hflip \ | |
| --modifier_token "<new1>+<new2>" \ | |
| --push_to_hub | |
| ``` | |
| Una vez finalizado el entrenamiento, puedes usar tu nuevo modelo de Custom Diffusion para la inferencia. | |
| ```py | |
| import torch | |
| from diffusers import DiffusionPipeline | |
| pipeline = DiffusionPipeline.from_pretrained( | |
| "CompVis/stable-diffusion-v1-4", dtype=torch.float16, | |
| ).to("cuda") # or "mps", "xpu", "cpu" | |
| pipeline.unet.load_attn_procs("path-to-save-model", weight_name="pytorch_custom_diffusion_weights.bin") | |
| pipeline.load_textual_inversion("path-to-save-model", weight_name="<new1>.bin") | |
| image = pipeline( | |
| "<new1> cat sitting in a bucket", | |
| num_inference_steps=100, | |
| guidance_scale=6.0, | |
| eta=1.0, | |
| ).images[0] | |
| image.save("cat.png") | |
| ``` | |
| ```py | |
| import torch | |
| from huggingface_hub.repocard import RepoCard | |
| from diffusers import DiffusionPipeline | |
| pipeline = DiffusionPipeline.from_pretrained( | |
| "CompVis/stable-diffusion-v1-4", dtype=torch.float16, | |
| ).to("cuda") # or "mps", "xpu", "cpu" | |
| model_id = "sayakpaul/custom-diffusion-cat-wooden-pot" | |
| pipeline.unet.load_attn_procs(model_id, weight_name="pytorch_custom_diffusion_weights.bin") | |
| pipeline.load_textual_inversion(model_id, weight_name="<new1>.bin") | |
| pipeline.load_textual_inversion(model_id, weight_name="<new2>.bin") | |
| image = pipeline( | |
| "the <new1> cat sculpture in the style of a <new2> wooden pot", | |
| num_inference_steps=100, | |
| guidance_scale=6.0, | |
| eta=1.0, | |
| ).images[0] | |
| image.save("multi-subject.png") | |
| ``` | |
| ## Próximos pasos | |
| ¡Felicidades por entrenar un modelo con Custom Diffusion! 🎉 Para saber más: | |
| - Lee la publicación de blog [Multi-Concept Customization of Text-to-Image Diffusion](https://www.cs.cmu.edu/~custom-diffusion/) para conocer más detalles sobre los resultados experimentales del equipo de Custom Diffusion. | |
Xet Storage Details
- Size:
- 16.9 kB
- Xet hash:
- 28054b7d0e6eb7babd95f606dfd18108f3155f71ffcf89942e4358b65be87603
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.