Otimização do rosto de abraços
Optimum é uma extensão da biblioteca [Transformers] (https://maximofn.com/hugging-face-transformers/) que fornece um conjunto de ferramentas de otimização de desempenho para modelos de treinamento e inferência, em hardware específico, com eficiência máxima.
O ecossistema de IA está evoluindo rapidamente e cada vez mais hardware especializado está surgindo todos os dias, juntamente com suas próprias otimizações. Portanto, o Optimum
permite que os usuários utilizem eficientemente qualquer um desses HW com a mesma facilidade dos [Transformers] (https://maximofn.com/hugging-face-transformers/).
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..
A otimização para as seguintes plataformas HW é possível com o Optimun
:
- Nvidia
- AMD
- Intel
- AWS
- TPU
- Havana
- FuriosaAI
Além disso, ele oferece aceleração para as seguintes integrações de código aberto
- Tempo de execução do ONNX
- Exportadores: exportam dados do Pytorch ou do TensorFlow para diferentes formatos, como ONNX ou TFLite.
- Melhor transformador
- Tocha FX
Instalação
Para instalar o Optimum
, basta executar:
pip install optimum
Mas se quiser instalá-lo com suporte para todas as plataformas HW, você pode fazer o seguinte
Accelerator | Instalação |
---|---|
ONNX Runtime | pip install --upgrade --upgrade-strategy eager optimum[onnxruntime] |
Intel Neural Compressor | pip install --upgrade --upgrade-strategy eager optimum[neural-compressor] |
OpenVINO | pip install --upgrade --upgrade-strategy eager optimum[openvino] |
NVIDIA TensorRT-LLM | docker run -it --gpus all --ipc host huggingface/optimum-nvidia |
AMD Instinct GPUs e Ryzen AI NPU | pip install --upgrade --upgrade-strategy eager optimum[amd] |
AWS Trainum & Inferentia | pip install --upgrade --upgrade-strategy eager optimum[neuronx] |
Havana Gaudi Processor (HPU) | pip install --upgrade --upgrade-strategy eager optimum [habana] |
FuriosaAI | pip install --upgrade --upgrade-strategy eager optimum[furiosa] |
Os sinalizadores --upgrade --upgrade-strategy eager
são necessários para garantir que os diferentes pacotes sejam atualizados para a versão mais recente possível.
Como a maioria das pessoas usa o Pytorch em GPUs Nvidia e, especialmente, como eu tenho uma Nvidia, esta postagem falará apenas sobre o uso do Optimun
com GPUs Nvidia e Pytorch.
BeterTransformer
O BetterTransformer é uma otimização nativa do PyTorch para aumentar a velocidade de 1,25 a 4 vezes na inferência de modelo baseada no Transformer.
BetterTransformer é uma API que permite que você aproveite os recursos modernos de hardware para acelerar o treinamento e a inferência de modelos de transformadores no PyTorch, usando implementações mais eficientes e com atenção ao "caminho rápido" da versão nativa nn.TransformerEncoderLayer
do nn.TransformerEncoderLayer
.
O BetterTransformer usa dois tipos de acelerações:
Flash Attention
: é uma implementação doattention
que usa osparse
para reduzir a complexidade computacional. A atenção é uma das operações mais caras nos modelos de transformadores, e oFlash Attention
a torna mais eficiente.Memory-Efficient Attention
: essa é outra implementação de atenção que usa a funçãoscaled_dot_product_attention
do PyTorch. Essa função é mais eficiente em termos de memória do que a implementação padrão de atenção do PyTorch.
Além disso, a versão 2.0 do PyTorch inclui um operador de atenção de produto de ponto escalonado (SDPA) nativo como parte do torch.nn.functional
.
O Optimmun fornece essa funcionalidade com a biblioteca Transformers
.
Inferência com modelo automático
Primeiro, vamos ver como seria a inferência normal com Transformers
e Automodel
.
from transformers import AutoTokenizer, AutoModelForCausalLM
checkpoint = "openai-community/gpt2"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForCausalLM.from_pretrained(checkpoint, device_map="auto")
tokenizer.pad_token = tokenizer.eos_token
input_tokens = tokenizer(["Me encanta aprender de"], return_tensors="pt", padding=True).to("cuda")
output_tokens = model.generate(**input_tokens, max_length=50)
sentence_output = tokenizer.decode(output_tokens[0], skip_special_tokens=True)
sentence_output
Agora, veremos como ele seria otimizado com o BetterTransformer
e o Optimun
.
O que temos que fazer é converter o modelo usando o método transform
do BeterTransformer
.
from transformers import AutoTokenizer, AutoModelForCausalLM
from optimum.bettertransformer import BetterTransformer
checkpoint = "openai-community/gpt2"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model_hf = AutoModelForCausalLM.from_pretrained(checkpoint, device_map="auto")
# Convert the model to a BetterTransformer model
model = BetterTransformer.transform(model_hf, keep_original_model=True)
tokenizer.pad_token = tokenizer.eos_token
input_tokens = tokenizer(["Me encanta aprender de"], return_tensors="pt", padding=True).to("cuda")
output_tokens = model.generate(**input_tokens, max_length=50)
sentence_output = tokenizer.decode(output_tokens[0], skip_special_tokens=True)
sentence_output
Inferências com o pipeline
Como antes, primeiro vemos como seria a inferência normal com Transformers
e Pipeline
.
from transformers import AutoTokenizer, AutoModelForCausalLMcheckpoint = "openai-community/gpt2"tokenizer = AutoTokenizer.from_pretrained(checkpoint)model = AutoModelForCausalLM.from_pretrained(checkpoint, device_map="auto")tokenizer.pad_token = tokenizer.eos_tokeninput_tokens = tokenizer(["Me encanta aprender de"], return_tensors="pt", padding=True).to("cuda")output_tokens = model.generate(**input_tokens, max_length=50)sentence_output = tokenizer.decode(output_tokens[0], skip_special_tokens=True)sentence_outputfrom transformers import AutoTokenizer, AutoModelForCausalLMfrom optimum.bettertransformer import BetterTransformercheckpoint = "openai-community/gpt2"tokenizer = AutoTokenizer.from_pretrained(checkpoint)model_hf = AutoModelForCausalLM.from_pretrained(checkpoint, device_map="auto")# Convert the model to a BetterTransformer modelmodel = BetterTransformer.transform(model_hf, keep_original_model=True)tokenizer.pad_token = tokenizer.eos_tokeninput_tokens = tokenizer(["Me encanta aprender de"], return_tensors="pt", padding=True).to("cuda")output_tokens = model.generate(**input_tokens, max_length=50)sentence_output = tokenizer.decode(output_tokens[0], skip_special_tokens=True)sentence_outputfrom transformers import pipelinepipe = pipeline(task="fill-mask", model="distilbert-base-uncased")pipe("I am a student at [MASK] University.")
Setting `pad_token_id` to `eos_token_id`:50256 for open-end generation.The BetterTransformer implementation does not support padding during training, as the fused kernels do not support attention masks. Beware that passing padded batched data during training may result in unexpected outputs. Please refer to https://huggingface.co/docs/optimum/bettertransformer/overview for more details.Setting `pad_token_id` to `eos_token_id`:50256 for open-end generation.[{'score': 0.05116177722811699,'token': 8422,'token_str': 'stanford','sequence': 'i am a student at stanford university.'},{'score': 0.04033993184566498,'token': 5765,'token_str': 'harvard','sequence': 'i am a student at harvard university.'},{'score': 0.03990468755364418,'token': 7996,'token_str': 'yale','sequence': 'i am a student at yale university.'},{'score': 0.0361952930688858,'token': 10921,'token_str': 'cornell','sequence': 'i am a student at cornell university.'},{'score': 0.03303057327866554,'token': 9173,'token_str': 'princeton','sequence': 'i am a student at princeton university.'}]
Agora veremos como otimizá-lo, de modo que usaremos pipeline
do Optimun
, em vez de Transformers
. Também devemos indicar que queremos usar o bettertransformer
como acelerador.
from optimum.pipelines import pipeline
# Use the BetterTransformer pipeline
pipe = pipeline(task="fill-mask", model="distilbert-base-uncased", accelerator="bettertransformer")
pipe("I am a student at [MASK] University.")
Treinamento
Para o treinamento com Optimun
, fazemos o mesmo que com a inferência Automodel, convertemos o modelo usando o método transform
do BeterTransformer
.
Quando terminamos o treinamento, convertemos o modelo novamente usando o método reverse
do BeterTransformer
para obter o modelo original de volta, para que possamos salvá-lo e carregá-lo no hub Hugging Face.
from optimum.pipelines import pipeline# Use the BetterTransformer pipelinepipe = pipeline(task="fill-mask", model="distilbert-base-uncased", accelerator="bettertransformer")pipe("I am a student at [MASK] University.")from transformers import AutoTokenizer, AutoModelForCausalLMfrom optimum.bettertransformer import BetterTransformercheckpoint = "openai-community/gpt2"tokenizer = AutoTokenizer.from_pretrained(checkpoint)model_hf = AutoModelForCausalLM.from_pretrained(checkpoint, device_map="auto")# Convert the model to a BetterTransformer modelmodel = BetterTransformer.transform(model_hf, keep_original_model=True)############################################################################### do your training here############################################################################### Convert the model back to a Hugging Face modelmodel_hf = BetterTransformer.reverse(model)model_hf.save_pretrained("fine_tuned_model")model_hf.push_to_hub("fine_tuned_model")