Connect with us

Estrutura de Inferência da Microsoft traz Modelos de Linguagem Grande de 1-Bit para Dispositivos Locais

Inteligência artificial

Estrutura de Inferência da Microsoft traz Modelos de Linguagem Grande de 1-Bit para Dispositivos Locais

mm
Understanding 1-bit LLMs and Microsoft's BitNet.cpp Framework

Em 17 de outubro de 2024, a Microsoft anunciou o BitNet.cpp, uma estrutura de inferência projetada para executar Modelos de Linguagem Grande (LLMs) quantizados em 1-bit. O BitNet.cpp é um progresso significativo na IA gerada, permitindo o deploy eficiente de LLMs de 1-bit em CPUs padrão, sem a necessidade de GPUs caras. Este desenvolvimento democratiza o acesso a LLMs, tornando-os disponíveis em uma ampla gama de dispositivos e oferecendo novas possibilidades em aplicações de IA em dispositivos.

Entendendo Modelos de Linguagem Grande de 1-Bit

Os Modelos de Linguagem Grande (LLMs) tradicionalmente exigem recursos computacionais significativos devido ao uso de números de ponto flutuante de alta precisão (tipicamente FP16 ou BF16) para os pesos do modelo. Essa necessidade tornou o deploy de LLMs caro e intensivo em energia.

Em seu núcleo, os LLMs de 1-bit usam técnicas de quantização extremas para representar os pesos do modelo usando apenas três valores possíveis: -1, 0 e 1, daí o termo “1,58-bit” (pois requer ligeiramente mais de um bit para codificar três estados).

Sistema de Peso Ternário

O Conceito

A quantização de 1-bit no BitNet.cpp é um sistema de peso ternário. O BitNet opera com apenas três valores possíveis para cada parâmetro:

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

Isso resulta em uma exigência de armazenamento de cerca de 1,58 bits por parâmetro, daí o nome BitNet b1.58. Essa redução drástica na largura de bit do parâmetro leva a uma redução impressionante no uso de memória e complexidade computacional, pois a maioria das multiplicações de ponto flutuante é substituída por simples adições e subtrações.

Fundamentação Matemática

A quantização de 1-bit envolve transformar pesos e ativações em sua representação ternária por meio dos seguintes passos:

1. Binarização de Pesos

Binarizar os pesos envolve centralizá-los em torno da média (α), resultando em uma representação ternária. A transformação é expressa matematicamente como:

Wf=Sign(Wα)

Onde:

  • W é a matriz de pesos original.
  • α é a média dos pesos.
  • Sign(x) retorna +1 se x > 0 e -1 caso contrário.

2. Quantização de Ativações

Quantizar ativações garante que as entradas sejam limitadas a uma largura de bit especificada:

Onde:

  • Qb = 2(b−1)2^{(b-1)} é o nível de quantização máximo para a largura de bit b.
  • γ é o valor absoluto máximo de x (denotado como ∣∣x∣∣∞).
  • ε é um número pequeno para evitar overflow durante os cálculos.

3. Operação BitLinear

A camada BitLinear substitui as multiplicações matriciais tradicionais por uma operação simplificada:

y=Wf×x^e×(Qbβγ)

Onde:

  • β é um fator de escala usado para minimizar erros de aproximação.
  • γ escala as ativações.
  • Q_b é o fator de quantização.

Essa transformação permite cálculos eficientes enquanto preserva o desempenho do modelo.

Implicações de Desempenho

Eficiência de Memória

O sistema de peso ternário reduz significativamente as exigências de memória:

  • LLMs Tradicionais: 16 bits por peso
  • BitNet.cpp: 1,58 bits por peso

Essa redução se traduz em uma economia de memória de aproximadamente 90% em comparação com os modelos tradicionais de 16 bits, permitindo que modelos maiores sejam acomodados dentro das mesmas restrições de hardware.

Eficiência Energética

Velocidade de Inferência, Eficiência Energética (Apple M2)

 

Velocidade de Inferência: Mais Rápido em Ambas as CPUs

Velocidade de Inferência, Eficiência Energética (i7-13700H)

1. Velocidade de Inferência: Mais Rápido em Ambas as CPUs

A velocidade de inferência é representada como o número de tokens processados por segundo. Aqui está uma quebra das observações:

  • No Apple M2 Ultra: O BitNet.cpp alcança até 5,07x de aumento de velocidade para modelos maiores (30B) em comparação com o Llama.cpp, com um pico de velocidade de 593,43 tokens por segundo para um modelo de 125M, o que é um 1,37x de aumento de velocidade. Para modelos maiores, como o 3,8B e o 7B, o BitNet.cpp mantém uma velocidade acima de 84,77 tokens por segundo, mostrando sua eficiência em diferentes escalas.
  • No Intel i7-13700H: O BitNet.cpp alcança melhorias de velocidade ainda mais dramáticas. No tamanho do modelo de 7B, o BitNet.cpp entrega um aumento de velocidade incrível de 5,68x em comparação com o Llama.cpp. Para modelos menores, como o 125M, processa 389,08 tokens por segundo, o que é 2,37x mais rápido que o Llama.cpp.

2. Eficiência Energética: Um Fator-Chave para Dispositivos de Borda

Os gráficos fornecidos também incluem comparações de custo energético, que mostram uma redução significativa no consumo de energia por token processado:

  • No Apple M2 Ultra: As economias de energia do BitNet.cpp são substanciais. Para o modelo de 700M, consome 55,4% menos energia por token em comparação com o Llama.cpp, caindo de 0,314 para 0,140. Essa tendência continua para modelos maiores, com o modelo de 70B mostrando uma redução de 70,0% no consumo de energia.
  • No Intel i7-13700H: O BitNet.cpp entrega 71,9% de economia de energia para o modelo de 700M, com o consumo caindo de 1,367 para 0,384. Embora os dados de energia para o modelo de 70B no Llama.cpp não estejam disponíveis, o BitNet.cpp permanece eficiente, com um consumo de energia de 17,33 para o modelo de 70B.

3. Ultrapassando a Barreira de Velocidade de Leitura Humana

Uma das informações mais interessantes desses gráficos é a referência à velocidade de leitura humana, marcada em 5-7 tokens por segundo. Essa linha vermelha mostra que ambas as implementações, especialmente o BitNet.cpp, podem facilmente ultrapassar as velocidades de leitura humanas mesmo para os modelos maiores:

  • No Apple M2 Ultra, o BitNet.cpp ultrapassa a velocidade de leitura humana para todos os tamanhos de modelo, com a velocidade mais baixa sendo 8,67 tokens por segundo para um modelo de 70B.
  • No Intel i7-13700H, o modelo de 100B ainda alcança 1,70 tokens por segundo, quase alcançando a faixa inferior da velocidade de leitura humana, enquanto todos os modelos menores ultrapassam essa barreira.

Considerações de Treinamento

Estimador Direto (STE)

Como a quantização de 1-bit introduz funções não diferenciáveis, o treinamento envolve uma técnica especializada conhecida como Estimador Direto (STE). Nessa abordagem, os gradientes fluem inalterados através de pontos não diferenciáveis. Aqui está uma implementação simplificada em Python:

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

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

Treinamento de Precisão Mista

Para manter a estabilidade durante o treinamento, precisão mista é empregada:

  • Pesos e Ativações: Quantizados para precisão de 1 bit.
  • Gradientes e Estados do Otimizador: Armazenados em precisão mais alta.
  • Pesos Latentes: Mantidos em alta precisão para facilitar atualizações precisas durante o treinamento.

Estratégia de Taxa de Aprendizado Grande

Um desafio único com modelos de 1 bit é que atualizações pequenas podem não afetar os pesos binarizados. Para mitigar isso, a taxa de aprendizado é aumentada, garantindo convergência mais rápida e melhor otimização em comparação com abordagens tradicionais.

Quantização e Normalização de Grupo

O BitNet.cpp introduz Quantização e Normalização de Grupo para melhorar o paralelismo do modelo. Em vez de calcular parâmetros para a matriz de pesos inteira, o BitNet divide os pesos e ativações em vários grupos (G).

Isso permite processamento paralelo eficiente sem comunicação adicional entre grupos, permitindo treinamento e inferência de modelos em grande escala.

Notas de Implementação e Otimizações

Otimização de CPU

O BitNet.cpp aproveita várias otimizações de baixo nível para alcançar o desempenho máximo da CPU:

  • Operações Vetorizadas: Utiliza instruções SIMD para realizar manipulações de bits de forma eficiente.
  • Acesso à Memória Amigável ao Cache: Estrutura os dados para minimizar perdas de cache.
  • Processamento Paralelo: Distribui a carga de trabalho efetivamente em vários núcleos de CPU.

Aqui está um exemplo de uma função-chave que implementa quantização e inferência no BitNet:

def bitlinear_forward(input, weight, scale):
# Quantize a entrada usando quantização absmax
input_q = quantize(input)

# Realiza multiplicação matricial binária
output = binary_matmul(input_q, weight)

# Escala a saída para corresponder à precisão original
return output * scale

def quantize(x):
# Realiza quantização absmax
scale = torch.max(torch.abs(x))
return torch.clamp(x / scale, -1, 1) * scale

Modelos Suportados

A versão atual do BitNet.cpp suporta os seguintes LLMs de 1 bit disponíveis no Hugging Face:

  • bitnet_b1_58-large (0,7B parâmetros)
  • bitnet_b1_58-3B (3,3B parâmetros)
  • Llama3-8B-1.58-100B-tokens (8,0B parâmetros)

Esses modelos estão disponíveis publicamente para demonstrar as capacidades de inferência da estrutura. Embora não sejam treinados ou lançados oficialmente pela Microsoft, eles ilustram a versatilidade da estrutura.

Guia de Instalação

Para começar a usar o BitNet.cpp, siga os passos abaixo:

Pré-requisitos

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

Para usuários Windows, o Visual Studio deve ser instalado com os seguintes componentes habilitados:

  • Desenvolvimento de Desktop com C++
  • Ferramentas C++-CMake para Windows
  • Git para Windows
  • Compilador C++-Clang para Windows
  • Suporte ao MS-Build para Conjunto de Ferramentas LLVM (Clang)

Para usuários Debian/Ubuntu, um script de instalação automática está disponível:

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

Instalação Passo a Passo

  1. Clone o Repositório:
    git clone --recursive https://github.com/microsoft/BitNet.git

    cd BitNet
  2. Instale as Dependências:
    # Crie um novo ambiente Conda (recomendado)
    conda create -n bitnet-cpp python=3.9
    conda activate bitnet-cpp


    pip install -r requirements.txt
  3. Construa e Prepare o Projeto: Você pode baixar um modelo diretamente do Hugging Face e convertê-lo para um formato quantizado:
    python setup_env.py --hf-repo HF1BitLLM/Llama3-8B-1.58-100B-tokens -q i2_s

    Alternativamente, baixe e converta o 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

Executando Inferência com o BitNet.cpp

Para executar a inferência usando a estrutura, use o seguinte comando:

python run_inference.py -m models/Llama3-8B-1.58-100B-tokens/ggml-model-i2_s.gguf -p "Sandra viajou para a cozinha. Onde está Sandra?" -n 6 -temp 0.7

Explicação:

  • -m especifica o caminho do arquivo do modelo.
  • -p define o texto do prompt.
  • -n define o número de tokens para prever.
  • -temp ajusta a aleatoriedade da amostragem (temperatura) durante a inferência.

Exemplo de Saída

Sandra viajou para a cozinha. Onde está Sandra?

Resposta: Sandra está na cozinha.

Detalhes Técnicos do BitNet.cpp

Camada BitLinear

O BitNet.cpp implementa uma arquitetura Transformer modificada, substituindo multiplicações matriciais padrão por operações BitLinear. Essa abordagem centraliza os pesos em zero antes da quantização e os escala para reduzir erros de aproximação. A função de transformação-chave parece com isso:


# Função de binarização para pesos de 1 bit
def binarize_weights(W):
alpha = W.mean()
W_binarized = np.sign(W - alpha)
return W_binarized

A combinação de pesos centralizados e escalonamento garante que o erro de quantização permaneça mínimo, preservando assim o desempenho do modelo.

Impacto na Indústria

O BitNet.cpp pode ter implicações de longo alcance para o deploy de LLMs:

  • Acessibilidade: Permite que LLMs sejam executados em dispositivos padrão, democratizando o acesso a IA poderosa.
  • Eficiência de Custo: Reduz a necessidade de GPUs caras, diminuindo a barreira para adoção.
  • Eficiência Energética: Economiza energia ao aproveitar a inferência baseada em CPU.
  • Inovação: Abre novas possibilidades para IA em dispositivos, como tradução de linguagem em tempo real, assistentes de voz e aplicações focadas na privacidade sem dependência de nuvem.

Desafios e Direções Futuras

Embora os LLMs de 1 bit tenham potencial, vários desafios permanecem. Esses incluem o desenvolvimento de modelos de 1 bit robustos para tarefas diversas, otimização de hardware para computação de 1 bit e encorajamento de desenvolvedores a adotar esse novo paradigma. Além disso, explorar a quantização de 1 bit para tarefas de visão computacional ou áudio representa uma direção futura emocionante.

Conclusão

O lançamento do BitNet.cpp pela Microsoft é um avanço significativo. Ao permitir inferência eficiente de 1 bit em CPUs padrão, o BitNet.cpp cria acessibilidade e sustentabilidade para a IA. Essa estrutura define o palco para LLMs mais portáteis e economicamente viáveis, empurrando os limites do que é possível com a IA em dispositivos.

Eu passei os últimos cinco anos me imergindo no fascinante mundo de Aprendizado de Máquina e Aprendizado Profundo. Minha paixão e especialização me levaram a contribuir para mais de 50 projetos diversificados de engenharia de software, com um foco particular em IA/ML. Minha curiosidade contínua também me atraiu para o Processamento de Linguagem Natural, um campo que estou ansioso para explorar mais.