Modelos y plataformas de IA

El marco de inferencia de Microsoft lleva los modelos de lenguaje grande de 1 bit a los dispositivos locales

mm
AÃąade Unite.AI a tus fuentes preferidas en Google

El 17 de octubre de 2024, Microsoft anunciÃģ BitNet.cpp (MSFT ), un marco de inferencia diseÃąado para ejecutar modelos de lenguaje grande (LLM) cuantizados de 1 bit. BitNet.cpp es un progreso significativo en la inteligencia artificial generativa, que permite la implementaciÃģn eficiente de LLM de 1 bit en CPUs estÃĄndar, sin requerir GPUs costosas. Este desarrollo democratiza el acceso a los LLM, haciÃĐndolos disponibles en una amplia gama de dispositivos y brindando nuevas posibilidades en aplicaciones de inteligencia artificial en dispositivos.

Entendiendo los modelos de lenguaje grande de 1 bit

Los modelos de lenguaje grande (LLM) han requerido tradicionalmente recursos computacionales significativos debido a su uso de nÚmeros de punto flotante de alta precisiÃģn (típicamente FP16 o BF16) para los pesos del modelo. Esta necesidad ha hecho que la implementaciÃģn de LLM sea costosa y energÃĐticamente intensiva.

En su nÚcleo, los LLM de 1 bit utilizan tÃĐcnicas de cuantizaciÃģn extremas para representar los pesos del modelo utilizando solo tres valores posibles: -1, 0 y 1, de ahí el tÃĐrmino “1,58 bits” (ya que requiere ligeramente mÃĄs de un bit para codificar tres estados).

Sistema de peso ternario

El concepto

La cuantizaciÃģn de 1 bit en BitNet.cpp es un sistema de peso ternario. BitNet opera con solo tres valores posibles para cada parÃĄmetro:

  • -1 (negativo)
  • 0 (neutral)
  • 1 (positivo)

Esto resulta en un requisito de almacenamiento de alrededor de 1,58 bits por parÃĄmetro, de ahí el nombre BitNet b1.58. Esta reducciÃģn drÃĄstica en el ancho de bits de los parÃĄmetros conduce a una reducciÃģn impresionante en el uso de memoria y la complejidad computacional, ya que la mayoría de las multiplicaciones de punto flotante se reemplazan con simples sumas y restas.

Fundamento matemÃĄtico

La cuantizaciÃģn de 1 bit implica transformar los pesos y las activaciones en su representaciÃģn ternaria a travÃĐs de los siguientes pasos:

1. CuantizaciÃģn de pesos

La cuantizaciÃģn de los pesos implica centralizarlos alrededor de la media (Îą), lo que da como resultado una representaciÃģn ternaria. La transformaciÃģn se expresa matemÃĄticamente como:

Wf​=Sign(W−α)

Donde:

  • W es la matriz de pesos original.
  • Îą es la media de los pesos.
  • Sign(x) devuelve +1 si x > 0 y -1 de lo contrario.

2. CuantizaciÃģn de activaciones

La cuantizaciÃģn de las activaciones garantiza que las entradas estÃĐn limitadas a un ancho de bits especificado:

x^e​=Quant(x)=Clip(Îģx×Qb​​,−Qb​+Ïĩ,Qb​−Ïĩ)

Donde:

  • Qb = 2(b−1)2^{(b-1)} es el nivel de cuantizaciÃģn mÃĄximo para el ancho de bits b.
  • Îģ es el valor absoluto mÃĄximo de x (denotado como âˆĢâˆĢxâˆĢâˆĢ∞).
  • Îĩ es un nÚmero pequeÃąo para prevenir desbordamientos durante los cÃĄlculos.

3. OperaciÃģn BitLinear

La capa BitLinear reemplaza las multiplicaciones de matrices tradicionales con una operaciÃģn simplificada:

y=Wf​×x^e​×(Qb​ÎēÎģ​)

Donde:

  • Îē es un factor de escala utilizado para minimizar errores de aproximaciÃģn.
  • Îģ escala las activaciones.
  • Q_b es el factor de cuantizaciÃģn.

Esta transformaciÃģn permite cÃĄlculos eficientes mientras se mantiene el rendimiento del modelo.

Implicaciones de rendimiento

Eficiencia de memoria

El sistema de peso ternario reduce significativamente los requisitos de memoria:

  • LLM tradicionales: 16 bits por peso
  • BitNet.cpp: 1,58 bits por peso

Esta reducciÃģn se traduce en un ahorro de memoria del 90% aproximadamente en comparaciÃģn con los modelos de 16 bits tradicionales, lo que permite que los modelos mÃĄs grandes se ajusten dentro de las mismas restricciones de hardware.

Eficiencia energÃĐtica

Velocidad de inferencia, eficiencia energÃĐtica (Apple [securities_stock_price_tag symbol="AAPL" exchange="NASDAQ"] M2)

 

Velocidad de inferencia: mÃĄs rÃĄpida en ambas CPUs

Velocidad de inferencia, eficiencia energÃĐtica (i7-13700H)

1. Velocidad de inferencia: mÃĄs rÃĄpida en ambas CPUs

La velocidad de inferencia se representa como el nÚmero de tokens procesados por segundo. A continuaciÃģn, se muestra un desglose de las observaciones:

  • En Apple M2 Ultra: BitNet.cpp logra hasta 5,07 veces de velocidad para modelos mÃĄs grandes (30B) en comparaciÃģn con Llama.cpp, con una velocidad mÃĄxima de 593,43 tokens por segundo para un modelo de 125M, lo que es 1,37 veces mÃĄs rÃĄpido. Para modelos mÃĄs grandes como el 3,8B y el 7B, BitNet.cpp mantiene una velocidad superior a 84,77 tokens por segundo, demostrando su eficiencia en diferentes escalas.
  • En Intel (INTC ) i7-13700H: BitNet.cpp logra mejoras de velocidad aÚn mÃĄs dramÃĄticas. En el tamaÃąo de modelo de 7B, BitNet.cpp entrega una increíble velocidad 5,68 veces mayor en comparaciÃģn con Llama.cpp. Para modelos mÃĄs pequeÃąos como el 125M, procesa 389,08 tokens por segundo, lo que es 2,37 veces mÃĄs rÃĄpido que Llama.cpp.

2. Eficiencia energÃĐtica: un cambio de juego para dispositivos perifÃĐricos

Los grÃĄficos proporcionados tambiÃĐn incluyen comparaciones de costos energÃĐticos, lo que muestra una reducciÃģn significativa en el consumo de energía por token procesado:

  • En Apple M2 Ultra: Los ahorros de energía de BitNet.cpp son sustanciales. Para el modelo de 700M, consume 55,4% menos energía por token en comparaciÃģn con Llama.cpp, disminuyendo de 0,314 a 0,140. Esta tendencia continÚa para modelos mÃĄs grandes, con el modelo de 70B mostrando una reducciÃģn del 70,0% en el consumo de energía.
  • En Intel i7-13700H: BitNet.cpp entrega 71,9% de ahorro de energía para el modelo de 700M, con un consumo que disminuye de 1,367 a 0,384. Aunque los datos de energía para el modelo de 70B en Llama.cpp no estÃĄn disponibles, BitNet.cpp sigue siendo eficiente, con un consumo de energía de 17,33 para el modelo de 70B.

3. Superar el benchmark de velocidad de lectura humana

Una de las observaciones mÃĄs interesantes de estos grÃĄficos es la referencia a la velocidad de lectura humana, marcada en 5-7 tokens por segundo. Esta línea roja muestra que ambas implementaciones, especialmente BitNet.cpp, pueden superar cÃģmodamente las velocidades de lectura humanas incluso para los modelos mÃĄs grandes:

  • En Apple M2 Ultra, BitNet.cpp supera la velocidad de lectura humana para todos los tamaÃąos de modelo, con la velocidad mÃĄs baja siendo 8,67 tokens por segundo para un modelo de 70B.
  • En Intel i7-13700H, el modelo de 100B aÚn logra 1,70 tokens por segundo, casi tocando el rango inferior de la velocidad de lectura humana, mientras que todos los modelos mÃĄs pequeÃąos superan este benchmark.

Consideraciones de entrenamiento

Estimador de paso recto (STE)

Dado que la cuantizaciÃģn de 1 bit introduce funciones no diferenciables, el entrenamiento implica una tÃĐcnica especializada conocida como Estimador de paso recto (STE). En este enfoque, los gradientes fluyen sin alteraciÃģn a travÃĐs de puntos no diferenciables. A continuaciÃģn, se muestra una implementaciÃģn simplificada en Python:

class StraightThroughEstimator(Function):
@staticmethod
def forward(ctx, input):
return input.sign()

@staticmethod
def backward(ctx, grad_output):
return grad_output

Entrenamiento de precisiÃģn mixta

Para mantener la estabilidad durante el entrenamiento, se emplea precisiÃģn mixta:

  • Pesos y activaciones: Cuantizados a precisiÃģn de 1 bit.
  • Gradientes y estados del optimizador: Almacenados en una precisiÃģn mÃĄs alta.
  • Pesos latentes: Mantenidos en alta precisiÃģn para facilitar actualizaciones precisas durante el entrenamiento.

Estrategia de tasa de aprendizaje grande

Un desafío Único con los modelos de 1 bit es que las actualizaciones pequeÃąas pueden no afectar los pesos binarizados. Para mitigar esto, la tasa de aprendizaje se aumenta, lo que garantiza una convergencia mÃĄs rÃĄpida y una mejor optimizaciÃģn en comparaciÃģn con los enfoques tradicionales.

CuantizaciÃģn y normalizaciÃģn de grupo

BitNet.cpp introduce cuantizaciÃģn y normalizaciÃģn de grupo para mejorar el paralelismo del modelo. En lugar de calcular parÃĄmetros para la matriz de pesos completa, BitNet divide los pesos y las activaciones en mÚltiples grupos (G).
Esta agrupaciÃģn permite un procesamiento paralelo eficiente sin comunicaciÃģn adicional entre grupos, lo que permite el entrenamiento y la inferencia de modelos a gran escala.

Notas de implementaciÃģn y optimizaciones

OptimizaciÃģn de CPU

BitNet.cpp aprovecha varias optimizaciones de bajo nivel para lograr un rendimiento de CPU mÃĄximo:

  • Operaciones vectorizadas: Utiliza instrucciones SIMD para realizar manipulaciones de bits de manera eficiente.
  • Acceso a memoria amigable con la cachÃĐ: Estructura los datos para minimizar los errores de cachÃĐ.
  • Procesamiento paralelo: Distribuye la carga de trabajo de manera efectiva a travÃĐs de mÚltiples nÚcleos de CPU.

A continuaciÃģn, se muestra un ejemplo de una funciÃģn clave que implementa la cuantizaciÃģn y la inferencia en BitNet:

def bitlinear_forward(input, weight, scale):
# Cuantiza la entrada utilizando la cuantizaciÃģn de valor absoluto mÃĄximo
input_q = quantize(input)

# Realiza la multiplicaciÃģn de matrices binaria
output = binary_matmul(input_q, weight)

# Escala la salida para coincidir con la precisiÃģn original
return output * scale

def quantize(x):
# Realiza la cuantizaciÃģn de valor absoluto mÃĄximo
scale = torch.max(torch.abs(x))
return torch.clamp(x / scale, -1, 1) * scale

Modelos compatibles

La versiÃģn actual de BitNet.cpp admite los siguientes modelos de LLM de 1 bit disponibles en Hugging Face:

  • bitnet_b1_58-large (0,7 mil millones de parÃĄmetros)
  • bitnet_b1_58-3B (3,3 mil millones de parÃĄmetros)
  • Llama3-8B-1.58-100B-tokens (8,0 mil millones de parÃĄmetros)

Estos modelos estÃĄn disponibles pÚblicamente para demostrar las capacidades de inferencia del marco. Aunque no fueron entrenados ni lanzados oficialmente por Microsoft, ilustran la versatilidad del marco.

Guía de instalaciÃģn

Para comenzar con BitNet.cpp, siga los pasos a continuaciÃģn:

Requisitos previos

  1. Python >= 3.9
  2. CMake >= 3.22
  3. Clang >= 18
  4. Conda (altamente recomendado)

Para los usuarios de Windows, se debe instalar Visual Studio con los siguientes componentes habilitados:

  • Desarrollo de escritorio con C++
  • Herramientas de C++-CMake para Windows
  • Git para Windows
  • Compilador de C++-Clang para Windows
  • Soporte para MS-Build para el conjunto de herramientas de LLVM (Clang)

Para los usuarios de Debian/Ubuntu, hay un script de instalaciÃģn automÃĄtico disponible:

bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"

Pasos de instalaciÃģn

  1. Clonar el repositorio:
    git clone --recursive https://github.com/microsoft/BitNet.git

    cd BitNet
  2. Instalar dependencias:
    # Crear un nuevo entorno de Conda (recomendado)
    conda create -n bitnet-cpp python=3.9
    conda activate bitnet-cpp


    pip install -r requirements.txt
  3. Compilar y preparar el proyecto: Puede descargar un modelo directamente desde Hugging Face y convertirlo a un formato cuantizado:
    python setup_env.py --hf-repo HF1BitLLM/Llama3-8B-1.58-100B-tokens -q i2_s

    Alternativamente, puede descargar y convertir el modelo manualmente:

    huggingface-cli download HF1BitLLM/Llama3-8B-1.58-100B-tokens --local-dir models/Llama3-8B-1.58-100B-tokens

    python setup_env.py -md models/Llama3-8B-1.58-100B-tokens -q i2_s

Ejecutar la inferencia con BitNet.cpp

Para ejecutar la inferencia utilizando el marco, use el siguiente comando:

python run_inference.py -m models/Llama3-8B-1.58-100B-tokens/ggml-model-i2_s.gguf -p "Sandra viajÃģ a la cocina. ÂŋDÃģnde estÃĄ Sandra?" -n 6 -temp 0.7

ExplicaciÃģn:

  • -m especifica la ruta del archivo del modelo.
  • -p define el texto de la promociÃģn.
  • -n establece el nÚmero de tokens para predecir.
  • -temp ajusta la aleatoriedad de muestreo (temperatura) durante la inferencia.

Ejemplo de salida

Sandra viajÃģ a la cocina. ÂŋDÃģnde estÃĄ Sandra?

Respuesta: Sandra estÃĄ en la cocina.

Detalles tÃĐcnicos de BitNet.cpp

Capa BitLinear

BitNet.cpp implementa una arquitectura de transformador modificada, sustituyendo las multiplicaciones de matrices estÃĄndar con operaciones BitLinear. Este enfoque centraliza los pesos en cero antes de la cuantizaciÃģn y los escala para reducir los errores de aproximaciÃģn. La funciÃģn de transformaciÃģn clave se parece a esto:

# FunciÃģn de binarizaciÃģn para pesos de 1 bit
def binarize_weights(W):
alpha = W.mean()
W_binarized = np.sign(W - alpha)
return W_binarized

La combinaciÃģn de pesos centralizados y escalados garantiza que el error de cuantizaciÃģn permanece mínimo, preservando así el rendimiento.

Impacto en la industria

BitNet.cpp podría tener implicaciones de gran alcance para la implementaciÃģn de LLM:

  • Accesibilidad: Permite que los LLM se ejecuten en dispositivos estÃĄndar, democratizando el acceso a la inteligencia artificial potente.
  • Eficiencia de costo: Reduce la necesidad de GPUs costosas, lo que reduce la barrera para la adopciÃģn.
  • Eficiencia energÃĐtica: Ahorra energía al aprovechar la inferencia basada en CPU.
  • InnovaciÃģn: Abre nuevas posibilidades para la inteligencia artificial en dispositivos, como la traducciÃģn de lenguaje en tiempo real, asistentes de voz y aplicaciones enfocadas en la privacidad sin dependencia de la nube.

Desafíos y direcciones futuras

Aunque los LLM de 1 bit tienen un gran potencial, varios desafíos persisten. Estos incluyen el desarrollo de modelos de 1 bit robustos para diversas tareas, la optimizaciÃģn del hardware para cÃĄlculos de 1 bit y el fomento de la adopciÃģn de este nuevo paradigma por parte de los desarrolladores. AdemÃĄs, explorar la cuantizaciÃģn de 1 bit para tareas de visiÃģn por computadora o audio representa una emocionante direcciÃģn futura.

ConclusiÃģn

El lanzamiento de BitNet.cpp por parte de Microsoft es un avance significativo. Al permitir la inferencia eficiente de 1 bit en CPUs estÃĄndar, BitNet.cpp crea la accesibilidad y la sostenibilidad de la inteligencia artificial. Este marco senta las bases para LLM mÃĄs portÃĄtiles y rentables, empujando lo que es posible con la inteligencia artificial en dispositivos.

He dedicado los Últimos cinco aÃąos sumergiÃĐndome en el fascinante mundo de Machine Learning y Deep Learning. Mi pasiÃģn y experiencia me han llevado a contribuir a mÃĄs de 50 proyectos de ingeniería de software diversos, con un enfoque particular en AI/ML. Mi curiosidad en curso tambiÃĐn me ha llevado hacia el Procesamiento de Lenguaje Natural, un campo que estoy ansioso por explorar mÃĄs a fondo.