Hugging Face Optimun

Hugging Face Optimun Hugging Face Optimun

Hugging Face Optimunlink image 0

Optimum es una extensión de la librería Transformers que proporciona un conjunto de herramientas de optimización del rendimiento para entrenar y para la inferencia modelos, en hardware específico, con la máxima eficiencia.

El ecosistema de IA evoluciona rápidamente y cada día surge más hardware especializado junto con sus propias optimizaciones. Por tanto, Optimum permite a los utilizar eficientemente cualquiera de este HW con la misma facilidad que Transformers.

Optimun premite la optimización para las siguientes plataformas HW:

  • Nvidia
  • AMD
  • Intel
  • AWS
  • TPU
  • Habana
  • FuriosaAI

Además ofrece aceleración para las siguientes integraciones open source

  • ONNX runtime
  • Exporters: Exportar omdelos Pytorch o TensorFlow a diferentes formatos como ONNX o TFLite
  • BetterTransformer
  • Torch FX

Instalaciónlink image 1

Para instalar Optimum simplemente ejecuta:

pip install optimum
      

Pero si se quiere instalar con soporte para todas las plataformas HW, se puede hacer así

Accelerator Installation
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 and Ryzen AI NPU pip install --upgrade --upgrade-strategy eager optimum[amd]
AWS Trainum & Inferentia pip install --upgrade --upgrade-strategy eager optimum[neuronx]
Habana Gaudi Processor (HPU) pip install --upgrade --upgrade-strategy eager optimum[habana]
FuriosaAI pip install --upgrade --upgrade-strategy eager optimum[furiosa]

los flags --upgrade --upgrade-strategy eager son necesarios para garantizar que los diferentes paquetes se actualicen a la última versión posible.

Como la mayoría de la gente usa Pytorch en GPUs de Nvidia, y sobre todo, como Nvidia es lo que yo tengo, este post va a hablar solo del uso de Optimun con GPUs de Nvidia y Pytorch.

BeterTransformerlink image 2

BetterTransformer es una optimización nativa de PyTorch para obtener una aceleración de x1,25 a x4 en la inferencia de modelos basados ​​en Transformer

BetterTransformer es una API que permite aprovechar las características de hardware modernas para acelerar el entrenamiento y la inferencia de modelos de transformers en PyTorch, utilizando implementaciones de atención más eficientes y fast path de la versión nativa de nn.TransformerEncoderLayer.

BetterTransformer usa dos tipos de aceleraciones:

  1. Flash Attention: Esta es una implementación de la attention que utiliza sparse para reducir la complejidad computacional. La atención es una de las operaciones más costosas en los modelos de transformers, y Flash Attention la hace más eficiente.
  2. Memory-Efficient Attention: Esta es otra implementación de la atención que utiliza la función scaled_dot_product_attention de PyTorch. Esta función es más eficiente en términos de memoria que la implementación estándar de la atención en PyTorch.

Además, la versión 2.0 de PyTorch incluye un operador de atención de productos punto escalado (SDPA) nativo como parte de torch.nn.functional

Optimun proporciona esta funcionalidad con la librería Transformers

Inferencia con Automodellink image 3

Primero vamos a ver cómo sería la inferencia normal con Transformers y 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
      
Setting `pad_token_id` to `eos_token_id`:50256 for open-end generation.
      
Out[1]:
'Me encanta aprender de la vie de la vie de la vie de la vie de la vie de la vie de la vie de la vie de la vie de la vie de la vie de'

Ahora vemos cómo se optimizaría con BetterTransformer y Optimun

Lo que tenemos que hacer es convertir el modelo mediante el método transform de 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
      
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.
      
Out[2]:
'Me encanta aprender de la vie de la vie de la vie de la vie de la vie de la vie de la vie de la vie de la vie de la vie de la vie de'

Inferecncia con Pipelinelink image 4

Al igual que antes, primero vemos cómo sería la inferencia normal con Transformers y Pipeline

	
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
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
from transformers import pipeline
pipe = pipeline(task="fill-mask", model="distilbert-base-uncased")
pipe("I am a student at [MASK] University.")
Copy
	
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.'}]

Ahora vemos cómo optimizarlo, para ello usamos pipeline de Optimun, en vez de el de Transformers. Además hay que indicar que queremos usar 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.")
      
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.
      /home/wallabot/miniconda3/envs/nlp/lib/python3.11/site-packages/optimum/bettertransformer/models/encoder_models.py:868: UserWarning: The PyTorch API of nested tensors is in prototype stage and will change in the near future. (Triggered internally at /opt/conda/conda-bld/pytorch_1708025845868/work/aten/src/ATen/NestedTensorImpl.cpp:177.)
        hidden_states = torch._nested_tensor_from_mask(hidden_states, attn_mask)
      
Out[4]:
[{'score': 0.05116180703043938,
        'token': 8422,
        'token_str': 'stanford',
        'sequence': 'i am a student at stanford university.'},
       {'score': 0.040340032428503036,
        'token': 5765,
        'token_str': 'harvard',
        'sequence': 'i am a student at harvard university.'},
       {'score': 0.039904672652482986,
        'token': 7996,
        'token_str': 'yale',
        'sequence': 'i am a student at yale university.'},
       {'score': 0.036195311695337296,
        'token': 10921,
        'token_str': 'cornell',
        'sequence': 'i am a student at cornell university.'},
       {'score': 0.03303062543272972,
        'token': 9173,
        'token_str': 'princeton',
        'sequence': 'i am a student at princeton university.'}]

Entrenamientolink image 5

Para el entrneamiento con Optimun hacemos lo mismo que con la inferencia con Automodel, convertimos el modelo mediante el método transform de BeterTransformer.

Cuando terminamos el entrenamiento, volvemos a convertir el modelo mediante el método reverse de BeterTransformer para volver a tener el modelo original y así poder guardarlo y subirlo al hub de Hugging Face.

	
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.")
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)
##############################################################################
# do your training here
##############################################################################
# Convert the model back to a Hugging Face model
model_hf = BetterTransformer.reverse(model)
model_hf.save_pretrained("fine_tuned_model")
model_hf.push_to_hub("fine_tuned_model")
Copy

Seguir leyendo

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

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

¿Alguna vez has hablado con un LLM y te ha respondido algo que suena como si hubiera estado bebiendo café de máquina durante toda la noche? 😂 ¡Eso es lo que llamamos una alucinación en el mundo de los LLMs! Pero no te preocupes, porque no es que tu modelo de lenguaje esté loco (aunque a veces puede parecerlo 🤪). La verdad es que los LLMs pueden ser un poco... creativos cuando se trata de generar texto. Pero gracias a DoLa, un método que utiliza capas de contraste para mejorar la factibilidad de los LLMs, podemos evitar que nuestros modelos de lenguaje se conviertan en escritores de ciencia ficción 😂. En este post, te explicaré cómo funciona DoLa y te mostraré un ejemplo de código para que puedas entender mejor cómo hacer que tus LLMs sean más fiables y menos propensos a inventar historias. ¡Vamos a salvar a nuestros LLMs de la locura y hacer que sean más útiles! 🚀

Últimos posts -->

¿Has visto estos proyectos?

Subtify

Subtify Subtify

Generador de subtítulos para videos en el idioma que desees. Además a cada persona le pone su subtítulo de un color

Ver todos los proyectos -->

¿Quieres aplicar la IA en tu proyecto? Contactame!

¿Quieres mejorar con estos tips?

Últimos tips -->

Usa esto en local

Los espacios de Hugging Face nos permite ejecutar modelos con demos muy sencillas, pero ¿qué pasa si la demo se rompe? O si el usuario la elimina? Por ello he creado contenedores docker con algunos espacios interesantes, para poder usarlos de manera local, pase lo que pase. De hecho, es posible que si pinchas en alún botón de ver proyecto te lleve a un espacio que no funciona.

Ver todos los contenedores -->

¿Quieres aplicar la IA en tu proyecto? Contactame!

¿Quieres entrenar tu modelo con estos datasets?

short-jokes-dataset

Dataset de chistes en inglés

opus100

Dataset con traducciones de inglés a español

netflix_titles

Dataset con películas y series de Netflix

Ver más datasets -->