GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers

GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers

GPTQ: Quantização pós-treinamento precisa para transformadores pré-treinados generativoslink image 44

No artigo GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers, é exposta a necessidade de criar um método de quantização pós-treinamento que não prejudique a qualidade do modelo. Nesta postagem, vimos o método llm.int8() que quantiza para INT8 alguns vetores das matrizes de peso, desde que nenhum de seus valores exceda um valor limite, o que é bom, mas eles não quantizam todos os pesos do modelo. Neste artigo, eles propõem um método que quantiza todos os pesos do modelo para 4 e 3 bits, sem degradar a qualidade do modelo. Isso economiza bastante memória, não só porque todos os pesos são quantizados, mas também porque isso é feito em 4, 3 bits (e até mesmo 1 e 2 bits sob certas condições), em vez de 8 bits.

Este caderno foi traduzido automaticamente para torná-lo acessível a mais pessoas, por favor me avise se você vir algum erro de digitação..

Trabalhos nos quais se baseialink image 45

Quantificação em camadaslink image 46

Por um lado, eles se baseiam nos trabalhos Nagel et al., 2020; Wang et al., 2020; Hubara et al., 2021 e Frantar et al., 2022, que propõem quantizar os pesos das camadas de uma rede neural para 4 e 3 bits, sem degradar a qualidade do modelo.

Dado um conjunto de dados m de um conjunto de dados, cada camada l é alimentada com os dados e a saída dos pesos W dessa camada é obtida. Portanto, o que você faz é procurar novos pesos quantizados Ŵ que minimizem o erro quadrático em relação à saída da camada de precisão total.

argmin_Ŵ||WX- ŴX||^2.

Os valores de Ŵ são definidos antes da execução do processo de quantização e, durante o processo, cada parâmetro de Ŵ pode mudar de valor independentemente, sem depender do valor dos outros parâmetros de Ŵ.

Quantização ideal do cérebro (OBQ)link image 47

No trabalho OBQ de Frantar et al., 2022, eles otimizam o processo de quantização em camadas acima, tornando-o até três vezes mais rápido. Isso ajuda com modelos grandes, pois a quantização de um modelo grande pode levar muito tempo.

O método OBQ é uma abordagem para resolver o problema de quantização em camadas em modelos de linguagem. O OBQ parte da ideia de que o erro quadrático pode ser decomposto na soma de erros individuais para cada linha da matriz de peso. O método quantifica cada peso de forma independente, sempre atualizando os pesos não quantificados para compensar o erro incorrido pela quantização.

O método é capaz de quantificar modelos de tamanho médio em tempos razoáveis, mas, como é um algoritmo de complexidade cúbica, é extremamente caro para ser aplicado a modelos com bilhões de parâmetros.

Algoritmo GPTQlink image 48

Etapa 1: informações arbitrárias do pedidolink image 49

No OBQ, eles procuraram a linha de pesos que criava o menor erro quadrático médio para quantificar, mas perceberam que fazer isso aleatoriamente não aumentava muito o erro quadrático médio final. Assim, em vez de procurar a linha que minimizasse o erro quadrático médio, o que criava uma complexidade cúbica no algoritmo, isso é feito sempre na mesma ordem. Isso reduz bastante o tempo de execução do algoritmo de quantização.

Etapa 2: atualizações em lote preguiçosaslink image 50

Como a atualização dos pesos é feita linha por linha, isso torna o processo lento e não utiliza totalmente o hardware. Portanto, eles propõem executar as atualizações em lotes de B=128 linhas. Isso faz melhor uso do hardware e reduz o tempo de execução do algoritmo.

Etapa 3: Reformulação de Choleskylink image 51

O problema com as atualizações em lote é que, devido à grande escala dos modelos, podem ocorrer erros numéricos que afetam a precisão do algoritmo. Em particular, matrizes indefinidas podem ser obtidas, fazendo com que o algoritmo atualize os pesos restantes nas direções erradas, resultando em uma quantização muito ruim.

Para resolver isso, os autores do artigo propõem o uso de uma reformulação Cholesky, que é um método numericamente mais estável.

Resultados do GPTQlink image 52

Abaixo estão dois gráficos com a medida de perplexidade no conjunto de dados WikiText2 para todos os tamanhos dos modelos OPT e BLOOM. É possível observar que, com a técnica de quantização RTN, a perplexidade em alguns tamanhos aumenta muito, enquanto com o GPTQ ela permanece semelhante à obtida com o modelo FP16.

GPTQ-figure1

Outros gráficos são mostrados abaixo, mas com a medida de precisão no conjunto de dados LAMBADA. É a mesma coisa, enquanto o GPTQ permanece semelhante ao obtido com o FP16, outros métodos de quantização degradam muito a qualidade do modelo.

GPTQ-figure3

Quantificação extremalink image 53

Os gráficos anteriores mostraram os resultados da quantização do modelo em 3 e 4 bits, mas podemos quantizá-los em 2 bits ou até mesmo em 1 bit.

Modificando o tamanho dos lotes ao usar o algoritmo, podemos obter bons resultados quantificando tanto o modelo quanto os lotes.

Modelo FP16 g128 g64 g32 3 bits
OPT-175B 8,34 9,58 9,18 8,94 8,68
BLOOM 8,11 9,55 9,17 8,83 8,64

Na tabela acima, você pode ver o resultado da perplexidade no conjunto de dados WikiText2 para os modelos OPT-175B e BLOOM quantizados em 3 bits. É possível observar que, à medida que lotes menores são usados, a perplexidade diminui, o que significa que a qualidade do modelo quantizado é melhor. Mas o problema é que o algoritmo leva mais tempo para ser executado.

Desconto dinâmico na inferêncialink image 54

Durante a inferência, algo chamado "dequantização dinâmica" é executado para realizar a inferência. Cada camada é dequantificada à medida que passa por ela.

Para fazer isso, eles desenvolveram um kernel que desquantifica as matrizes e executa produtos de matrizes. Embora a descompactação seja mais intensiva em termos de computação, o kernel precisa acessar muito menos memória, o que resulta em um aumento significativo da velocidade.

A inferência é realizada no FP16, descontando os pesos à medida que você passa pelas camadas, e a função de ativação de cada camada também é realizada no FP16. Embora isso signifique que mais cálculos tenham de ser feitos, porque os pesos têm de ser descontados, esses cálculos tornam o processo geral mais rápido, porque menos dados têm de ser buscados na memória. Os pesos precisam ser obtidos da memória em menos bits, portanto, no final, em matrizes com muitos parâmetros, isso economiza muitos dados. O gargalo geralmente está na obtenção dos dados da memória, portanto, mesmo que você tenha que fazer mais cálculos, no final a inferência é mais rápida.

Velocidade de inferêncialink image 55

Os autores do artigo testaram a quantização do modelo BLOOM-175B para 3 bits, o que ocupou cerca de 63 GB de memória VRAM, incluindo embeddings e a camada de saída que são mantidos em FP16. Além disso, a manutenção da janela de contexto de 2048 tokens consome cerca de 9 GB de memória, em um total de cerca de 72 GB de memória VRAM. Eles quantizaram em 3 bits e não em 4 bits para poder realizar esse experimento e ajustar o modelo em uma única GPU Nvidia A100 com 80 GB de memória VRAM.

Para fins de comparação, a inferência FP16 normal requer cerca de 350 GB de VRAM, o que equivale a 5 GPUs Nvidia A100 com 80 GB de VRAM. E a inferência quantizada de 8 bits usando llm.int8() requer 3 dessas GPUs.

Abaixo está uma tabela com inferência de modelo em FP16 e 3 bits quantizados em GPUs Nvidia A100 com 80 GB de VRAM e GPUs Nvidia A6000 com 48 GB de VRAM.

GPU (VRAM) Tempo médio por token em FP16 (ms) Tempo médio por token em 3 bits (ms) Aceleração Redução das GPUs necessárias
A6000 (48GB) 589 130 ×4.53 8→ 2
A100 (80GB) 230 71 ×3.24 5→ 1

Por exemplo, usando os kernels, o modelo OPT-175B de 3 bits é executado em um único A100 (em vez de 5) e é aproximadamente 3,25 vezes mais rápido do que a versão FP16 em termos de tempo médio por token.

A GPU NVIDIA A6000 tem uma largura de banda de memória muito menor, o que torna essa estratégia ainda mais eficaz: a execução do modelo OPT-175B de 3 bits em 2 GPUs A6000 (em vez de 8) é aproximadamente 4,53 vezes mais rápida do que a versão FP16.

Livrariaslink image 56

Os autores do artigo implementaram a biblioteca GPTQ. Outras bibliotecas foram criadas, como GPTQ-for-LLaMa, exllama e llama.cpp. No entanto, essas bibliotecas se concentram apenas na arquitetura llama, de modo que a biblioteca AutoGPTQ ganhou mais popularidade porque tem uma cobertura mais ampla de arquiteturas.

Por esse motivo, essa biblioteca AutoGPTQ foi integrada por meio de uma API na biblioteca transformers. Para usá-la, é necessário instalá-la conforme indicado na seção Installation de seu repositório e ter a biblioteca optimun instalada.

Além da seção Installation do seu repositório, você também deve fazer o seguinte:

git clone https://github.com/PanQiWei/AutoGPTQ
      cd AutoGPTQ
      pip install .
      ```
      
      Para que os kernels de quantização da GPU desenvolvidos pelos autores do artigo sejam instalados.
      

Quantização de um modelolink image 57

Vamos ver como quantificar um modelo com a biblioteca optimun e a API AutoGPTQ.

Inferência de modelo não quantificadalink image 58

Vamos quantificar o modelo meta-call/Meta-Call-3-8B-Instruct que, como o nome indica, é um modelo de 8B parâmetros, portanto, no FP16, precisaríamos de 16 GB de memória VRAM. Primeiro, executamos o modelo para ver quanta memória ele ocupa e a saída que ele gera

Como para usar esse modelo temos que pedir permissão ao Meta, entramos no HuggingFace para baixar o tokenizador e o modelo.

	
from huggingface_hub import notebook_login
notebook_login()
Copy

Instanciamos o tokenizador e o modelo

	
from huggingface_hub import notebook_login
notebook_login()
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
checkpoint = "meta-llama/Meta-Llama-3-8B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForCausalLM.from_pretrained(checkpoint).half().to(device)
Copy

Vamos ver a quantidade de memória que o FP16 ocupa.

	
from huggingface_hub import notebook_login
notebook_login()
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
checkpoint = "meta-llama/Meta-Llama-3-8B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForCausalLM.from_pretrained(checkpoint).half().to(device)
model_memory = model.get_memory_footprint()/(1024**3)
print(f"Model memory: {model_memory:.2f} GB")
Copy
	
Model memory: 14.96 GB

Vemos que ele ocupa quase 15 GB, mais ou menos os 16 GB que dissemos que deveria ocupar, mas por que essa diferença? Certamente esse modelo não tem exatamente 8B de parâmetros, mas tem um pouco menos, mas ao indicar o número de parâmetros, ele é arredondado para 8B.

Fazemos uma inferência para ver como ele faz isso e quanto tempo leva.

import time
      
      input_tokens = tokenizer("Hello my name is Maximo and I am a Machine Learning Engineer", return_tensors="pt").to(model.device)
      
      t0 = time.time()
      max_new_tokens = 50
      outputs = model.generate(
          input_ids=input_tokens.input_ids,
          attention_mask=input_tokens.attention_mask,
          max_length=input_tokens.input_ids.shape[1] + max_new_tokens,
      )
      print(tokenizer.decode(outputs[0], skip_special_tokens=True))
      print(f"Inference time: {time.time() - t0:.2f} s")
      
Setting `pad_token_id` to `eos_token_id`:128001 for open-end generation.
      
Hello my name is Maximo and I am a Machine Learning Engineer at a startup in the Bay Area. I am passionate about building AI systems that can help humans make better decisions and improve their lives.
      
      I have a background in computer science and mathematics, and I have been working with machine learning for several years. I
      Inference time: 4.14 s
      

Quantização do modelo para 4 bitslink image 59

Vamos quantificar isso em 4 bits. Reinicio o notebook para evitar problemas de memória, então entramos no Hugging Face novamente.

	
import time
input_tokens = tokenizer("Hello my name is Maximo and I am a Machine Learning Engineer", return_tensors="pt").to(model.device)
t0 = time.time()
max_new_tokens = 50
outputs = model.generate(
input_ids=input_tokens.input_ids,
attention_mask=input_tokens.attention_mask,
max_length=input_tokens.input_ids.shape[1] + max_new_tokens,
)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
print(f"Inference time: {time.time() - t0:.2f} s")
from huggingface_hub import notebook_login
notebook_login()
Copy

Primeiro, crio o tokenizador

	
import time
input_tokens = tokenizer("Hello my name is Maximo and I am a Machine Learning Engineer", return_tensors="pt").to(model.device)
t0 = time.time()
max_new_tokens = 50
outputs = model.generate(
input_ids=input_tokens.input_ids,
attention_mask=input_tokens.attention_mask,
max_length=input_tokens.input_ids.shape[1] + max_new_tokens,
)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
print(f"Inference time: {time.time() - t0:.2f} s")
from huggingface_hub import notebook_login
notebook_login()
from transformers import AutoTokenizer
checkpoint = "meta-llama/Meta-Llama-3-8B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
Copy
	
Setting `pad_token_id` to `eos_token_id`:128001 for open-end generation.
Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.

Agora criamos a configuração de quantização. Como já dissemos, esse algoritmo calcula o erro dos pesos quantizados em relação aos pesos originais com base nas entradas de um conjunto de dados, portanto, na configuração, temos de informá-lo com qual conjunto de dados queremos quantificar o modelo.

Os padrões disponíveis são wikitext2, c4, c4-new, ptb e ptb-new.

Também podemos criar um conjunto de dados a partir de uma lista de cadeias de caracteres.

dataset = ["auto-gptq é uma biblioteca de quantização de modelos fácil de usar com apis amigáveis, baseada no algoritmo GPTQ."].
      

Além disso, precisamos informar a ele o número de bits que o modelo quantizado tem por meio do parâmetro bits.

	
from transformers import GPTQConfig
quantization_config = GPTQConfig(bits=4, dataset = "c4", tokenizer=tokenizer)
Copy

Quantificamos o modelo

from transformers import AutoModelForCausalLM
      import time
      
      t0 = time.time()
      model_4bits = AutoModelForCausalLM.from_pretrained(checkpoint, device_map="auto", quantization_config=quantization_config)
      t_quantization = time.time() - t0
      print(f"Quantization time: {t_quantization:.2f} s = {t_quantization/60:.2f} min")
      
Loading checkpoint shards: 100%|██████████| 4/4 [00:00<?, ?it/s]
Quantizing model.layers blocks : 100%|██████████|32/32 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
/usr/local/lib/python3.10/dist-packages/transformers/modeling_utils.py:4565: FutureWarning: `_is_quantized_training_enabled` is going to be deprecated in transformers 4.39.0. Please use `model.hf_quantizer.is_trainable` instead
        warnings.warn(
      
Quantization time: 1932.09 s = 32.20 min
      

Como o processo de quantização calcula o menor erro entre os pesos quantizados e os pesos originais ao passar as entradas por cada camada, o processo de quantização leva tempo. Nesse caso, levou cerca de meia hora

Vamos dar uma olhada na memória que ele ocupa agora

	
from transformers import GPTQConfig
quantization_config = GPTQConfig(bits=4, dataset = "c4", tokenizer=tokenizer)
from transformers import AutoModelForCausalLM
import time
t0 = time.time()
model_4bits = AutoModelForCausalLM.from_pretrained(checkpoint, device_map="auto", quantization_config=quantization_config)
t_quantization = time.time() - t0
print(f"Quantization time: {t_quantization:.2f} s = {t_quantization/60:.2f} min")
model_4bits_memory = model_4bits.get_memory_footprint()/(1024**3)
print(f"Model memory: {model_4bits_memory:.2f} GB")
Copy
	
Loading checkpoint shards: 100%|██████████| 4/4 [00:00<?, ?it/s]
Model memory: 5.34 GB

Aqui podemos ver um benefício da quantização. Enquanto o modelo original ocupava cerca de 15 GB de VRAM, agora o modelo quantizado ocupa cerca de 5 GB, quase um terço do tamanho original.

Fazemos a inferência e observamos o tempo que leva

import time
      
      input_tokens = tokenizer("Hello my name is Maximo and I am a Machine Learning Engineer", return_tensors="pt").to(model_4bits.device)
      
      t0 = time.time()
      max_new_tokens = 50
      outputs = model_4bits.generate(
          input_ids=input_tokens.input_ids,
          attention_mask=input_tokens.attention_mask,
          max_length=input_tokens.input_ids.shape[1] + max_new_tokens,
      )
      print(tokenizer.decode(outputs[0], skip_special_tokens=True))
      print(f"Inference time: {time.time() - t0:.2f} s")
      
Setting `pad_token_id` to `eos_token_id`:128001 for open-end generation.
      
Hello my name is Maximo and I am a Machine Learning Engineer. I have a strong background in computer science and mathematics, and I am passionate about developing innovative solutions that can positively impact society. I am excited to be a part of this community and to learn from and contribute to the discussions here. I am particularly
      Inference time: 2.34 s
      

O modelo não quantizado levou 4,14 segundos, enquanto agora quantizado para 4 bits levou 2,34 segundos e também gerou bem o texto. Conseguimos reduzir a inferência em quase metade.

Como o tamanho do modelo quantizado é quase um terço do modelo FP16, poderíamos pensar que a velocidade de inferência deveria ser cerca de três vezes mais rápida com o modelo quantizado. Mas lembre-se de que, em cada camada, os pesos são quantificados e os cálculos são realizados em FP16, portanto, só conseguimos reduzir o tempo de inferência pela metade e não em um terço.

Agora vamos salvar o modelo

	
import time
input_tokens = tokenizer("Hello my name is Maximo and I am a Machine Learning Engineer", return_tensors="pt").to(model_4bits.device)
t0 = time.time()
max_new_tokens = 50
outputs = model_4bits.generate(
input_ids=input_tokens.input_ids,
attention_mask=input_tokens.attention_mask,
max_length=input_tokens.input_ids.shape[1] + max_new_tokens,
)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
print(f"Inference time: {time.time() - t0:.2f} s")
save_folder = "./model_4bits/"
model_4bits.save_pretrained(save_folder)
tokenizer.save_pretrained(save_folder)
Copy
	
Setting `pad_token_id` to `eos_token_id`:128001 for open-end generation.
('./model_4bits/tokenizer_config.json',
'./model_4bits/special_tokens_map.json',
'./model_4bits/tokenizer.json')

E fazemos o upload para o hub

repo_id = "Llama-3-8B-Instruct-GPTQ-4bits"
      commit_message = f"AutoGPTQ model for {checkpoint}: {quantization_config.bits}bits, gr{quantization_config.group_size}, desc_act={quantization_config.desc_act}"
      model_4bits.push_to_hub(repo_id, commit_message=commit_message)
      
README.md: 100%|██████████| 5.17/5.17k [00:00<?, ?B/s]
CommitInfo(commit_url='https://huggingface.co/Maximofn/Llama-3-8B-Instruct-GPTQ-4bits/commit/44cfdcad78db260122943d3f57858c1b840bda17', commit_message='AutoGPTQ model for meta-llama/Meta-Llama-3-8B-Instruct: 4bits, gr128, desc_act=False', commit_description='', oid='44cfdcad78db260122943d3f57858c1b840bda17', pr_url=None, pr_revision=None, pr_num=None)

Também fizemos o upload do tokenizador. Embora não tenhamos alterado o tokenizador, nós o carregamos porque, se alguém fizer download do nosso modelo a partir do hub, não precisará saber qual tokenizador usamos, portanto, provavelmente desejará fazer o download do modelo e do tokenizador juntos. Podemos indicar no cartão do modelo qual tokenizador usamos para fazer o download, mas é muito provável que a pessoa não leia o cartão do modelo, tente fazer o download do tokenizador, receba um erro e não saiba o que fazer. Por isso, fizemos o upload para evitar esse problema.

repo_id = "Llama-3-8B-Instruct-GPTQ-4bits"
      commit_message = f"Tokenizers for {checkpoint}: {quantization_config.bits}bits, gr{quantization_config.group_size}, desc_act={quantization_config.desc_act}"
      tokenizer.push_to_hub(repo_id, commit_message=commit_message)
      
README.md: 100%|██████████| 0.00/5.17k [00:00<?, ?B/s]
Out[5]:
CommitInfo(commit_url='https://huggingface.co/Maximofn/Llama-3-8B-Instruct-GPTQ-4bits/commit/75600041ca6e38b5f1fb912ad1803b66656faae4', commit_message='Tokenizers for meta-llama/Meta-Llama-3-8B-Instruct: 4bits, gr128, desc_act=False', commit_description='', oid='75600041ca6e38b5f1fb912ad1803b66656faae4', pr_url=None, pr_revision=None, pr_num=None)

Quantização do modelo para 3 bitslink image 60

Vamos quantificar isso em 3 bits. Reinicio o notebook para evitar problemas de memória e faço login novamente no Hugging Face.

	
repo_id = "Llama-3-8B-Instruct-GPTQ-4bits"
commit_message = f"AutoGPTQ model for {checkpoint}: {quantization_config.bits}bits, gr{quantization_config.group_size}, desc_act={quantization_config.desc_act}"
model_4bits.push_to_hub(repo_id, commit_message=commit_message)
repo_id = "Llama-3-8B-Instruct-GPTQ-4bits"
commit_message = f"Tokenizers for {checkpoint}: {quantization_config.bits}bits, gr{quantization_config.group_size}, desc_act={quantization_config.desc_act}"
tokenizer.push_to_hub(repo_id, commit_message=commit_message)
from huggingface_hub import notebook_login
notebook_login()
Copy

Primeiro, crio o tokenizador

	
repo_id = "Llama-3-8B-Instruct-GPTQ-4bits"
commit_message = f"AutoGPTQ model for {checkpoint}: {quantization_config.bits}bits, gr{quantization_config.group_size}, desc_act={quantization_config.desc_act}"
model_4bits.push_to_hub(repo_id, commit_message=commit_message)
repo_id = "Llama-3-8B-Instruct-GPTQ-4bits"
commit_message = f"Tokenizers for {checkpoint}: {quantization_config.bits}bits, gr{quantization_config.group_size}, desc_act={quantization_config.desc_act}"
tokenizer.push_to_hub(repo_id, commit_message=commit_message)
from huggingface_hub import notebook_login
notebook_login()
from transformers import AutoTokenizer
checkpoint = "meta-llama/Meta-Llama-3-8B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
Copy
	
README.md: 100%|██████████| 5.17/5.17k [00:00<?, ?B/s]
README.md: 100%|██████████| 0.00/5.17k [00:00<?, ?B/s]
Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.

Criamos a configuração de quantização e agora indicamos que queremos quantizar para 3 bits.

	
from transformers import GPTQConfig
quantization_config = GPTQConfig(bits=3, dataset = "c4", tokenizer=tokenizer)
Copy

Quantificamos o modelo

from transformers import AutoModelForCausalLM
      import time
      
      t0 = time.time()
      model_3bits = AutoModelForCausalLM.from_pretrained(checkpoint, device_map="auto", quantization_config=quantization_config)
      t_quantization = time.time() - t0
      print(f"Quantization time: {t_quantization:.2f} s = {t_quantization/60:.2f} min")
      
Loading checkpoint shards: 100%|██████████| 4/4 [00:00<?, ?it/s]
Quantizing model.layers blocks : 100%|██████████|32/32 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
/usr/local/lib/python3.10/dist-packages/transformers/modeling_utils.py:4565: FutureWarning: `_is_quantized_training_enabled` is going to be deprecated in transformers 4.39.0. Please use `model.hf_quantizer.is_trainable` instead
        warnings.warn(
      
Quantization time: 1912.69 s = 31.88 min
      

Como antes, demorou cerca de meia hora.

Vamos dar uma olhada na memória que ele ocupa agora

	
from transformers import GPTQConfig
quantization_config = GPTQConfig(bits=3, dataset = "c4", tokenizer=tokenizer)
from transformers import AutoModelForCausalLM
import time
t0 = time.time()
model_3bits = AutoModelForCausalLM.from_pretrained(checkpoint, device_map="auto", quantization_config=quantization_config)
t_quantization = time.time() - t0
print(f"Quantization time: {t_quantization:.2f} s = {t_quantization/60:.2f} min")
model_3bits_memory = model_3bits.get_memory_footprint()/(1024**3)
print(f"Model memory: {model_3bits_memory:.2f} GB")
Copy
	
Loading checkpoint shards: 100%|██████████| 4/4 [00:00<?, ?it/s]
Model memory: 4.52 GB

O espaço ocupado pela memória do modelo de 3 bits também é de quase 5 GB. O modelo de 4 bits ocupava 5,34 GB, enquanto o modelo de 3 bits agora ocupa 4,52 GB, portanto, conseguimos reduzir um pouco mais o tamanho do modelo.

Fazemos a inferência e observamos o tempo que leva

import time
      
      input_tokens = tokenizer("Hello my name is Maximo and I am a Machine Learning Engineer", return_tensors="pt").to(model_3bits.device)
      
      t0 = time.time()
      max_new_tokens = 50
      outputs = model_3bits.generate(
          input_ids=input_tokens.input_ids,
          attention_mask=input_tokens.attention_mask,
          max_length=input_tokens.input_ids.shape[1] + max_new_tokens,
      )
      print(tokenizer.decode(outputs[0], skip_special_tokens=True))
      print(f"Inference time: {time.time() - t0:.2f} s")
      
Setting `pad_token_id` to `eos_token_id`:128001 for open-end generation.
      
Hello my name is Maximo and I am a Machine Learning Engineer at Google. I am excited to be here today to talk about my work in the field of Machine Learning and to share some of the insights I have gained through my experiences.
      I am a Machine Learning Engineer at Google, and I am excited to be
      Inference time: 2.89 s
      

Embora a saída de 3 bits seja boa, o tempo de inferência passou a ser de 2,89 segundos, enquanto a saída de 4 bits foi de 2,34 segundos. Mais testes devem ser feitos para verificar se sempre leva menos tempo em 4 bits ou se a diferença é tão pequena que às vezes a inferência de 3 bits é mais rápida e às vezes a inferência de 4 bits é mais rápida.

Além disso, embora o resultado faça sentido, ele começa a se tornar repetitivo.

Salvamos o modelo

	
import time
input_tokens = tokenizer("Hello my name is Maximo and I am a Machine Learning Engineer", return_tensors="pt").to(model_3bits.device)
t0 = time.time()
max_new_tokens = 50
outputs = model_3bits.generate(
input_ids=input_tokens.input_ids,
attention_mask=input_tokens.attention_mask,
max_length=input_tokens.input_ids.shape[1] + max_new_tokens,
)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
print(f"Inference time: {time.time() - t0:.2f} s")
save_folder = "./model_3bits/"
model_3bits.save_pretrained(save_folder)
tokenizer.save_pretrained(save_folder)
Copy
	
Setting `pad_token_id` to `eos_token_id`:128001 for open-end generation.
('./model_3bits/tokenizer_config.json',
'./model_3bits/special_tokens_map.json',
'./model_3bits/tokenizer.json')

E fazemos o upload para o hub

repo_id = "Llama-3-8B-Instruct-GPTQ-3bits"
      commit_message = f"AutoGPTQ model for {checkpoint}: {quantization_config.bits}bits, gr{quantization_config.group_size}, desc_act={quantization_config.desc_act}"
      model_3bits.push_to_hub(repo_id, commit_message=commit_message)
      
model.safetensors: 100%|██████████| 4.85/4.85G [00:00<?, ?B/s]
Out[14]:
CommitInfo(commit_url='https://huggingface.co/Maximofn/Llama-3-8B-Instruct-GPTQ-3bits/commit/422fd94a031234c10224ddbe09c0e029a5e9c01f', commit_message='AutoGPTQ model for meta-llama/Meta-Llama-3-8B-Instruct: 3bits, gr128, desc_act=False', commit_description='', oid='422fd94a031234c10224ddbe09c0e029a5e9c01f', pr_url=None, pr_revision=None, pr_num=None)

Também carregamos o tokenizador

repo_id = "Llama-3-8B-Instruct-GPTQ-3bits"
      commit_message = f"Tokenizers for {checkpoint}: {quantization_config.bits}bits, gr{quantization_config.group_size}, desc_act={quantization_config.desc_act}"
      tokenizer.push_to_hub(repo_id, commit_message=commit_message)
      
README.md: 100%|██████████| 0.00/5.17k [00:00<?, ?B/s]
CommitInfo(commit_url='https://huggingface.co/Maximofn/Llama-3-8B-Instruct-GPTQ-4bits/commit/75600041ca6e38b5f1fb912ad1803b66656faae4', commit_message='Tokenizers for meta-llama/Meta-Llama-3-8B-Instruct: 4bits, gr128, desc_act=False', commit_description='', oid='75600041ca6e38b5f1fb912ad1803b66656faae4', pr_url=None, pr_revision=None, pr_num=None)

Quantização do modelo para 2 bitslink image 61

Vamos quantificar isso em 2 bits. Reinicio o notebook para evitar problemas de memória e faço login novamente no Hugging Face.

	
repo_id = "Llama-3-8B-Instruct-GPTQ-3bits"
commit_message = f"AutoGPTQ model for {checkpoint}: {quantization_config.bits}bits, gr{quantization_config.group_size}, desc_act={quantization_config.desc_act}"
model_3bits.push_to_hub(repo_id, commit_message=commit_message)
repo_id = "Llama-3-8B-Instruct-GPTQ-3bits"
commit_message = f"Tokenizers for {checkpoint}: {quantization_config.bits}bits, gr{quantization_config.group_size}, desc_act={quantization_config.desc_act}"
tokenizer.push_to_hub(repo_id, commit_message=commit_message)
from huggingface_hub import notebook_login
notebook_login()
Copy

Primeiro, crio o tokenizador

	
repo_id = "Llama-3-8B-Instruct-GPTQ-3bits"
commit_message = f"AutoGPTQ model for {checkpoint}: {quantization_config.bits}bits, gr{quantization_config.group_size}, desc_act={quantization_config.desc_act}"
model_3bits.push_to_hub(repo_id, commit_message=commit_message)
repo_id = "Llama-3-8B-Instruct-GPTQ-3bits"
commit_message = f"Tokenizers for {checkpoint}: {quantization_config.bits}bits, gr{quantization_config.group_size}, desc_act={quantization_config.desc_act}"
tokenizer.push_to_hub(repo_id, commit_message=commit_message)
from huggingface_hub import notebook_login
notebook_login()
from transformers import AutoTokenizer
checkpoint = "meta-llama/Meta-Llama-3-8B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
Copy
	
model.safetensors: 100%|██████████| 4.85/4.85G [00:00<?, ?B/s]
README.md: 100%|██████████| 0.00/5.17k [00:00<?, ?B/s]
Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.

Criamos a configuração de quantização. Agora dizemos a ele para quantizar em 2 bits. Além disso, temos que indicar quantos vetores da matriz de peso ele quantiza ao mesmo tempo por meio do parâmetro group_size, antes, por padrão, ele tinha o valor 128 e não mexemos nele, mas agora, ao quantizar para 2 bits, para ter menos erro, colocamos um valor menor. Se o deixarmos em 128, o modelo quantizado funcionará muito mal. Nesse caso, colocarei um valor de 16.

	
from transformers import GPTQConfig
quantization_config = GPTQConfig(bits=2, dataset = "c4", tokenizer=tokenizer, group_size=16)
Copy
from transformers import AutoModelForCausalLM
      import time
      
      t0 = time.time()
      model_2bits = AutoModelForCausalLM.from_pretrained(checkpoint, device_map="auto", quantization_config=quantization_config)
      t_quantization = time.time() - t0
      print(f"Quantization time: {t_quantization:.2f} s = {t_quantization/60:.2f} min")
      
Loading checkpoint shards: 100%|██████████| 4/4 [00:00<?, ?it/s]
Quantizing model.layers blocks : 100%|██████████|32/32 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
/usr/local/lib/python3.10/dist-packages/transformers/modeling_utils.py:4565: FutureWarning: `_is_quantized_training_enabled` is going to be deprecated in transformers 4.39.0. Please use `model.hf_quantizer.is_trainable` instead
        warnings.warn(
      
Quantization time: 1973.12 s = 32.89 min
      

Vemos que isso também levou cerca de meia hora.

Vamos dar uma olhada na memória que ele ocupa agora

	
from transformers import GPTQConfig
quantization_config = GPTQConfig(bits=2, dataset = "c4", tokenizer=tokenizer, group_size=16)
from transformers import AutoModelForCausalLM
import time
t0 = time.time()
model_2bits = AutoModelForCausalLM.from_pretrained(checkpoint, device_map="auto", quantization_config=quantization_config)
t_quantization = time.time() - t0
print(f"Quantization time: {t_quantization:.2f} s = {t_quantization/60:.2f} min")
model_2bits_memory = model_2bits.get_memory_footprint()/(1024**3)
print(f"Model memory: {model_2bits_memory:.2f} GB")
Copy
	
Loading checkpoint shards: 100%|██████████| 4/4 [00:00<?, ?it/s]
Model memory: 4.50 GB

Enquanto a quantização de 4 bits era de 5,34 GB e a de 3 bits era de 4,52 GB, agora a quantização de 2 bits é de 4,50 GB, portanto, conseguimos reduzir um pouco mais o tamanho do modelo.

Fazemos a inferência e observamos o tempo que leva

import time
      
      input_tokens = tokenizer("Hello my name is Maximo and I am a Machine Learning Engineer", return_tensors="pt").to(model_2bits.device)
      
      t0 = time.time()
      max_new_tokens = 50
      outputs = model_2bits.generate(
          input_ids=input_tokens.input_ids,
          attention_mask=input_tokens.attention_mask,
          max_length=input_tokens.input_ids.shape[1] + max_new_tokens,
      )
      print(tokenizer.decode(outputs[0], skip_special_tokens=True))
      print(f"Inference time: {time.time() - t0:.2f} s")
      
Setting `pad_token_id` to `eos_token_id`:128001 for open-end generation.
      
Hello my name is Maximo and I am a Machine Learning Engineer.  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
      Inference time: 2.92 s
      

Vemos que o resultado já não é bom, além disso, o tempo de inferência é de 2,92 segundos, praticamente o mesmo que com 3 e 4 bits.

Salvamos o modelo

	
import time
input_tokens = tokenizer("Hello my name is Maximo and I am a Machine Learning Engineer", return_tensors="pt").to(model_2bits.device)
t0 = time.time()
max_new_tokens = 50
outputs = model_2bits.generate(
input_ids=input_tokens.input_ids,
attention_mask=input_tokens.attention_mask,
max_length=input_tokens.input_ids.shape[1] + max_new_tokens,
)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
print(f"Inference time: {time.time() - t0:.2f} s")
save_folder = "./model_2bits/"
model_2bits.save_pretrained(save_folder)
tokenizer.save_pretrained(save_folder)
Copy
	
Setting `pad_token_id` to `eos_token_id`:128001 for open-end generation.
('./model_2bits/tokenizer_config.json',
'./model_2bits/special_tokens_map.json',
'./model_2bits/tokenizer.json')

Nós o carregamos no hub

repo_id = "Llama-3-8B-Instruct-GPTQ-2bits"
      commit_message = f"AutoGPTQ model for {checkpoint}: {quantization_config.bits}bits, gr{quantization_config.group_size}, desc_act={quantization_config.desc_act}"
      model_2bits.push_to_hub(repo_id, commit_message=commit_message)
      
model.safetensors: 100%|██████████| 4.83/4.83G [00:00<?, ?B/s]
Out[8]:
CommitInfo(commit_url='https://huggingface.co/Maximofn/Llama-3-8B-Instruct-GPTQ-2bits/commit/13ede006ce0dbbd8aca54212e960eff98ea5ec63', commit_message='AutoGPTQ model for meta-llama/Meta-Llama-3-8B-Instruct: 2bits, gr16, desc_act=False', commit_description='', oid='13ede006ce0dbbd8aca54212e960eff98ea5ec63', pr_url=None, pr_revision=None, pr_num=None)

Quantização do modelo para 1 bitlink image 62

Vamos quantificar isso em 1 bit. Reinicio o notebook para evitar problemas de memória e faço login novamente no Hugging Face.

	
repo_id = "Llama-3-8B-Instruct-GPTQ-2bits"
commit_message = f"AutoGPTQ model for {checkpoint}: {quantization_config.bits}bits, gr{quantization_config.group_size}, desc_act={quantization_config.desc_act}"
model_2bits.push_to_hub(repo_id, commit_message=commit_message)
from huggingface_hub import notebook_login
notebook_login()
Copy

Primeiro, crio o tokenizador

	
repo_id = "Llama-3-8B-Instruct-GPTQ-2bits"
commit_message = f"AutoGPTQ model for {checkpoint}: {quantization_config.bits}bits, gr{quantization_config.group_size}, desc_act={quantization_config.desc_act}"
model_2bits.push_to_hub(repo_id, commit_message=commit_message)
from huggingface_hub import notebook_login
notebook_login()
from transformers import AutoTokenizer
checkpoint = "meta-llama/Meta-Llama-3-8B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
Copy
	
model.safetensors: 100%|██████████| 4.83/4.83G [00:00<?, ?B/s]
Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.

Criamos a configuração de quantização, agora dizemos a ela para quantizar em apenas 1 bit e também para usar um group_size de 8.

	
from transformers import GPTQConfig
quantization_config = GPTQConfig(bits=2, dataset = "c4", tokenizer=tokenizer, group_size=8)
Copy
from transformers import AutoModelForCausalLM
      import time
      
      t0 = time.time()
      model_1bits = AutoModelForCausalLM.from_pretrained(checkpoint, device_map="auto", quantization_config=quantization_config)
      t_quantization = time.time() - t0
      print(f"Quantization time: {t_quantization:.2f} s = {t_quantization/60:.2f} min")
      
Loading checkpoint shards: 100%|██████████| 4/4 [00:00<?, ?it/s]
Quantizing model.layers blocks : 100%|██████████|32/32 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
Quantizing layers inside the block: 100%|██████████| 7/7 [00:00<?, ?it/s]
/usr/local/lib/python3.10/dist-packages/transformers/modeling_utils.py:4565: FutureWarning: `_is_quantized_training_enabled` is going to be deprecated in transformers 4.39.0. Please use `model.hf_quantizer.is_trainable` instead
        warnings.warn(
      
Quantization time: 2030.38 s = 33.84 min
      

Vemos que também leva cerca de meia hora para quantificar.

Vamos dar uma olhada na memória que ele ocupa agora

	
from transformers import GPTQConfig
quantization_config = GPTQConfig(bits=2, dataset = "c4", tokenizer=tokenizer, group_size=8)
from transformers import AutoModelForCausalLM
import time
t0 = time.time()
model_1bits = AutoModelForCausalLM.from_pretrained(checkpoint, device_map="auto", quantization_config=quantization_config)
t_quantization = time.time() - t0
print(f"Quantization time: {t_quantization:.2f} s = {t_quantization/60:.2f} min")
model_1bits_memory = model_1bits.get_memory_footprint()/(1024**3)
print(f"Model memory: {model_1bits_memory:.2f} GB")
Copy
	
Loading checkpoint shards: 100%|██████████| 4/4 [00:00<?, ?it/s]
Model memory: 5.42 GB

Vemos que, nesse caso, ele ocupa ainda mais do que quantificado em 2 bits, 4,52 GB.

Fazemos a inferência e observamos o tempo que leva

import time
      
      input_tokens = tokenizer("Hello my name is Maximo and I am a Machine Learning Engineer", return_tensors="pt").to(model_1bits.device)
      
      t0 = time.time()
      max_new_tokens = 50
      outputs = model_1bits.generate(
          input_ids=input_tokens.input_ids,
          attention_mask=input_tokens.attention_mask,
          max_length=input_tokens.input_ids.shape[1] + max_new_tokens,
      )
      print(tokenizer.decode(outputs[0], skip_special_tokens=True))
      print(f"Inference time: {time.time() - t0:.2f} s")
      
Setting `pad_token_id` to `eos_token_id`:128001 for open-end generation.
      
Hello my name is Maximo and I am a Machine Learning Engineerimerszuimersimerspinsimersimersingoingoimersurosimersimersimersoleningoimersingopinsimersbirpinsimersimersimersorgeingoimersiringimersimersimersimersimersimersimersンディorge_REFERER ingest羊imersorgeimersimersendetingoШАhandsingo
      Inference time: 3.12 s
      

Vemos que a saída é muito ruim e também demora mais do que quando quantizamos para 2 bits.

Salvamos o modelo

	
import time
input_tokens = tokenizer("Hello my name is Maximo and I am a Machine Learning Engineer", return_tensors="pt").to(model_1bits.device)
t0 = time.time()
max_new_tokens = 50
outputs = model_1bits.generate(
input_ids=input_tokens.input_ids,
attention_mask=input_tokens.attention_mask,
max_length=input_tokens.input_ids.shape[1] + max_new_tokens,
)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
print(f"Inference time: {time.time() - t0:.2f} s")
save_folder = "./model_1bits/"
model_1bits.save_pretrained(save_folder)
tokenizer.save_pretrained(save_folder)
Copy
	
Setting `pad_token_id` to `eos_token_id`:128001 for open-end generation.
('./model_1bits/tokenizer_config.json',
'./model_1bits/special_tokens_map.json',
'./model_1bits/tokenizer.json')

Nós o carregamos no hub

repo_id = "Llama-3-8B-Instruct-GPTQ-1bits"
      commit_message = f"AutoGPTQ model for {checkpoint}: {quantization_config.bits}bits, gr{quantization_config.group_size}, desc_act={quantization_config.desc_act}"
      model_1bits.push_to_hub(repo_id, commit_message=commit_message)
      
README.md: 100%|██████████| 0.00/5.17k [00:00<?, ?B/s]
Upload 2 LFS files: 100%|██████████| 0/2 [00:00<?, ?it/s]
model-00002-of-00002.safetensors: 100%|██████████| 0.00/1.05G [00:00<?, ?B/s]
model-00001-of-00002.safetensors: 100%|██████████| 0.00/4.76G [00:00<?, ?B/s]
Out[8]:
CommitInfo(commit_url='https://huggingface.co/Maximofn/Llama-3-8B-Instruct-GPTQ-2bits/commit/e59ccffc03247e7dcc418f98b482cc02dc7a168d', commit_message='AutoGPTQ model for meta-llama/Meta-Llama-3-8B-Instruct: 2bits, gr8, desc_act=False', commit_description='', oid='e59ccffc03247e7dcc418f98b482cc02dc7a168d', pr_url=None, pr_revision=None, pr_num=None)

Resumo da quantificaçãolink image 63

Vamos comprar quantização de 4, 3, 2 e 1 bits.

Bits Tempo de quantização (min) Memória (GB) Tempo de inferência (s) Qualidade da saída
FP16 0 14.96 4.14 Bom
4 32.20 5.34 2.34 Bom
3 31.88 4.52 2.89 Bom
2 32.89 4.50 2.92 Ruim
1 33.84 5.42 3.12 Ruim

Observando essa tabela, vemos que não faz sentido, neste exemplo, quantificar com menos de 4 bits.

A quantificação em 1 e 2 bits claramente não faz sentido porque a qualidade da saída é ruim.

Mas, embora a saída quando quantizamos para 3 bits seja boa, ela começou a se tornar repetitiva, portanto, a longo prazo, provavelmente não seria uma boa ideia usar esse modelo. Além disso, nem a economia no tempo de quantização, nem a economia de VRAM, nem a economia no tempo de inferência são significativas em comparação com a quantização para 4 bits.

Carregamento do modelo salvolink image 64

Agora que comparamos a quantização dos modelos, vamos ver como seria feito para carregar o modelo de 4 bits que salvamos, já que, como vimos, essa é a melhor opção.

Primeiro, carregamos o tokenizador que usamos.

	
repo_id = "Llama-3-8B-Instruct-GPTQ-1bits"
commit_message = f"AutoGPTQ model for {checkpoint}: {quantization_config.bits}bits, gr{quantization_config.group_size}, desc_act={quantization_config.desc_act}"
model_1bits.push_to_hub(repo_id, commit_message=commit_message)
from transformers import AutoTokenizer
path = "./model_4bits"
tokenizer = AutoTokenizer.from_pretrained(path)
Copy
	
README.md: 100%|██████████| 0.00/5.17k [00:00<?, ?B/s]
Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.

Agora, carregamos o modelo que salvamos

	
from transformers import AutoModelForCausalLM
load_model_4bits = AutoModelForCausalLM.from_pretrained(path, device_map="auto")
Copy
	
Loading checkpoint shards: 100%|██████████| 2/2 [00:00<?, ?it/s]

Vemos a memória que ele ocupa

	
load_model_4bits_memory = load_model_4bits.get_memory_footprint()/(1024**3)
print(f"Model memory: {load_model_4bits_memory:.2f} GB")
Copy
	
Model memory: 5.34 GB

Vemos que ele ocupa a mesma memória de quando o quantificamos, o que é lógico.

Fazemos a inferência e observamos o tempo que leva

import time
      
      input_tokens = tokenizer("Hello my name is Maximo and I am a Machine Learning Engineer", return_tensors="pt").to(load_model_4bits.device)
      
      t0 = time.time()
      max_new_tokens = 50
      outputs = load_model_4bits.generate(
          input_ids=input_tokens.input_ids,
          attention_mask=input_tokens.attention_mask,
          max_length=input_tokens.input_ids.shape[1] + max_new_tokens,
      )
      print(tokenizer.decode(outputs[0], skip_special_tokens=True))
      print(f"Inference time: {time.time() - t0:.2f} s")
      
Setting `pad_token_id` to `eos_token_id`:128001 for open-end generation.
      
Hello my name is Maximo and I am a Machine Learning Engineer. I have a strong background in computer science and mathematics, and I have been working with machine learning models for several years. I am excited to be a part of this community and to share my knowledge and experience with others. I am particularly interested in
      Inference time: 3.82 s
      

Vemos que a inferência é boa e levou 3,82 segundos, um pouco mais do que quando a quantificamos. Mas, como eu disse antes, teríamos que fazer esse teste várias vezes e tirar uma média.

Carregando o modelo carregado para o hublink image 65

Agora veremos como carregar o modelo de 4 bits que carregamos no hub.

Primeiro, carregamos o tokenizador que carregamos.

	
import time
input_tokens = tokenizer("Hello my name is Maximo and I am a Machine Learning Engineer", return_tensors="pt").to(load_model_4bits.device)
t0 = time.time()
max_new_tokens = 50
outputs = load_model_4bits.generate(
input_ids=input_tokens.input_ids,
attention_mask=input_tokens.attention_mask,
max_length=input_tokens.input_ids.shape[1] + max_new_tokens,
)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
print(f"Inference time: {time.time() - t0:.2f} s")
from transformers import AutoTokenizer
checkpoint = "Maximofn/Llama-3-8B-Instruct-GPTQ-4bits"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
Copy
	
Setting `pad_token_id` to `eos_token_id`:128001 for open-end generation.
Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.

Agora, carregamos o modelo que salvamos

	
from transformers import AutoModelForCausalLM
load_model_4bits = AutoModelForCausalLM.from_pretrained(checkpoint, device_map="auto")
Copy

Vemos a memória que ele ocupa

	
from transformers import AutoModelForCausalLM
load_model_4bits = AutoModelForCausalLM.from_pretrained(checkpoint, device_map="auto")
load_model_4bits_memory = load_model_4bits.get_memory_footprint()/(1024**3)
print(f"Model memory: {load_model_4bits_memory:.2f} GB")
Copy
	
Model memory: 5.34 GB

Ele também ocupa a mesma memória

Fazemos a inferência e observamos o tempo que leva

import time
      
      input_tokens = tokenizer("Hello my name is Maximo and I am a Machine Learning Engineer", return_tensors="pt").to(load_model_4bits.device)
      
      t0 = time.time()
      max_new_tokens = 50
      outputs = load_model_4bits.generate(
          input_ids=input_tokens.input_ids,
          attention_mask=input_tokens.attention_mask,
          max_length=input_tokens.input_ids.shape[1] + max_new_tokens,
      )
      print(tokenizer.decode(outputs[0], skip_special_tokens=True))
      print(f"Inference time: {time.time() - t0:.2f} s")
      
Setting `pad_token_id` to `eos_token_id`:128001 for open-end generation.
      
Hello my name is Maximo and I am a Machine Learning Engineer with a passion for building innovative AI solutions. I have been working in the field of AI for over 5 years, and have gained extensive experience in developing and implementing machine learning models for various industries.
      
      In my free time, I enjoy reading books on
      Inference time: 3.81 s
      

Vemos que a inferência também é boa e levou 3,81 segundos.

Continuar lendo

DoLa – Decoding by Contrasting Layers Improves Factuality in Large Language Models

DoLa – Decoding by Contrasting Layers Improves Factuality in Large Language Models

Você já conversou com um LLM e ele lhe respondeu algo que parece ter bebido café de máquina a noite toda? 😂 Isso é o que chamamos de alucinação no mundo dos LLMs! Mas não se preocupe, pois não é que seu modelo de linguagem esteja louco (embora às vezes possa parecer isso 🤪). A verdade é que os LLMs podem ser um pouco... criativos quando se trata de gerar texto. Mas graças ao DoLa, um método que usa camadas de contraste para melhorar a viabilidade dos LLMs, podemos evitar que nossos modelos de linguagem se transformem em escritores de ficção científica 😂. Nesta publicação, explicarei como o DoLa funciona e mostrarei um exemplo de código para que você possa entender melhor como tornar seus LLMs mais confiáveis e menos propensos a inventar histórias. Vamos salvar nossos LLMs da loucura e torná-los mais úteis! 🚀

Últimos posts -->

Você viu esses projetos?

Subtify

Subtify Subtify

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.

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 -->