Quantización GPTQ en un modelo Llama 2 7B Fine-Tuned con HuggingFace

Quantización GPTQ en Llama 2 7B Fine-Tuned con HuggingFace

Una guía fácil de seguir sobre cómo cuantizar un LLM

Imagen de Milad Fakurian en Unsplash

En mi artículo anterior, te mostré cómo ajustar finamente el nuevo modelo Llama 2, recién lanzado por Meta AI, para construir un generador de código Python en pocas líneas de código. En esta ocasión, describiremos cómo cuantizar este modelo utilizando la cuantización GPTQ ahora que está integrado con transformers.

La semana pasada, Hugging Face anunció la compatibilidad de sus bibliotecas de transformers con la biblioteca AutoGPTQ, que nos permite cuantizar un modelo de lenguaje grande en 2, 3 o 4 bits utilizando la metodología GPTQ.

GPTQ: Cuantización después del entrenamiento en modelos generativos

En un innovador artículo [1], los investigadores presentaron GPTQ, un novedoso método de cuantización después del entrenamiento que tiene el potencial de transformar la compresión de modelos de lenguaje. GPTQ no solo es lo suficientemente eficiente como para aplicarse a modelos con cientos de miles de millones de parámetros, sino que también puede lograr una precisión notable al comprimir estos modelos a tan solo 2, 3 o 4 bits por parámetro sin sacrificar una precisión significativa.

Esta técnica de vanguardia se destaca por su capacidad para cuantizar modelos masivos, como OPT-175B y BLOOM-176B, en solo unas pocas horas de GPU mientras mantiene una perplexidad mínima, una medida rigurosa de precisión. En el ámbito práctico, los investigadores han desarrollado un conjunto de herramientas de ejecución que permite el funcionamiento eficiente de los modelos comprimidos para tareas generativas. Sorprendentemente, lograron ejecutar el modelo comprimido OPT-175B en una sola GPU NVIDIA A100, o con solo dos GPU NVIDIA A6000 más rentables. Además, los kernels de GPU personalizados optimizados para la compresión resultan en aceleraciones significativas, mejorando aún más la practicidad de estos modelos comprimidos.

Lo que hace que GPTQ destaque es su capacidad para cuantizar modelos de lenguaje con cientos de miles de millones de parámetros en el rango de 3-4 bits por componente. Este es un avance notable, ya que los métodos anteriores tenían dificultades para mantener la precisión por debajo de los 8 bits y generalmente se centraban en modelos más pequeños. Sin embargo, el estudio también destaca las complejas compensaciones entre perplexidad, ancho de bits y tamaño del modelo inducidas por la compresión. Pero también tiene limitaciones. GPTQ actualmente no ofrece aceleraciones para multiplicaciones reales debido a la falta de soporte de hardware para operandos de precisión mixta en arquitecturas convencionales. La cuantización de activaciones tampoco está incluida en los resultados actuales, pero se puede abordar a través de técnicas ortogonales.

En resumen, la capacidad de GPTQ para comprimir modelos de lenguaje extremadamente precisos a niveles sin precedentes marca un hito significativo en el campo del aprendizaje automático y la modelización del lenguaje. Allana el camino para aplicaciones más eficientes y accesibles de estos modelos colosales mientras apunta hacia nuevas posibilidades de investigación en el ámbito de la compresión de modelos.

Métodos de cuantización en el aprendizaje automático se pueden categorizar en dos enfoques distintos, cada uno con sus ventajas únicas:

  1. Cuantización después del entrenamiento (PTQ): En PTQ, los modelos pre-entrenados se cuantizan utilizando recursos relativamente moderados, como un conjunto de datos de calibración y algunas horas de tiempo computacional. Este método es particularmente beneficioso para modelos grandes, donde la reentrenamiento completo o el ajuste fino pueden ser costosos.
  2. Entrenamiento con conciencia de cuantización (QAT): QAT, por otro lado, implica la cuantización aplicada antes del entrenamiento del modelo o durante el ajuste fino posterior.

Enfoque innovador de GPTQ: GPTQ se clasifica en la categoría PTQ, lo que lo convierte en una opción atractiva para modelos masivos. Lo que distingue a GPTQ es su adopción de un esquema de cuantización mixto int4/fp16. Aquí, los pesos del modelo se cuantizan como int4, mientras que las activaciones se mantienen en float16. Durante la inferencia, los pesos se descuantizan dinámicamente y se realizan los cálculos en float16.

Este enfoque innovador promete ahorros de memoria cercanos a 4 veces para la cuantización int4 y posibles aceleraciones debido al menor ancho de banda utilizado para los pesos. En la práctica, GPTQ es un método de cuantización diseñado para modelos que ya están ajustados finamente y listos para implementarse. Este método es particularmente eficaz para reducir la precisión de los pesos del modelo a 4 bits o 3 bits, aunque se utiliza principalmente para la cuantización de 4 bits.

Una característica clave de GPTQ es su capacidad para cuantificar modelos sin necesidad de cargar el modelo completo en la memoria. En cambio, cuantifica el modelo módulo por módulo, reduciendo significativamente los requisitos de memoria durante el proceso de cuantificación. Sin embargo, requiere una pequeña muestra de datos para la calibración, un paso que puede llevar más de una hora en una GPU de consumo típica.

Imagen de Pythonfix en la descripción del paquete Auto-GPTQ.

Para una explicación detallada sobre GPTQ, puedes leer el increíble artículo de Maxime Labonne, “Cuantización de 4 bits con GPTQ” publicado en Towards Data Science. Es un artículo que profundiza en los aspectos técnicos para aquellos que deseen comprender los detalles de este proceso.

Y recomiendo encarecidamente el útil artículo “GPTQ o bitsandbytes: ¿Qué método de cuantización utilizar para LLMs? – Ejemplos con Llama 2” de Benjamin Marie. Allí, puedes ver una comparación entre la cuantización de GPTQ y bitsandbytes, ventajas y desventajas, de modo que puedas comprender mejor cuándo es más conveniente aplicar cada una de estas técnicas.

¿Cuándo debes usar GPTQ?

La respuesta a esta pregunta dependerá de cada caso específico y del modelo base a utilizar, pero un enfoque que se está aplicando a numerosos modelos y que es indicado por HuggingFace, y el artículo que mencioné antes, es el siguiente:

  • Ajusta finamente el modelo LLM original con bitsandbytes en 4 bits, nf4 y QLoRa para un ajuste fino eficiente.
  • Fusiona el adaptador en el modelo original
  • Cuantifica el modelo resultante con GPTQ de 4 bits.

Ejecuté los dos primeros pasos en mi artículo anterior [3] y ahora que la biblioteca AutoGPT está integrada con el ecosistema de Huggingface, ejecutaremos el tercer paso de una manera extremadamente sencilla.

AutoGPT integrado con Hugging Face transformers

La biblioteca AutoGPTQ surge como una herramienta poderosa para cuantificar modelos Transformer, empleando el eficiente método GPTQ. Algunos esfuerzos como GPTQ-for-LLaMa, Exllama y llama.cpp se centran en la cuantificación de la arquitectura Llama, pero AutoGPTQ se distingue al ofrecer soporte perfecto para una amplia variedad de arquitecturas de transformadores.

El equipo de Hugging Face ha dado un paso significativo para mejorar la accesibilidad a GPTQ, e han integrado una API Transformers inclusiva, simplificando el proceso de cuantización del Modelo de Bajo Nivel (LLM) para una audiencia más amplia. Esta integración incluye opciones de optimización esenciales, como núcleos CUDA, que se adaptan a casos de uso comunes.

Para los usuarios que buscan opciones de cuantización más avanzadas, la biblioteca Auto-GPTQ sigue siendo un recurso valioso, ofreciendo capacidades como núcleos Triton y compatibilidad con atención fusionada, y asegurando versatilidad y adaptabilidad en el mundo de la cuantización de modelos transformer.

Nuestra integración de AutoGPTQ tiene muchas ventajas:

Los modelos cuantizados son serializables y se pueden compartir en el Hub.

GPTQ reduce drásticamente los requisitos de memoria para ejecutar LLMs, mientras que la latencia de inferencia es similar a la de la inferencia de FP16.

AutoGPTQ admite núcleos Exllama para una amplia gama de arquitecturas.

La integración cuenta con soporte nativo de RoCm para GPUs AMD.

Está disponible el ajuste fino con PEFT.

Extraído del artículo del blog de Huggingface “Haciendo los LLMs más ligeros con AutoGPTQ y transformers” [5].

Nuestro enfoque para esta tarea

En primer lugar, cargaremos nuestro modelo ajustado finamente Llama 2 7B 4-bit Python coder en una sesión de Colab utilizando un T4 con memoria adicional. El modelo se carga en 4 bits con bitsandbytes y luego ejecutamos alrededor de 12 ejemplos para medir el tiempo de inferencia. Con el fin de realizar una evaluación simple del rendimiento en el tiempo de inferencia, hemos tomado como ejemplos aquellos cuyo texto de entrada tenía más de 500 caracteres y de esta manera, trataremos de apreciar mejor el impacto de la cuantización durante la inferencia.

Puedes extraer el código para cargar este modelo en la descripción del modelo en Hugging Face Hub. En mi cuaderno, describiremos cómo realizar inferencias en los ejemplos mencionados.

Cuantizar el modelo usando auto-gptq, 🤗 transformers y optimum

La cuantización de GPTQ consume mucha memoria VRAM de la GPU, por esa razón necesitamos ejecutarlo en una GPU A100 en Colab. Se tarda aproximadamente 45 minutos en cuantizar el modelo, menos de $1 en Colab. Puedes encontrar el código en este cuaderno en mi repositorio.

Primero, necesitamos instalar las bibliotecas como se recomienda en el tutorial de Hugging Face:

!pip install -q -U transformers peft accelerate optimum!pip install auto-gptq --extra-index-url https://huggingface.github.io/autogptq-index/whl/cu117/# Por ahora, hasta la próxima versión de AutoGPTQ, construiremos la biblioteca desde el origen!

La biblioteca Optimum, la herramienta de Hugging Face para la optimización del entrenamiento y la inferencia, proporciona la integración de AutoGPTQ en Transformers.

El algoritmo GPTQ requiere calibrar los pesos cuantizados del modelo haciendo inferencias en el modelo cuantizado. Para cuantizar un modelo usando auto-gptq, necesitamos pasar un conjunto de datos al cuantizador. Esto se puede lograr ya sea pasando un conjunto de datos predeterminado compatible entre ['wikitext2','c4','c4-new','ptb','ptb-new'] o una lista de cadenas que se utilizarán como conjunto de datos personalizado.

Ahora solo necesitas cargar el modelo usando una configuración GPTQ estableciendo los parámetros deseados, como es habitual al trabajar con transformers, es muy fácil:

from transformers import AutoModelForCausalLM, AutoTokenizer, GPTQConfigimport torch# Establecer el modelo para cargarhf_model_repo='edumunozsala/llama-2-7b-int4-python-code-20k'# Cargar el tokenizertokenizer = AutoTokenizer.from_pretrained(hf_model_repo, use_fast=True)# Establecer la configuración de cuantizaciónquantization_config = GPTQConfig(     bits=4,     group_size=128,     dataset="c4",     desc_act=False,     tokenizer=tokenizer)# Cargar el modelo desde HFquant_model = AutoModelForCausalLM.from_pretrained(hf_model_repo,                 quantization_config=quantization_config, device_map='auto')

Como se mencionó, este código tarda aproximadamente 45 minutos en ejecutarse y consume un máximo de 32 GB de memoria VRAM de la GPU. “Necesitarás una GPU para cuantizar un modelo. Pondremos el modelo en la CPU y moveremos los módulos hacia adelante y hacia atrás a la GPU para cuantificarlos. Si quieres maximizar el uso de tus GPUs mientras usas la descarga de la CPU, puedes configurar device_map = 'auto'” [6], documentos de Hugging Face.

Los parámetros se explican por sí mismos, cuantización de 4 bits, conjunto de datos C4 y el tokenizador a utilizar durante la cuantización. Los otros dos parámetros toman los valores predeterminados:

  • group_size: El tamaño del grupo a utilizar para la cuantización. El valor recomendado es 128 y -1 utiliza cuantización por columna.
  • desc_act: Si se deben cuantizar las columnas en orden de tamaño de activación decreciente. Establecerlo en Falso puede acelerar significativamente la inferencia, pero la perplejidad puede empeorar ligeramente. También conocido como act-order.

Una vez que tengas tu modelo cuantizado, es hora de cargarlo en Hugging Face Hub y compartirlo con la comunidad.

quant_model.push_to_hub("edumunozsala/llama-2-7b-int4-GPTQ-python-code-20k")tokenizer.push_to_hub("edumunozsala/llama-2-7b-int4-GPTQ-python-code-20k")

En mi experimento usando GPTQ, la reducción en el tamaño del modelo es sorprendente. Mi modelo Llama 2 7B afinado con pesos de 4 bits ocupaba 13.5 GB en disco, pero después de la cuantización, su tamaño se redujo drásticamente a solo 3.9 GB, un tercio del tamaño original. Esta característica es muy atractiva al implementar modelos de lenguaje grandes.

Cargando el modelo GPTQ desde Hugging Face Hub y realizando algunas inferencias

Probablemente, todos ustedes saben cómo hacer eso, pero por si acaso piensan que esto podría ser más “complicado” que con otros modelos, les mostraremos que es como de costumbre.

Recuerden que necesitan cargar todas las bibliotecas, incluyendo optimum, accelerate y, por supuesto, auto-gptq .

!pip install -q -U transformers peft accelerate optimum!pip install auto-gptq

Luego pueden cargar el tokenizer y el modelo en su cuaderno en una T4 GPU en Google Colab:

import torchfrom transformers import AutoModelForCausalLM, AutoTokenizermodel_id = "edumunozsala/llama-2-7b-int4-GPTQ-python-code-20k"tokenizer = AutoTokenizer.from_pretrained(model_id)model = AutoModelForCausalLM.from_pretrained(model_id,                   torch_dtype=torch.float16, device_map="auto")

Ahora podemos verificar nuestra GPU para confirmar cuánta memoria estamos consumiendo y, de hecho, podemos ver que el modelo ocupa 5,053 GB.

Repetimos la evaluación de rendimiento que mencionamos anteriormente, haciendo inferencias en un montón de ejemplos largos para comparar con el modelo original. Ambos procesos de inferencia se ejecutaron en una GPU T4, el modelo base tardó alrededor de 17-19 segundos por inferencia mientras que el modelo cuantizado se ejecutó en aproximadamente 8 a 9 segundos por inferencia, la mitad.

Todo el código y los ejemplos están bien explicados en su cuaderno en mi repositorio. Cualquier sugerencia o corrección de errores es bienvenida.

Referencias

[1] Artículo ICLR 2023 “GPTQ: Cuantificación precisa posterior al entrenamiento para transformers pre-entrenados generativos”

[2] “GPTQ o bitsandbytes: ¿Qué método de cuantificación usar para LLMs? – Ejemplos con Llama 2” por Benjamin Marie.

[3] “Afinando un modelo Llama 2 7B para la generación de código en Python” por Eduardo Muñoz

[4] Modelo afinado original en Huggingface “edumunozsala/llama-2–7b-int4-python-code-20k”

[5] Artículo del blog de Hugging Face “Haciendo LLMs más livianos con AutoGPTQ y transformers”

[6] Documentación oficial de Hugging Face sobre GPTQConfig

[7] “Cuantificación de 4 bits con GPTQ” por Maxime Labonne.

We will continue to update Zepes; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

Inteligencia Artificial

La FAA aprueba el sistema de aeronaves no tripuladas más grande de los Estados Unidos.

La Administración Federal de Aviación de los Estados Unidos aprobó la operación comercial de los rociadores agrícolas...

Inteligencia Artificial

Ajuste fino rápido y rentable de LLaMA 2 con AWS Trainium

Los grandes modelos de lenguaje (LLMs) han capturado la imaginación y la atención de desarrolladores, científicos, te...