notícias

Milhares de palavras de informações técnicas! Um guia de quantificação de leitura obrigatória para engenheiros LLM, ilustrações visuais revelam como compactar modelos grandes

2024-07-31

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina


Novo Relatório de Sabedoria

Editor: Departamento Editorial

[Introdução à Nova Sabedoria] Diante da escala de parâmetros em expansão gradual do LLM, os desenvolvedores e pesquisadores sem o H100 criaram muitas maneiras de compensar isso, e a tecnologia de "quantificação" é uma delas. Este guia visual usa várias ilustrações para resumir de forma abrangente os conceitos básicos e métodos ramificados de "quantificação".

Os modelos de linguagem grande (LLMs) costumam ser grandes demais para serem executados em hardware de consumo. Esses modelos podem ter mais de bilhões de parâmetros e geralmente exigem GPUs com grande memória para acelerar o processo de inferência.

Portanto, mais e mais pesquisas começaram a se concentrar em como reduzir o modelo, como melhorar métodos de treinamento ou usar adaptadores. Uma das principais técnicas neste campo é chamada de quantização.

O engenheiro de ML Maarten Grootendorst escreveu uma postagem no blog que apresenta especificamente a tecnologia de quantificação no contexto da modelagem de linguagem e explora conceitos relacionados um por um por meio de métodos visuais para nos ajudar a construir uma compreensão intuitiva da tecnologia.


Nesta postagem do blog, Maarten explora vários métodos, casos de uso e os princípios por trás da quantificação.

O índice e o conteúdo do artigo são mostrados na figura abaixo. Ele apresenta principalmente os dois métodos de quantificação pós-treinamento (PTQ) e treinamento consciente de quantização (QAT). Recomenda-se que os leitores com conhecimento básico de IA saltem. diretamente para a parte de quantização simétrica:


Parte Um: O "Problema" do LLM

Os "modelos de linguagem grande" são grandes em termos de número de parâmetros do modelo, geralmente atingindo bilhões em escala (principalmente pesos).

Não só os custos de armazenamento destes parâmetros são bastante elevados, mas a quantidade de cálculo na fase de inferência também é grande.

Durante a inferência, o valor de ativação é o produto da entrada e do peso, portanto, quanto maior o número de pesos, maior será o valor de ativação.


Portanto, queremos representar bilhões de valores da forma mais eficiente possível, minimizando assim o espaço necessário para armazenar parâmetros.

Vamos começar do início e explorar como os valores são representados antes de otimizar.

Como representar valores numéricos

Os valores numéricos são geralmente armazenados como números de ponto flutuante (ou simplesmente flutuantes): um número positivo ou negativo com ponto decimal.

Esses valores são representados por dígitos binários em cada bit.

O padrão IEEE-754 descreve como os dígitos de cada dígito representam um valor específico. Especificamente, existem três mapeamentos: sinal, expoente ou decimal (mantissa).


Estas três partes podem ser combinadas para calcular o valor representado com base em um conjunto de valores de bits:


Quanto mais dígitos forem usados, mais preciso será o valor numérico. Por exemplo, o formulário FP32 pode ter precisão de mais dígitos após a vírgula decimal do que FP16:


limite de memória

Quanto mais dígitos disponíveis, não apenas mais preciso será o valor, mas também mais ampla será a gama de valores que podem ser representados.


Dado um número de bit e uma representação, o intervalo de valores que pode ser representado é chamado de intervalo dinâmico, e a distância entre dois valores adjacentes é chamada de precisão.


Uma característica interessante desta representação é que podemos calcular quanta memória o dispositivo requer para armazenar um determinado valor.

Como cada byte na memória contém 8 bits, podemos criar uma fórmula básica para a maioria das formas de números de ponto flutuante –


Em aplicações reais, há muitos outros fatores que afetam a quantidade de gráficos/memória necessária durante a inferência, como tamanho do contexto e arquitetura do modelo.

Agora imagine que temos um modelo com 70 bilhões de parâmetros. A maioria dos modelos é representada usando números de ponto flutuante de 32 bits (geralmente chamados de precisão total), o que requer 280 GB de memória para carregar o modelo.


Mas se todos os parâmetros puderem ser expressos como números de ponto flutuante de 16 bits, o tamanho da memória necessária poderá ser reduzido diretamente em uma vez.

Portanto, é muito atrativo minimizar o número de representações dos parâmetros do modelo (não apenas para inferência, mas também para treinamento).

No entanto, esta abordagem não é gratuita. A precisão do modelo normalmente diminui à medida que o número de bits de representação diminui, resultando em diminuição da precisão.

Queremos reduzir o número de dígitos usados ​​para representar um valor, mantendo a precisão... é aqui que as técnicas de quantização são úteis.

Parte 2: Introdução à Quantificação

Sabemos agora que o objetivo da quantização é reduzir a precisão dos parâmetros do modelo de larguras de bits mais altas (como números de ponto flutuante de 32 bits) para larguras de bits mais baixas (como números inteiros de 8 bits).


Ao reduzir o número de bits que representam os parâmetros originais, geralmente ocorre uma perda de alguma precisão (granularidade).

Para tornar esse efeito mais intuitivo, podemos usar as cores das fotos como analogia. Por exemplo, selecione qualquer imagem (esquerda), mas use apenas 8 cores (direita):


Observe que o cookie ampliado parece mais “granulado” que o original.

Da mesma forma, o principal objetivo da quantização é reduzir o número de bits (cores) necessários para representar os parâmetros originais, mantendo o máximo de precisão possível dos parâmetros originais.

Tipos de dados comuns

Primeiro, vamos examinar os tipos de dados comuns e o impacto de usá-los em vez da representação de 32 bits (chamada de precisão total ou FP32).

FP16

O primeiro é um exemplo de como passar de ponto flutuante de 32 bits para 16 bits (chamado de meia precisão ou FP16):


A faixa de valores possíveis para FP16 é muito menor que para FP32.

BF16

A fim de obter uma faixa numérica semelhante ao FP32 original, o bfloat 16 foi introduzido como um tipo "FP32 truncado":


O BF16 usa o mesmo número de bits que o FP16, mas adiciona um bit exponencial, para que possa obter uma faixa mais ampla de valores e é frequentemente usado na área de aprendizado profundo.

INT8

À medida que você reduz ainda mais o número de bits, a representação se torna mais próxima de um número inteiro em vez de um número de ponto flutuante. Por exemplo, indo de FP32 para INT8 que possui apenas 8 bits, apenas 1/4 do número original de bits:


Cada vez que o número de bits é reduzido, um mapeamento é realizado para “comprimir” a representação original do FP32 em menos bits.

Mas na operação real, não precisamos mapear todo o intervalo FP32 [-3.4e38, 3.4e38] em INT8. Precisamos apenas encontrar uma maneira de mapear o intervalo de dados dos parâmetros reais do modelo no INT8.

Os métodos comuns de compressão/mapeamento incluem quantização simétrica e quantização assimétrica, ambos mapeamentos lineares.

O que discutiremos a seguir é o método de quantização de FP32 a INT8.

Quantização simétrica

Na quantização simétrica, o intervalo do valor de ponto flutuante original é mapeado para um intervalo simétrico centrado em zero no espaço de quantização, com zero como o ponto médio do intervalo antes e depois da quantização.

Isto significa que o zero original no espaço de ponto flutuante é exatamente zero após ser mapeado para o espaço quantizado.


Um exemplo típico de quantização simétrica é a quantização de máximo absoluto (absmax).

Dada uma lista de valores, tomamos o maior valor absoluto (α) como o intervalo para realizar o mapeamento linear.


[-127, 127] representa o intervalo restrito e o intervalo irrestrito é [-128, 127], dependendo do método de quantização

Como este é um mapa linear centrado em zero, a fórmula é simples.

Primeiro calcule o(s) fator(es) de escala usando a seguinte fórmula:

- b é o número de bytes que queremos quantizar para (8)

- α é o maior valor absoluto

Em seguida, usamos s para quantizar a entrada x:


Conforme mostrado na figura acima, o valor absoluto máximo α é 10,8. Ao mapear FP32 para INT8, a seguinte fórmula é obtida:


Se desejar restaurar os valores originais do FP32, você também pode usar o(s) fator(es) de escala calculado(s) anteriormente para quantização inversa.


Primeiro quantize e depois desquantize para restaurar o valor original. Todo o processo é o seguinte:


Você pode ver que alguns valores, como 3,08 e 3,02, são ambos 36 quando quantizados em INT8. Portanto, quando desquantizados de volta ao FP32, eles perdem alguma precisão e não são mais distinguíveis.

Essa diferença entre o valor original e o valor quantizado inverso é chamada de erro de quantização. Geralmente, quanto menos bits o resultado da quantização tiver, maior será o erro.


quantização assimétrica

Ao contrário da quantização simétrica, a quantização assimétrica não é uma simetria centrada em zero. Em vez disso, ele mapeia os valores mínimo (β) e máximo (α) do intervalo de ponto flutuante para os valores mínimo e máximo do intervalo quantizado, respectivamente.

O método que exploramos aqui é chamado de quantização de ponto zero.


Observe como a posição de 0 mudou. É por isso que é chamada de quantização assimétrica. No intervalo [-7,59, 10,8], os valores máximo e mínimo estão em distâncias diferentes de 0.

Devido ao deslocamento da posição do ponto zero, temos que calcular o ponto zero na faixa INT8 para realizar o mapeamento linear. Como antes, também temos que calcular o(s) fator(es) de escala, mas usando a diferença no intervalo INT8 [-128, 127].


Isto é um pouco complicado porque o ponto zero (z) precisa ser calculado na faixa INT8 para mover os pesos.

Como antes, vamos preencher a fórmula:


Para desquantizar o valor quantizado de INT8 de volta para FP32, precisamos usar o(s) fator(es) de escala previamente calculado(s) e o ponto zero (z).

Caso contrário, a desquantização é simples:


Quando colocamos a quantização simétrica e assimétrica lado a lado, podemos ver rapidamente a diferença entre os dois métodos:


Na imagem acima, podemos ver a característica do centro zero da quantização simétrica e o deslocamento da quantização assimétrica.

Mapeamento e recorte de intervalo (Recorte)

No exemplo anterior, exploramos como mapear um intervalo de valores em um determinado vetor para uma representação de poucos bits. Embora isso possa mapear toda a gama de valores vetoriais, tem uma grande desvantagem, ou seja, valores discrepantes.

Imagine que você tem um vetor contendo os seguintes valores:


Um valor muito maior que todos os outros pode ser considerado um outlier. Se mapearmos todo o intervalo de vetores, todos os valores pequenos serão mapeados para a mesma representação de ordem inferior e perderão sua distinção:


Este é o método absmax usado antes.A mesma coisa acontece com a quantização assimétrica sem recorte

Em vez disso, podemos optar por recortar determinados valores. Recorte refere-se à definição de uma faixa dinâmica diferente dos valores originais para que todos os valores discrepantes sejam definidos com o mesmo valor.

No exemplo abaixo, definimos manualmente o intervalo dinâmico para [-5, 5], e todos os valores fora deste intervalo serão mapeados para -127 ou 127, independentemente do seu valor real:


A principal vantagem desta abordagem é que o erro de quantização para não-outliers é significativamente reduzido. No entanto, isso levará a um aumento no erro de quantização para valores discrepantes.

Calibração

No exemplo acima, definimos aleatoriamente a faixa dinâmica para [-5, 5], mas a decisão deve ser tomada por meio de um processo de “calibração” para encontrar uma faixa apropriada que englobe tantos valores quanto possível, minimizando o erro de quantização.

A execução específica das etapas de calibração é diferente para diferentes tipos de parâmetros.

Pesos (e preconceitos)

Podemos pensar nos pesos e tendências de um modelo de linguagem grande (LLM) como valores estáticos porque são conhecidos antes da execução do modelo. Por exemplo, o arquivo de aproximadamente 20 GB do Llama 3 consiste principalmente em seus pesos e tendências.

Como o número de variáveis ​​de viés (milhões) é significativamente menor que os pesos (bilhões), os vieses geralmente mantêm maior precisão (como INT16), enquanto o principal trabalho sobre quantização concentra-se nos pesos.

Para pesos estáticos conhecidos, as técnicas de calibração para selecionar a faixa incluem:

- Selecione manualmente os percentis do intervalo de entrada

- Otimizar o erro quadrático médio (MSE) entre pesos originais e pesos quantizados

- Minimizar a entropia entre o valor original e o valor quantizado (divergência KL)


A escolha de um percentil, por exemplo, resulta em um comportamento de recorte semelhante ao que vimos anteriormente.

valor de ativação

As entradas que são constantemente atualizadas em um grande modelo de linguagem são frequentemente chamadas de ativações.


Eles são chamados de valores de ativação porque geralmente passam por alguma função de ativação, como sigmóide ou relu.

Ao contrário dos pesos, as ativações mudam com os dados de entrada durante a inferência e são, portanto, difíceis de quantificar com precisão.

Como esses valores são atualizados após cada camada oculta, seus valores específicos não são conhecidos durante a fase de inferência até que os dados de entrada passem pelo modelo.


Em geral, existem dois métodos de calibração de pesos e ativações, aplicados em diferentes etapas do modelo:

- Quantização Pós-Treinamento (PTQ)

- Como o nome sugere, é quantificação após treino

- Treinamento Consciente de Quantização (QAT)

- Quantização durante o treinamento/ajuste

Parte 3: Quantificação pós-treinamento (PTQ)

A quantização pós-treinamento (PTQ) é uma das técnicas de quantização mais populares. Ele quantifica os parâmetros do modelo (incluindo pesos e valores de ativação) após a conclusão do treinamento do modelo.

A quantização de pesos pode usar quantização simétrica ou quantização assimétrica.

No entanto, a quantificação dos valores de ativação requer uma etapa de inferência para obter a sua distribuição subjacente, uma vez que não conhecemos antecipadamente o seu alcance.

Existem duas formas de quantização de valores de ativação:

- quantização dinâmica

- quantização estática

quantização dinâmica

Após os dados passarem pela camada oculta, seus valores de ativação são coletados e o valor máximo (α) e o valor mínimo (β) de cada camada são comparados:


A distribuição dessas ativações é então usada para calcular os valores do ponto zero (z) e do(s) fator(es) de escala necessários para a saída quantizada:


Este processo se repete cada vez que os dados passam por uma nova camada de rede. Portanto, cada camada possui seus próprios valores independentes de z e s, utilizando assim um esquema de quantização diferente.

quantização estática

Ao contrário da quantização dinâmica, a quantização estática não calcula o ponto zero (z) e o(s) fator(es) de escala durante a inferência, mas calcula esses valores antes da inferência.

Para encontrar esses valores, usamos um conjunto de dados de calibração e o alimentamos no modelo para coletar essas distribuições subjacentes de valores de ativação.


Uma vez coletadas essas distribuições, os valores s e z necessários para quantificação durante a inferência podem ser calculados.

No momento real da inferência, os valores s e z não são recalculados, mas usados ​​globalmente em todas as ativações para quantizá-los.

No geral, a quantização dinâmica, que calcula os valores s e z para cada camada oculta, tende a ser mais precisa. Entretanto, isso pode aumentar o tempo de cálculo, uma vez que esses valores precisam ser calculados a cada tempo de inferência.

Em contraste, a quantização estática, embora não seja tão precisa quanto a quantização dinâmica, é mais rápida porque já conhece antecipadamente os valores s e z usados ​​para quantização.

Campo quantitativo de 4 bits

A quantização abaixo de 8 bits sempre foi um desafio porque o erro de quantização aumenta com cada bit perdido. Felizmente, existem várias maneiras inteligentes de reduzir o número de bits para 6, 4 ou até 2 bits (embora geralmente não seja recomendado reduzir o número de bits abaixo de 4 bits).

Exploraremos dois métodos comuns no HuggingFace:

- GPTQ (modelo completo roda em GPU)

- GGUF (possivelmente descarrega camadas para a CPU)

GPTQ

Pode-se dizer que o GPTQ é um dos métodos de quantização de 4 bits mais famosos em aplicações práticas.

Ele usa quantização assimétrica e a processa camada por camada, processando cada camada independentemente antes de passar para a próxima camada:


Neste processo de quantização camada por camada, ele primeiro converte os pesos das camadas em matrizes Hessianas inversas. A matriz Hessiana inversa é a segunda derivada da função de perda do modelo e representa a sensibilidade da saída do modelo a cada mudança de peso.

Simplificando, mostra essencialmente a importância (importância inversa) dos pesos em cada camada.

Pesos de valores menores na matriz Hessiana são mais importantes porque pequenas mudanças nesses pesos podem levar a mudanças significativas no desempenho do modelo.


Na matriz Hessiana inversa, valores mais baixos representam pesos mais “importantes”

A seguir, quantizamos e desquantizamos a primeira linha da matriz de pesos:


Este processo nos permite calcular o erro de quantização (q), que podemos ponderar usando o valor hessiano inverso calculado anteriormente (h_1).

Essencialmente, estamos criando um erro quantizado ponderado com base na importância dos pesos:


A seguir, redistribuímos esse erro de quantização ponderado para os outros pesos da linha. Isso ajuda a manter a funcionalidade geral e a saída da rede.

Por exemplo, se fizermos isso para o segundo peso (ou seja, x_2 = 0,3), multiplicamos o erro de quantização (q) pelo inverso de Hessian do segundo peso (h_2) e adicionamos a ele:


A seguir, continue a mesma operação para o terceiro peso de uma determinada linha:


Este processo de redistribuição do erro de quantização ponderado q é repetido até que todos os valores tenham sido quantizados.

Este método funciona porque os pesos geralmente estão relacionados entre si. Portanto, quando um peso apresenta um erro de quantização, o peso relacionado será atualizado de acordo através do Hessiano inverso.

GGUF

Embora o GPTQ seja um bom método de quantização para executar todo o modelo de linguagem grande (LLM) na GPU, se não houver condições de hardware correspondentes, qualquer camada do LLM também pode ser descarregada para a CPU por meio do GGUF.

Equivale a rodar o modelo na CPU e GPU ao mesmo tempo para compensar a falta de memória de vídeo (VRAM).

O método de quantização GGUF é frequentemente atualizado e depende do número específico de bits de quantização, mas o princípio básico é o seguinte.

Primeiro, os pesos de uma determinada camada são divididos em “superblocos”, cada um dos quais contém um conjunto de “subblocos”. A partir desses "subblocos" calculamos o(s) fator(es) de escala e o valor alfa:


Para quantizar um determinado "subbloco", você pode usar a quantização absmax mencionada anteriormente, multiplicando o peso fornecido pelo fator de escala (s_sub):


O fator de escala s_sub é calculado usando as informações do "subbloco", mas quantizado usando as informações s_super do "superbloco":


Em resumo, esta quantização bloco a bloco utiliza o fator de escala do “super bloco” (s_super) para quantizar o fator de escala do “subbloco” (s_sub).

O nível de quantização de cada fator de escala pode ser diferente, e os fatores de escala de “superbloco” geralmente têm maior precisão do que os fatores de escala de “subbloco”.

Para ilustrar isso, vamos explorar vários níveis de quantização (2 bits, 4 bits e 6 bits):


Dependendo do tipo de quantização, um valor mínimo adicional (m) também é necessário para ajustar o ponto zero, estes são quantizados assim como o(s) fator(es) de escala

Parte 4: Treinamento de Conscientização Quantitativa (QAT)

A terceira parte descreve como quantizar o modelo após o treinamento. A desvantagem deste método é que ele não leva em consideração o processo de treinamento real.

É aqui que o Treinamento de Consciência Quantitativa (QAT) se torna útil. Ao contrário da quantificação pós-treinamento (PTQ), o objetivo do QAT é aprender o processo de quantização durante o treinamento.


O QAT tende a ser mais preciso que o PTQ porque a quantização já é levada em consideração durante o processo de treinamento. Veja como funciona:

Durante o processo de treinamento, é introduzida a chamada quantização "falsa". Por exemplo, primeiro quantize os pesos em INT4 e depois desquantize-os de volta para FP32:


Este processo permite que o modelo leve em consideração o erro de quantização no cálculo de perdas e atualização de pesos durante a fase de treinamento.

Conforme mostrado na figura abaixo, o QAT tenta explorar o valor da perda no caso de mínimos “amplos” para reduzir erros de quantização, porque mínimos “estreitos” geralmente levam a erros de quantização maiores.


Supondo que a quantização não seja considerada durante a retropropagação, o processo de descida gradiente selecionará o peso com o menor valor de perda. No entanto, se estiver num mínimo "estreito", isso introduzirá erros de quantização maiores.

Em contraste, se considerarmos a quantização, um peso de atualização diferente será escolhido nos mínimos "amplos", com um erro de quantização muito menor.


Portanto, embora o método PTQ tenha um baixo valor de perda com alta precisão (por exemplo, FP32), o QAT também tem um baixo valor de perda com baixa precisão (por exemplo, INT4), que é o que estamos buscando.

Era de 1 bit: BitNet

Vimos antes que reduzir a precisão da quantização para 4 bits já é muito pequeno, mas e se reduzíssemos ainda mais?

É aqui que entra o BitNet, ele representa os pesos de um modelo como um único bit, seja -1 ou 1, e faz isso injetando o processo de quantização diretamente na arquitetura do Transformer.

A arquitetura do Transformer é a base da maioria dos LLMs e consiste em cálculos envolvendo camadas lineares:


Essas camadas lineares são normalmente representadas com maior precisão, como FP16, e são onde a maioria dos pesos está localizada.

BitNet substitui essas camadas lineares por camadas BitLinear:


As camadas BitLinear funcionam da mesma forma que as camadas lineares normais, multiplicando os pesos pelos valores de ativação para calcular a saída.

Mas a diferença é que a camada BitLinear usa apenas 1 bit para representar o peso do modelo e usa INT8 para representar o valor de ativação:


Camadas BitLinear, como treinamento com reconhecimento de quantização (QAT), realizam uma espécie de quantização "falsa" durante o treinamento para analisar o efeito de quantização de pesos e ativações:


Vamos entender o BitLinear passo a passo.

quantificação de peso

Durante o treinamento, os pesos são armazenados como INT8 e então quantizados em 1 bit usando uma estratégia básica chamada função signum.

Essencialmente, ele move a distribuição de pesos para centralizar em 0 e, em seguida, atribui todos os valores menores que 0 a -1 e todos os valores maiores que 0 a 1:


Além disso, ele registra um valor β (valor absoluto médio), que usaremos posteriormente no processo de quantização inversa.

Quantização de Ativação

Para quantificar as ativações, o BitLinear habilita o método do valor máximo absoluto (absmax) para converter as ativações de FP16 para INT8, pois requerem multiplicação de matrizes (×) com maior precisão.


Além disso, registra um valor α (valor absoluto máximo), que utilizaremos posteriormente no processo de desquantização.

quantização inversa

Acompanhamos α (o valor absoluto máximo das ativações) e β (o valor absoluto médio dos pesos), o que nos ajudará a desquantizar as ativações de volta ao FP16.

As ativações de saída são redimensionadas usando {α, γ} para desquantizá-las com a precisão original:


Este processo é relativamente simples e permite que o modelo seja representado com apenas dois valores, -1 ou 1.

Com esta abordagem, os autores observaram que à medida que o tamanho do modelo aumenta, a diferença de desempenho entre o treinamento de 1 bit e o treinamento FP16 torna-se cada vez menor.

No entanto, isto só se aplica a modelos maiores (parâmetros >30B), a diferença entre modelos menores ainda é grande.

Todos os LLMs têm 1,58 bits

Para melhorar os problemas de escalabilidade mencionados anteriormente, o BitNet 1.58b foi introduzido.

Nesta nova abordagem, cada peso do modelo pode não apenas ser -1 ou 1, mas também assumir 0, tornando cada variável um ternário.

Curiosamente, apenas adicionar 0 é uma operação simples que melhora muito o BitNet e acelera o processo de cálculo.

0 potência

Por que adicionar 0 é uma melhoria significativa?

Isso tem a ver com multiplicação de matrizes!

Primeiro, vamos explorar o funcionamento básico da multiplicação de matrizes.

Ao calcular a saída, multiplicamos a matriz de pesos pelo vetor de entrada. Aqui está uma visualização da multiplicação da primeira linha da primeira camada da matriz de pesos:


Essa multiplicação envolve duas ações, multiplicar um único peso pela entrada e depois somar todos eles.

Em contraste, o BitNet 1.58b consegue evitar o ato de multiplicação, uma vez que os pesos de três valores dizem essencialmente o seguinte:

- 1: quero adicionar esse valor

- 0: não quero esse valor

- -1: quero subtrair esse valor

Portanto, se seus pesos forem quantizados em 1,58 bits, basta realizar a adição:


Isso não apenas acelera significativamente os cálculos, mas também permite a filtragem de recursos.

Definir um determinado peso como 0 equivale a ignorar a entrada, em vez de adicionar ou subtrair o valor de entrada como 1 bit.

Quantificar

Para realizar a quantização de peso, o BitNet 1.58b usa a quantização de valor absoluto médio (absmean), uma variante da quantização de valor absoluto máximo (absmax) que vimos antes.

Simplesmente comprime a distribuição dos pesos e utiliza a média absoluta (α) para quantificar os valores. Em seguida, arredonde-os para -1, 0 ou 1:


Comparada ao BitNet, a quantização de ativação é a mesma, exceto por um aspecto: em vez de dimensionar as ativações para o intervalo [0, 2ᵇ⁻¹], usamos o método de valor absoluto máximo para dimensionar para [-2ᵇ⁻¹, 2ᵇ⁻¹] .

Para resumir, a quantização de 1,58 bits envolve principalmente duas técnicas:

- Adicione 0 para criar uma representação de três valores [-1, 0, 1]

- Quantificação média absoluta dos pesos

O artigo da BitNet chega à seguinte conclusão: "13B BitNet b1.58 é mais eficiente que 3B FP16 LLM em termos de latência, uso de memória e consumo de energia."


Endereço do artigo: https://arxiv.org/abs/2402.17764

Com apenas 1,58 bits computacionalmente eficientes, obtemos um modelo leve.

Referências:

https://newsletter.maartengrootendorst.com/p/a-visual-guide-to-quantization