Buckets:
| # bitsandbytes | |
| [bitsandbytes](https://huggingface.co/docs/bitsandbytes/index) es la opción más sencilla para cuantizar un modelo a 8 y 4 bits. La cuantización a 8 bits multiplica los valores atípicos en fp16 con los no atípicos en int8, convierte los valores no atípicos de vuelta a fp16 y luego los suma para devolver los pesos en fp16. Esto reduce el efecto degradante que los valores atípicos tienen sobre el rendimiento de un modelo. | |
| La cuantización de 4 bits comprime aún más un modelo y se utiliza comúnmente con [QLoRA](https://hf.co/papers/2305.14314) para ajustar LLMs cuantizados. | |
| Esta guía demuestra cómo la cuantización permite ejecutar [FLUX.1-dev](https://huggingface.co/black-forest-labs/FLUX.1-dev) con menos de 16 GB de VRAM e incluso en una instancia gratuita de Google Colab. | |
|  | |
| Para usar bitsandbytes, asegúrate de tener instaladas las siguientes bibliotecas: | |
| ```bash | |
| pip install diffusers transformers accelerate bitsandbytes -U | |
| ``` | |
| Ahora puedes cuantizar un modelo pasando una [BitsAndBytesConfig](/docs/diffusers/v0.43.0/es/api/quantization#diffusers.BitsAndBytesConfig) a [from_pretrained()](/docs/diffusers/v0.43.0/es/api/models/overview#diffusers.ModelMixin.from_pretrained). Esto funciona para cualquier modelo de cualquier modalidad, siempre que admita la carga con [Accelerate](https://hf.co/docs/accelerate/index) y contenga capas `torch.nn.Linear`. | |
| Cuantizar un modelo en 8 bits reduce a la mitad el uso de memoria: | |
| bitsandbytes es compatible tanto con Transformers como con Diffusers, por lo que puedes cuantizar tanto el [FluxTransformer2DModel](/docs/diffusers/v0.43.0/es/api/models/flux_transformer#diffusers.FluxTransformer2DModel) como el [T5EncoderModel](https://huggingface.co/docs/transformers/v5.22.2/en/model_doc/t5#transformers.T5EncoderModel). | |
| Para GPUs de la serie Ada y superiores, recomendamos cambiar `dtype` a `torch.bfloat16`. | |
| > [!TIP] | |
| > El `CLIPTextModel` y el [AutoencoderKL](/docs/diffusers/v0.43.0/es/api/models/autoencoderkl#diffusers.AutoencoderKL) no están cuantizados porque ya son pequeños en tamaño y porque [AutoencoderKL](/docs/diffusers/v0.43.0/es/api/models/autoencoderkl#diffusers.AutoencoderKL) solo tiene unas pocas capas `torch.nn.Linear`. | |
| ```py | |
| from diffusers import BitsAndBytesConfig as DiffusersBitsAndBytesConfig | |
| from transformers import BitsAndBytesConfig as TransformersBitsAndBytesConfig | |
| import torch | |
| from diffusers import AutoModel | |
| from transformers import T5EncoderModel | |
| quant_config = TransformersBitsAndBytesConfig(load_in_8bit=True,) | |
| text_encoder_2_8bit = T5EncoderModel.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", | |
| subfolder="text_encoder_2", | |
| quantization_config=quant_config, | |
| dtype=torch.float16, | |
| ) | |
| quant_config = DiffusersBitsAndBytesConfig(load_in_8bit=True,) | |
| transformer_8bit = AutoModel.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", | |
| subfolder="transformer", | |
| quantization_config=quant_config, | |
| dtype=torch.float16, | |
| ) | |
| ``` | |
| Por defecto, todos los demás módulos, como `torch.nn.LayerNorm`, se convierten a `torch.float16`. Puedes cambiar el tipo de datos de estos módulos con el parámetro `dtype`. | |
| ```diff | |
| transformer_8bit = AutoModel.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", | |
| subfolder="transformer", | |
| quantization_config=quant_config, | |
| + dtype=torch.float32, | |
| ) | |
| ``` | |
| Generemos una imagen usando nuestros modelos cuantizados. | |
| Establecer `device_map="auto"` llena automáticamente todo el espacio disponible primero en las GPU, luego en la CPU y, por último, en el disco duro (la opción más lenta) si aún no hay suficiente memoria. | |
| ```py | |
| from diffusers import FluxPipeline | |
| pipe = FluxPipeline.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", | |
| transformer=transformer_8bit, | |
| text_encoder_2=text_encoder_2_8bit, | |
| dtype=torch.float16, | |
| device_map="auto", | |
| ) | |
| pipe_kwargs = { | |
| "prompt": "A cat holding a sign that says hello world", | |
| "height": 1024, | |
| "width": 1024, | |
| "guidance_scale": 3.5, | |
| "num_inference_steps": 50, | |
| "max_sequence_length": 512, | |
| } | |
| image = pipe(**pipe_kwargs, generator=torch.manual_seed(0),).images[0] | |
| ``` | |
| Cuando hay suficiente memoria, también puede mover directamente el pipeline a la GPU con `.to("cuda")` y aplicar [enable_model_cpu_offload()](/docs/diffusers/v0.43.0/es/api/pipelines/overview#diffusers.DiffusionPipeline.enable_model_cpu_offload) para optimizar el uso de memoria de la GPU. | |
| Una vez que un modelo está cuantizado, puedes subir el modelo al Hub con el método [push_to_hub()](/docs/diffusers/v0.43.0/es/api/schedulers/overview#diffusers.utils.PushToHubMixin.push_to_hub). El archivo de configuración de cuantización `config.json` se sube primero, seguido de los pesos del modelo cuantizado. También puedes guardar los modelos 8-bit serializados localmente con [save_pretrained()](/docs/diffusers/v0.43.0/es/api/models/overview#diffusers.ModelMixin.save_pretrained). | |
| Cuantizar un modelo en 4 bits reduce el uso de memoria en 4 veces: | |
| bitsandbytes es compatible tanto con Transformers como con Diffusers, por lo que puedes cuantizar tanto el [FluxTransformer2DModel](/docs/diffusers/v0.43.0/es/api/models/flux_transformer#diffusers.FluxTransformer2DModel) como el [T5EncoderModel](https://huggingface.co/docs/transformers/v5.22.2/en/model_doc/t5#transformers.T5EncoderModel). | |
| Para GPUs de la serie Ada y superiores, recomendamos cambiar `dtype` a `torch.bfloat16`. | |
| > [!TIP] | |
| > El `CLIPTextModel` y el [AutoencoderKL](/docs/diffusers/v0.43.0/es/api/models/autoencoderkl#diffusers.AutoencoderKL) no están cuantizados porque ya son pequeños en tamaño y porque [AutoencoderKL](/docs/diffusers/v0.43.0/es/api/models/autoencoderkl#diffusers.AutoencoderKL) solo tiene unas pocas capas `torch.nn.Linear`. | |
| ```py | |
| from diffusers import BitsAndBytesConfig as DiffusersBitsAndBytesConfig | |
| from transformers import BitsAndBytesConfig as TransformersBitsAndBytesConfig | |
| import torch | |
| from diffusers import AutoModel | |
| from transformers import T5EncoderModel | |
| quant_config = TransformersBitsAndBytesConfig(load_in_4bit=True,) | |
| text_encoder_2_4bit = T5EncoderModel.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", | |
| subfolder="text_encoder_2", | |
| quantization_config=quant_config, | |
| dtype=torch.float16, | |
| ) | |
| quant_config = DiffusersBitsAndBytesConfig(load_in_4bit=True,) | |
| transformer_4bit = AutoModel.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", | |
| subfolder="transformer", | |
| quantization_config=quant_config, | |
| dtype=torch.float16, | |
| ) | |
| ``` | |
| Por defecto, todos los demás módulos, como `torch.nn.LayerNorm`, se convierten a `torch.float16`. Puedes cambiar el tipo de datos de estos módulos con el parámetro `dtype`. | |
| ```diff | |
| transformer_4bit = AutoModel.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", | |
| subfolder="transformer", | |
| quantization_config=quant_config, | |
| + dtype=torch.float32, | |
| ) | |
| ``` | |
| Generemos una imagen usando nuestros modelos cuantizados. | |
| Establecer `device_map="auto"` llena automáticamente todo el espacio disponible primero en las GPU, luego en la CPU y, por último, en el disco duro (la opción más lenta) si aún no hay suficiente memoria. | |
| ```py | |
| from diffusers import FluxPipeline | |
| pipe = FluxPipeline.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", | |
| transformer=transformer_4bit, | |
| text_encoder_2=text_encoder_2_4bit, | |
| dtype=torch.float16, | |
| device_map="auto", | |
| ) | |
| pipe_kwargs = { | |
| "prompt": "A cat holding a sign that says hello world", | |
| "height": 1024, | |
| "width": 1024, | |
| "guidance_scale": 3.5, | |
| "num_inference_steps": 50, | |
| "max_sequence_length": 512, | |
| } | |
| image = pipe(**pipe_kwargs, generator=torch.manual_seed(0),).images[0] | |
| ``` | |
| Cuando hay suficiente memoria, también puede mover directamente el pipeline a la GPU con `.to("cuda")` y aplicar [enable_model_cpu_offload()](/docs/diffusers/v0.43.0/es/api/pipelines/overview#diffusers.DiffusionPipeline.enable_model_cpu_offload) para optimizar el uso de memoria de la GPU. | |
| Una vez que un modelo está cuantizado, puedes subir el modelo al Hub con el método [push_to_hub()](/docs/diffusers/v0.43.0/es/api/schedulers/overview#diffusers.utils.PushToHubMixin.push_to_hub). El archivo de configuración de cuantización `config.json` se sube primero, seguido de los pesos del modelo cuantizado. También puedes guardar los modelos de 4 bits serializados localmente con [save_pretrained()](/docs/diffusers/v0.43.0/es/api/models/overview#diffusers.ModelMixin.save_pretrained). | |
| > [!WARNING] | |
| > El entrenamiento con pesos de 8 bits y 4 bits solo se admite para entrenar parámetros *extra*. | |
| Comprueba tu huella de memoria con el método `get_memory_footprint`: | |
| ```py | |
| print(model.get_memory_footprint()) | |
| ``` | |
| Tenga en cuenta que esto solo le indica la huella de memoria de los parámetros del modelo y no _estima_ los requisitos de memoria para la inferencia. | |
| Los modelos cuantizados se pueden cargar desde el método [from_pretrained()](/docs/diffusers/v0.43.0/es/api/models/overview#diffusers.ModelMixin.from_pretrained) sin necesidad de especificar los parámetros de `quantization_config`: | |
| ```py | |
| from diffusers import AutoModel, BitsAndBytesConfig | |
| quantization_config = BitsAndBytesConfig(load_in_4bit=True) | |
| model_4bit = AutoModel.from_pretrained( | |
| "hf-internal-testing/flux.1-dev-nf4-pkg", subfolder="transformer" | |
| ) | |
| ``` | |
| ## 8-bit (algoritmo LLM.int8()) | |
| > [!TIP] | |
| > ¡Aprende más sobre los detalles de la cuantización de 8 bits en esta [entrada de blog](https://huggingface.co/blog/hf-bitsandbytes-integration)! | |
| Esta sección explora algunas de las características específicas de los modelos de 8 bits, como los umbrales de valores atípicos y el omitir la conversión de módulos. | |
| ### Umbral de valores atípicos | |
| Un "outlier" es un valor de estado oculto mayor que un cierto umbral, y estos valores se calculan en fp16. Si bien los valores suelen estar distribuidos de forma normal ([-3.5, 3.5]), esta distribución puede ser muy diferente en modelos grandes ([-60, 6] o [6, 60]). La cuantización de 8 bits funciona bien para valores ~5, pero más allá de eso, hay un penalización significativa en el rendimiento. Un valor de umbral predeterminado adecuado es 6, pero puede ser necesario un umbral más bajo para modelos más inestables (modelos pequeños o finetuning). | |
| Para encontrar el mejor umbral para su modelo, le recomendamos experimentar con el parámetro `llm_int8_threshold` en [BitsAndBytesConfig](/docs/diffusers/v0.43.0/es/api/quantization#diffusers.BitsAndBytesConfig): | |
| ```py | |
| from diffusers import AutoModel, BitsAndBytesConfig | |
| quantization_config = BitsAndBytesConfig( | |
| load_in_8bit=True, llm_int8_threshold=10, | |
| ) | |
| model_8bit = AutoModel.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", | |
| subfolder="transformer", | |
| quantization_config=quantization_config, | |
| ) | |
| ``` | |
| ### Omitir la conversión de módulos | |
| Para algunos modelos, no es necesario cuantizar todos los módulos a 8 bits, ya que esto puede causar inestabilidad. Por ejemplo, en modelos de difusión como [Stable Diffusion 3](../api/pipelines/stable_diffusion/stable_diffusion_3), el módulo `proj_out` puede omitirse mediante el parámetro `llm_int8_skip_modules` en [BitsAndBytesConfig](/docs/diffusers/v0.43.0/es/api/quantization#diffusers.BitsAndBytesConfig): | |
| ```py | |
| from diffusers import SD3Transformer2DModel, BitsAndBytesConfig | |
| quantization_config = BitsAndBytesConfig( | |
| load_in_8bit=True, llm_int8_skip_modules=["proj_out"], | |
| ) | |
| model_8bit = SD3Transformer2DModel.from_pretrained( | |
| "stabilityai/stable-diffusion-3-medium-diffusers", | |
| subfolder="transformer", | |
| quantization_config=quantization_config, | |
| ) | |
| ``` | |
| ## 4-bit (algoritmo QLoRA) | |
| > [!TIP] | |
| > Obtenga más detalles en esta [entrada de blog](https://huggingface.co/blog/4bit-transformers-bitsandbytes). | |
| Esta sección explora algunas de las características específicas de los modelos de 4 bits, como cambiar el tipo de datos de cálculo, usar el tipo de datos Normal Float 4 (NF4) y usar cuantización anidada. | |
| ### Tipo de datos de cálculo | |
| Para acelerar el cálculo, puedes cambiar el tipo de datos de float32 (el valor predeterminado) a bf16 usando el parámetro `bnb_4bit_compute_dtype` en [BitsAndBytesConfig](/docs/diffusers/v0.43.0/es/api/quantization#diffusers.BitsAndBytesConfig): | |
| ```py | |
| import torch | |
| from diffusers import BitsAndBytesConfig | |
| quantization_config = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_compute_dtype=torch.bfloat16) | |
| ``` | |
| ### Float 4 normal (NF4) | |
| NF4 es un tipo de datos de 4 bits del artículo [QLoRA](https://hf.co/papers/2305.14314), adaptado para pesos inicializados desde una distribución normal. Debe usar NF4 para entrenar modelos base de 4 bits. Esto se puede configurar con el parámetro `bnb_4bit_quant_type` en [BitsAndBytesConfig](/docs/diffusers/v0.43.0/es/api/quantization#diffusers.BitsAndBytesConfig): | |
| ```py | |
| from diffusers import BitsAndBytesConfig as DiffusersBitsAndBytesConfig | |
| from transformers import BitsAndBytesConfig as TransformersBitsAndBytesConfig | |
| from diffusers import AutoModel | |
| from transformers import T5EncoderModel | |
| quant_config = TransformersBitsAndBytesConfig( | |
| load_in_4bit=True, | |
| bnb_4bit_quant_type="nf4", | |
| ) | |
| text_encoder_2_4bit = T5EncoderModel.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", | |
| subfolder="text_encoder_2", | |
| quantization_config=quant_config, | |
| dtype=torch.float16, | |
| ) | |
| quant_config = DiffusersBitsAndBytesConfig( | |
| load_in_4bit=True, | |
| bnb_4bit_quant_type="nf4", | |
| ) | |
| transformer_4bit = AutoModel.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", | |
| subfolder="transformer", | |
| quantization_config=quant_config, | |
| dtype=torch.float16, | |
| ) | |
| ``` | |
| Para la inferencia, el `bnb_4bit_quant_type` no tiene un gran impacto en el rendimiento. Sin embargo, para mantener la consistencia con los pesos del modelo, debe usar los valores de `bnb_4bit_compute_dtype` y `dtype`. | |
| ### Cuantización anidada | |
| La cuantización anidada es una técnica que puede ahorrar memoria adicional sin un coste de rendimiento extra. Esta función realiza una segunda cuantización de los pesos ya cuantizados para ahorrar 0,4 bits/parámetro adicionales. | |
| ```py | |
| from diffusers import BitsAndBytesConfig as DiffusersBitsAndBytesConfig | |
| from transformers import BitsAndBytesConfig as TransformersBitsAndBytesConfig | |
| from diffusers import AutoModel | |
| from transformers import T5EncoderModel | |
| quant_config = TransformersBitsAndBytesConfig( | |
| load_in_4bit=True, | |
| bnb_4bit_use_double_quant=True, | |
| ) | |
| text_encoder_2_4bit = T5EncoderModel.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", | |
| subfolder="text_encoder_2", | |
| quantization_config=quant_config, | |
| dtype=torch.float16, | |
| ) | |
| quant_config = DiffusersBitsAndBytesConfig( | |
| load_in_4bit=True, | |
| bnb_4bit_use_double_quant=True, | |
| ) | |
| transformer_4bit = AutoModel.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", | |
| subfolder="transformer", | |
| quantization_config=quant_config, | |
| dtype=torch.float16, | |
| ) | |
| ``` | |
| ## Descomprimir modelos de `bitsandbytes` | |
| Una vez cuantizado, puedes descuantizar un modelo a su precisión original, aunque esto podría provocar una pequeña pérdida de calidad. Asegúrate de tener suficiente RAM de GPU para cargar el modelo descuantizado. | |
| ```python | |
| from diffusers import BitsAndBytesConfig as DiffusersBitsAndBytesConfig | |
| from transformers import BitsAndBytesConfig as TransformersBitsAndBytesConfig | |
| from diffusers import AutoModel | |
| from transformers import T5EncoderModel | |
| quant_config = TransformersBitsAndBytesConfig( | |
| load_in_4bit=True, | |
| bnb_4bit_use_double_quant=True, | |
| ) | |
| text_encoder_2_4bit = T5EncoderModel.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", | |
| subfolder="text_encoder_2", | |
| quantization_config=quant_config, | |
| dtype=torch.float16, | |
| ) | |
| quant_config = DiffusersBitsAndBytesConfig( | |
| load_in_4bit=True, | |
| bnb_4bit_use_double_quant=True, | |
| ) | |
| transformer_4bit = AutoModel.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", | |
| subfolder="transformer", | |
| quantization_config=quant_config, | |
| dtype=torch.float16, | |
| ) | |
| text_encoder_2_4bit.dequantize() | |
| transformer_4bit.dequantize() | |
| ``` | |
| ## torch.compile | |
| Acelera la inferencia con `torch.compile`. Asegúrate de tener la última versión de `bitsandbytes` instalada y también recomendamos instalar [PyTorch nightly](https://pytorch.org/get-started/locally/). | |
| ```py | |
| torch._dynamo.config.capture_dynamic_output_shape_ops = True | |
| quant_config = DiffusersBitsAndBytesConfig(load_in_8bit=True) | |
| transformer_4bit = AutoModel.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", | |
| subfolder="transformer", | |
| quantization_config=quant_config, | |
| dtype=torch.float16, | |
| ) | |
| transformer_4bit.compile(fullgraph=True) | |
| ``` | |
| ```py | |
| quant_config = DiffusersBitsAndBytesConfig(load_in_4bit=True) | |
| transformer_4bit = AutoModel.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", | |
| subfolder="transformer", | |
| quantization_config=quant_config, | |
| dtype=torch.float16, | |
| ) | |
| transformer_4bit.compile(fullgraph=True) | |
| ``` | |
| En una RTX 4090 con compilación, la generación de Flux de 4 bits se completó en 25.809 segundos frente a 32.570 segundos sin ella. | |
| Consulte el [script de benchmarking](https://gist.github.com/sayakpaul/0db9d8eeeb3d2a0e5ed7cf0d9ca19b7d) para más detalles. | |
| ## Recursos | |
| * [Cuaderno de principio a fin que muestra la inferencia de Flux.1 Dev en un Colab de nivel gratuito](https://gist.github.com/sayakpaul/c76bd845b48759e11687ac550b99d8b4) | |
| * [Entrenamiento](https://github.com/huggingface/diffusers/blob/8c661ea586bf11cb2440da740dd3c4cf84679b85/examples/dreambooth/README_hidream.md#using-quantization) | |
Xet Storage Details
- Size:
- 17.7 kB
- Xet hash:
- fc4ddbcdc501e7e02d14471781e8a2104e4c62973cdb7ced252000d56da49f25
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.