25 puntos por xguru 2024-07-31 | Aún no hay comentarios. | Compartir por WhatsApp
  • Los modelos de lenguaje grandes (LLM) son demasiado grandes para ejecutarse en hardware común y, por lo general, tienen miles de millones de parámetros, por lo que requieren GPUs con grandes cantidades de VRAM
  • Por eso, cada vez más investigación se concentra en hacer estos modelos más pequeños mediante entrenamiento mejorado, adaptadores y otros métodos, y una de las técnicas clave en este campo es la cuantización (Quantization)

Part 1: El “problema” de los modelos de lenguaje grandes

  • Los LLM (Large Language Model) reciben su nombre según la cantidad de parámetros que contienen
  • Estos modelos normalmente incluyen miles de millones de parámetros (en su mayoría pesos), por lo que su costo de almacenamiento puede ser considerable
  • Durante la inferencia, las activaciones se generan a partir del producto entre la entrada y los pesos, y de igual forma pueden ser bastante grandes
  • Por ello, se busca representar miles de millones de valores de la forma más eficiente posible, minimizando al mismo tiempo el espacio necesario para almacenar cada valor dado

Cómo se representan los valores numéricos

  • Un valor dado suele representarse como un número de punto flotante (número real)
  • Estos valores se representan con “bits”, y el estándar IEEE-754 describe cómo los bits indican una de las funciones de signo, exponente y mantisa (fraction) para representar un valor
  • En general, cuantos más bits se usen para representar un valor, mayor será la precisión
  • Cuantos más bits haya disponibles, mayor será el rango de valores que pueden representarse

Restricciones de memoria

  • Si asumimos un modelo con 70 mil millones de parámetros, usar FP32 (full-precision) requeriría 280 GB de memoria solo para cargar el modelo
  • Por lo tanto, es muy importante minimizar el número de bits que representan los parámetros del modelo, pero cuando la precisión disminuye, la exactitud del modelo por lo general también baja
  • El objetivo es reducir la cantidad de bits usada para representar valores manteniendo la exactitud, y aquí es justamente donde entra la cuantización

Part 2: Introducción a la cuantización

  • La cuantización busca reducir la precisión de los parámetros del modelo desde un ancho de bits alto (por ejemplo, punto flotante de 32 bits) a uno más bajo (por ejemplo, enteros de 8 bits)
  • Cada vez que se reduce la cantidad de bits, se realiza un mapeo para “comprimir” los parámetros originales en una representación de pocos bits

Tipos de datos comunes

FP16

  • Al pasar de FP32 a FP16 (half precision), el rango de valores que FP16 puede tomar se vuelve bastante más pequeño que el de FP32

BF16

  • Para obtener un rango de valores similar al de FP32, se introdujo bfloat16, una especie de “FP32 recortado”
  • BF16 usa la misma cantidad de bits que FP16, pero puede abarcar un rango de valores más amplio y se usa con frecuencia en aplicaciones de deep learning

INT8

  • Si se reduce aún más la cantidad de bits, la representación se acerca más a una basada en enteros que a una de punto flotante

Cuantización simétrica

  • El rango de los valores originales de punto flotante se mapea a un rango simétrico alrededor de 0 dentro del espacio cuantizado
  • El valor cuantizado de 0 en el espacio de punto flotante es exactamente 0 en el espacio cuantizado

Cuantización asimétrica

  • A diferencia de la cuantización simétrica, no es simétrica alrededor de 0
  • El valor mínimo (β) y el máximo (α) se mapean desde el rango de punto flotante al valor mínimo y máximo del rango cuantizado
  • Uno de estos métodos se conoce como cuantización con zero-point

Mapeo de rango y clipping

  • Si se mapea el rango completo de un vector, los outliers pueden hacer que todos los valores pequeños terminen mapeados a la misma representación de pocos bits, perdiendo así capacidad de diferenciación
  • En su lugar, se puede optar por aplicar clipping a ciertos valores
  • El clipping consiste en establecer otro rango dinámico para los valores originales, de modo que todos los outliers tengan el mismo valor
  • El error de cuantización de los valores que no son outliers se reduce mucho, pero el error de cuantización de los outliers aumenta

Calibración (Calibration)

Pesos (y bias)

  • Los pesos y el bias pueden considerarse valores estáticos conocidos antes de ejecutar el modelo
  • Como el bias es mucho menos numeroso que los pesos, se mantiene con una precisión mayor (por ejemplo, INT16), y el esfuerzo principal de cuantización se dirige a los pesos
  • Entre las técnicas de calibración para pesos estáticos y conocidos están elegir manualmente percentiles del rango de entrada, optimizar el error cuadrático medio (MSE) entre los pesos originales y cuantizados, o minimizar la entropía (divergencia KL) entre los valores originales y cuantizados

Activaciones

  • Las entradas se actualizan continuamente a lo largo de todo el LLM y normalmente se llaman “activaciones”
  • Como estos valores cambian cada vez que se alimenta al modelo con un dato de entrada durante la inferencia, es difícil cuantizarlos con precisión
  • Estos valores se actualizan después de cada capa oculta, así que solo se puede saber en qué se convertirán durante la inferencia cuando los datos de entrada pasan por el modelo

Part 3: Cuantización post-entrenamiento (PTQ - Post-Training Quantization)

Cuantización dinámica

  • Las activaciones se recopilan después de que los datos pasan por una capa oculta
  • Esta distribución de activaciones se usa para calcular el zero-point (z) y el factor de escala (s) necesarios para cuantizar la salida
  • El proceso se repite cada vez que los datos pasan por una nueva capa. Por eso, cada capa tiene sus propios valores de z y s, y un esquema de cuantización distinto

Cuantización estática

  • El zero-point (z) y el factor de escala (s) se calculan por adelantado, no durante la inferencia
  • Para encontrar estos valores se usa un conjunto de datos de calibración, que se pasa al modelo para recolectar estas distribuciones potenciales
  • Al realizar la inferencia real, los valores de s y z no se recalculan, sino que se usan globalmente para cuantizar todas las activaciones
  • En general, la cuantización dinámica suele ser un poco más precisa porque intenta calcular los valores de s y z en cada capa oculta, aunque eso puede aumentar el tiempo de cómputo
  • En cambio, la cuantización estática es menos precisa, pero más rápida porque ya conoce los valores de s y z

El terreno de la cuantización de 4 bits

  • Bajar de 8 bits ha resultado ser una tarea difícil, porque el error de cuantización aumenta cada vez que se pierde un bit
  • Se exploran GPTQ y GGUF, dos métodos que suelen compartirse comúnmente en HuggingFace

GPTQ

  • Es, de hecho, uno de los métodos más conocidos para cuantizar a 4 bits
  • Usa cuantización asimétrica y se realiza capa por capa, de modo que cada capa se procesa de manera independiente antes de continuar con la siguiente
  • Durante el proceso de cuantización por capa, primero se transforman los pesos de la capa usando la Hessiana inversa, que es la segunda derivada de la función de pérdida del modelo y muestra qué tan sensible es la salida del modelo a cambios en cada peso
  • En pocas palabras, muestra la (inversa de la) importancia de cada peso en la capa
  • Los pesos con valores pequeños en la matriz Hessiana son más importantes, porque pequeños cambios en esos pesos pueden provocar grandes cambios en el rendimiento del modelo

GGUF

  • GPTQ es un buen método de cuantización para ejecutar un LLM completo en GPU, pero no siempre se dispone de esa capacidad
  • En su lugar, se puede usar GGUF para hacer offload de todas las capas del LLM al CPU
  • Esto permite usar tanto CPU como GPU cuando no hay suficiente VRAM

Part 4: Entrenamiento consciente de cuantización (QAT - Quantization Aware Training)

  • En la parte 3 vimos cómo cuantizar un modelo después del entrenamiento, pero esta cuantización tiene la desventaja de no considerar el proceso real de entrenamiento
  • Aquí es donde entra el entrenamiento consciente de cuantización (QAT). A diferencia de PTQ, QAT busca aprender el procedimiento de cuantización durante el entrenamiento
  • QAT tiende a ser más preciso que PTQ porque la cuantización ya se consideró durante el entrenamiento

La era de los LLM de 1 bit: BitNet

  • BitNet representa los pesos del modelo con un único bit: -1 o 1
  • Esto se logra inyectando directamente el proceso de cuantización en la arquitectura Transformer
  • La arquitectura Transformer se usa como base de la mayoría de los LLM y está compuesta por cálculos que incluyen capas lineales
  • BitNet reemplaza estas capas lineales por algo llamado BitLinear

Cuantización de pesos

  • Durante el entrenamiento, los pesos se almacenan en INT8 y luego se cuantizan a 1 bit usando la estrategia básica de la función signo
  • Esencialmente, se desplaza la distribución de los pesos para centrarla en 0, y luego todo lo que queda a la izquierda de 0 se asigna a -1, y todo lo de la derecha a 1

Cuantización de activaciones

  • Para cuantizar las activaciones, BitLinear usa cuantización absmax para convertir las activaciones de FP16 a INT8, ya que la multiplicación de matrices (×) requiere mayor precisión

Dequantización

  • Se hizo seguimiento de α (el mayor valor absoluto entre las activaciones) y β (el valor absoluto medio de los pesos), ya que estos valores luego ayudarán a dequantizar las activaciones de vuelta a FP16
  • Las activaciones de salida se reescalan con {α, γ} para dequantizarlas de nuevo a su precisión original

Todos los modelos de lenguaje grandes son de 1.58 bits

  • BitNet 1.58b se introdujo para mejorar los problemas de escalado mencionados antes
  • En este nuevo método, cada peso individual del modelo ya no solo puede tomar -1 o 1, sino también 0, por lo que se vuelve ternario
    • Curiosamente, agregar solo el 0 mejora mucho BitNet y acelera bastante el cómputo

El poder del 0

  • ¿Por qué agregar 0 representa una mejora tan grande? Todo está relacionado con la multiplicación de matrices
  • Si se tienen pesos cuantizados a 1.58 bits, no solo se puede acelerar mucho el cómputo porque solo hay que realizar multiplicaciones, sino que también es posible filtrar características

Cuantización

  • Para realizar la cuantización de pesos, BitNet 1.58b usa cuantización absmean, una variante de la cuantización absmax que vimos antes
  • Simplemente comprime la distribución de pesos y usa la media absoluta (α) para cuantizar los valores, que luego se redondean a -1, 0 o 1
  • En comparación con BitNet, la cuantización de activaciones es igual salvo por una cosa. En lugar de ajustar las activaciones al rango [0, 2ᵇ⁻¹], ahora se usa cuantización absmax para ajustarlas a [-2ᵇ⁻¹, 2ᵇ⁻¹]
  • La cuantización de 1.58 bits requirió (principalmente) dos trucos:
    • agregar 0 para crear una representación ternaria [-1, 0, 1]
    • cuantización absmean para los pesos
  • “13B BitNet b1.58 es más eficiente que un LLM FP16 de 3B en términos de latencia, uso de memoria y consumo energético”

  • Por lo tanto, se pueden obtener modelos ligeros gracias a que solo se usa una cuantización de 1.58 bits computacionalmente eficiente

Aún no hay comentarios.

Aún no hay comentarios.