LLMs quantization

LLMs quantization LLMs quantization

Aviso: Este post foi traduzido para o português usando um modelo de tradução automática. Por favor, me avise se encontrar algum erro.

Os modelos de linguagem estão cada vez maiores, o que os torna cada vez mais custosos e caros de executar.

LLMs-size-evolution Llama-size-evolution

Por exemplo, o modelo Llama 3 400B, se seus parâmetros estiverem armazenados no formato FP32, cada parâmetro ocupa, portanto, 4 bytes, o que significa que apenas para armazenar o modelo são necessários 400*(10e9)*4 bytes = 1,6 TB de memória VRAM. Isso equivale a 20 GPUs com 80GB de memória VRAM cada, as quais, além disso, não são baratas.

Mas se deixarmos de lado modelos gigantes e nos focarmos em modelos de tamanhos mais comuns, por exemplo, 70B de parâmetros, apenas armazenar o modelo representa 70*(10e9)*4 bytes = 280 GB de memória VRAM, o que equivale a 4 GPUs de 80GB de memória VRAM cada uma.

Isso acontece porque armazenamos os pesos no formato FP32, ou seja, cada parâmetro ocupa 4 bytes. Mas o que acontece se conseguirmos que cada parâmetro ocupe menos bytes? Isso é chamado de quantização.

Por exemplo, se conseguirmos que um modelo de 70B de parâmetros ocupe meio byte por parâmetro, então precisaríamos apenas de 70*(10e9)*0.5 bytes = 35 GB de memória VRAM, o que equivale a 2 GPUs de 24GB de memória VRAM cada uma, as quais já podem ser consideradas GPUs de usuários normais.

Portanto, precisamos maneiras de poder reduzir o tamanho desses modelos. Existem três formas de fazer isso: a destilação, a poda e a quantização.

A destilação consiste em treinar um modelo menor a partir das saídas do maior. Isso significa que uma entrada é fornecida tanto ao modelo pequeno quanto ao grande, considerando-se que a saída correta é a do modelo grande, de modo que o treinamento do modelo pequeno é realizado de acordo com a saída do modelo grande. Mas isso requer ter armazenado o modelo grande, o que não é o que queremos ou podemos fazer.

A poda consiste em eliminar parâmetros do modelo, tornando-o cada vez menor. Este método se baseia na ideia de que os modelos de linguagem atuais estão sobredimensionados e apenas alguns poucos parâmetros são os que realmente contribuem com informações. Por isso, se conseguirmos eliminar os parâmetros que não fornecem informações, obteremos um modelo menor. Mas isso não é simples atualmente, porque não temos uma maneira de saber bem quais parâmetros são importantes e quais não são.

Por outro lado, a quantização consiste em reduzir o tamanho de cada um dos parâmetros do modelo. E é isso que vamos explicar neste post.

Formato dos parâmetroslink image 19

Os parâmetros dos pesos podem ser armazenados em vários tipos de formatos

numbers-representation

Originalmente, era usado o FP32 para armazenar os parâmetros, mas devido ao fato de começarmos a ficar sem memória para armazenar os modelos, passamos a usar o FP16, o que não dava resultados ruins.

No entanto, o problema do FP16 é que ele não alcança valores tão altos quanto o FP32, o que pode levar ao caso de overflow de valores, ou seja, ao realizar cálculos internos na rede, o resultado pode ser tão alto que não possa ser representado em FP16, gerando erros. Isso ocorre porque o modelo foi treinado em FP32, o que permite que todos os possíveis cálculos internos sejam realizados, mas ao passar para FP16 posteriormente para realizar inferências, alguns cálculos internos podem causar overflow.

Devido a esses erros de overflow, foram criados o TF32 e o BF16, os quais têm a mesma quantidade de bits de expoente, o que permite que eles alcancem valores tão altos quanto o FP32, mas com a vantagem de ocupar menos memória por terem menos bits. No entanto, ambos, por terem menos bits de mantissa, não podem representar números com tanta precisão quanto o FP32, o que pode resultar em erros de arredondamento, mas pelo menos não obteremos um erro ao executar a rede. O TF32 tem no total 19 bits, enquanto o BF16 tem 16 bits. Geralmente, usa-se mais o BF16 porque se economiza mais memória.

Históricamente existiram os formatos INT8 e UINT8, que podem representar números de -128 a 127 e de 0 a 255, respectivamente. Embora sejam formatos bons porque permitem economizar memória, já que cada parâmetro ocupa 1 byte em comparação aos 4 bytes do FP32, o problema que têm é que só podem representar um intervalo pequeno de números e, além disso, apenas inteiros, pelo que podem ocorrer os dois problemas vistos anteriormente: desbordamento e falta de precisão.

Para resolver o problema de que os formatos INT8 e UINT8 representam apenas números inteiros, foram criados os formatos FP8 e FP4, mas ainda não estão muito consolidados, nem possuem um formato muito padronizado.

Embora tenhamos meios de armazenar os parâmetros dos modelos em formatos menores, e embora consigamos resolver os problemas de overflow e arredondamento, temos outro problema, que é o fato de que nem todas as GPUs são capazes de representar todos os formatos. Isso ocorre porque esses problemas de memória são relativamente novos, de modo que as GPUs mais antigas não foram projetadas para resolver esses problemas e, portanto, não são capazes de representar todos os formatos.

GPUs-data-formating

Como último detalhe, como curiosidade, durante o treinamento dos modelos é utilizada a chamada precisão mista. Os pesos do modelo são armazenados no formato FP32, no entanto, o forward pass e o backward pass são realizados em FP16 para ser mais rápido. Os gradientes resultantes do backward pass são armazenados em FP16 e usados para modificar os valores FP32 dos pesos.

Tipos de quantizaçãolink image 20

Quantização de ponto zerolink image 21

Este é o tipo de quantização mais simples. Consiste em reduzir o intervalo de valores de maneira linear, o menor valor de FP32 corresponde ao menor valor do novo formato, o zero de FP32 corresponde ao zero do novo formato e o maior valor de FP32 corresponde ao maior valor do novo formato.

Por exemplo, se quisermos passar os números representados de -1 até 1 no formato UINT8, como os limites do UINT8 são -127 e 127, se quisermos representar o valor 0.3, o que fazemos é multiplicar 0.3 por 127, o que dá 38.1 e arredondá-lo para 38, que é o valor que seria armazenado no UINT8.

Se quisermos fazer o passo contrário, para converter 38 para o formato entre -1 e 1, o que fazemos é dividir 38 por 127, que dá 0.2992, que é aproximadamente 0.3, e podemos ver que temos um erro de 0.008

!quantization-zero-point

Quantização Afimlink image 22

Neste tipo de quantização, se tiver um array de valores em um formato e quiser passar para outro, primeiro divide-se o array inteiro pelo valor máximo do array e depois multiplica-se o array inteiro pelo valor máximo do novo formato.

quantization-affine

Por exemplo, na imagem acima temos o array

[1.2, -0.5, -4.3, 1.2, -3.1, 0.8, 2.4, 5.4]

Como seu valor máximo é 5.4, dividimos o array por esse valor e obtemos

[0.2222222222, -0.09259259259, -0.7962962963, 0.2222222222, -0.5740740741, 0.1481481481, 0.4444444444, 1]

Se agora multiplicarmos todos os valores por 127, que é o valor máximo de UINT8, obtemos

[28,22222222, -11,75925926, -101,1296296, 28,22222222, -72,90740741, 18,81481481, 56,44444444, 127]

Que, arredondando, seria

[28, -12, -101, 28, -73, 19, 56, 127]

Se quisermos realizar o passo inverso, teríamos que dividir o array resultante por 127, que daria

[0,2204724409, -0,09448818898, -0,7952755906, 0,2204724409, -0,5748031496, 0,1496062992, 0,4409448819, 1]

E multiplicar novamente por 5.4, com o que obteríamos

[1,190551181, -0.5102362205, -4.294488189, 1.190551181, -3.103937008, 0.8078740157, 2.381102362, 5.4]

Se compararmos com o array original, vemos que temos um erro

Momentos de quantizaçãolink image 23

Quantização pós-treinamentolink image 24

Como o nome sugere, a quantização ocorre após o treinamento. O modelo é treinado em FP32 e depois é quantizado para outro formato. Este método é o mais simples, mas pode levar a erros de precisão na quantização.

Quantização durante o treinamentolink image 25

Durante o treinamento, é realizado o forward pass no modelo original e em um modelo quantizado, e são observados os possíveis erros decorrentes da quantização para poder mitigá-los. Este processo torna o treinamento mais custoso, pois você precisa armazenar na memória o modelo original e o quantizado, e mais lento, pois você precisa realizar o forward pass em dois modelos.

Métodos de quantizaçãolink image 26

A seguir mostro os links para os posts onde explico cada um dos métodos, para que este post não fique muito longo

Continuar lendo

MCP: Guia Completa para Criar Servidores e Clientes MCP (Model Context Protocol) com FastMCP

MCP: Guia Completa para Criar Servidores e Clientes MCP (Model Context Protocol) com FastMCP

Aprenda o que é o Model Context Protocol (MCP), o padrão de código aberto desenvolvido pela Anthropic que revoluciona como os modelos de IA interagem com ferramentas externas. Nesta guia prática e detalhada, eu te levo passo a passo na criação de um servidor e cliente MCP do zero usando a biblioteca fastmcp. Você construirá um agente de IA "inteligente" com Claude Sonnet, capaz de interagir com a API do GitHub para consultar issues e informações de repositórios. Vamos cobrir desde conceitos básicos até recursos avançados como filtragem de ferramentas por tags, composição de servidores, recursos estáticos e plantillas dinâmicas (resource templates), geração de prompts e autenticação segura. Descubra como MCP pode padronizar e simplificar a integração de ferramentas em suas aplicações de IA, de forma análoga ao como o USB unificou periféricos!

Últimos posts -->

Você viu esses projetos?

Horeca chatbot

Horeca chatbot Horeca chatbot
Python
LangChain
PostgreSQL
PGVector
React
Kubernetes
Docker
GitHub Actions

Chatbot conversacional para cozinheiros de hotéis e restaurantes. Um cozinheiro, gerente de cozinha ou serviço de quarto de um hotel ou restaurante pode falar com o chatbot para obter informações sobre receitas e menus. Mas também implementa agentes, com os quais pode editar ou criar novas receitas ou menus

Naviground

Naviground Naviground

Subtify

Subtify Subtify
Python
Whisper
Spaces

Gerador de legendas para vídeos no idioma que você desejar. Além disso, coloca uma legenda de cor diferente para cada pessoa

Ver todos os projetos -->

Quer aplicar IA no seu projeto? Entre em contato!

Quer melhorar com essas dicas?

Últimos tips -->

Use isso localmente

Os espaços do Hugging Face nos permitem executar modelos com demos muito simples, mas e se a demo quebrar? Ou se o usuário a deletar? Por isso, criei contêineres docker com alguns espaços interessantes, para poder usá-los localmente, aconteça o que acontecer. Na verdade, se você clicar em qualquer botão de visualização de projeto, ele pode levá-lo a um espaço que não funciona.

Flow edit

Flow edit Flow edit

Edite imagens com este modelo de Flow. Baseado em SD3 ou FLUX, você pode editar qualquer imagem e gerar novas

FLUX.1-RealismLora

FLUX.1-RealismLora FLUX.1-RealismLora
Ver todos os contêineres -->

Quer aplicar IA no seu projeto? Entre em contato!

Você quer treinar seu modelo com esses datasets?

short-jokes-dataset

Dataset com piadas em inglês

opus100

Dataset com traduções de inglês para espanhol

netflix_titles

Dataset com filmes e séries da Netflix

Ver mais datasets -->