Affiner le LLM multimodèle : IDEFICS 9B à l'aide d'A100
Introduction
Dans cet article, nous apprendrons comment exécuter l'inférence à l'aide de la version quantifiée d'IDEFICS et affiner IDEFICS-9b à l'aide d'un GPU A100. Nous peaufinerons également IDEFICS 9B, une variante du modèle de langage visuel innovant. Ce processus de réglage fin implique des techniques telles que LoRa, spécialement conçues pour améliorer les performances du modèle dans certains domaines.
Lorsqu'il s'agit d'exécuter des inférences et d'affiner IDEFICS-9 b, la puissance de traitement élevée des GPU A100 peut accélérer considérablement le processus, vous permettant ainsi d'itérer et d'expérimenter plus rapidement.
Qu’est-ce qu’IDEFICS ?
IDEFICS (Image-aware Decoder Enhanced à la Flamingo with Interleaved Cross-attentionS) est un modèle de langage visuel en libre accès qui peut traiter des séquences d'images et de texte pour produire des sorties texte, similaires à GPT-4.
Le modèle est construit sur le modèle Flamingo de DeepMind, qui n’est pas accessible au public. IDEFICS utilise des données et des modèles accessibles au public, en particulier LLaMA v1 et OpenCLIP, et est proposé en deux versions : une version de base et une version instruite, chacune disponible en 9 milliards et 80 milliards de tailles de paramètres.
Récemment, IDEFICS2 a été publié. Le modèle est formé pour répondre à des questions sur les images, telles que « De quelle couleur est la voiture ? » ou « Combien de personnes y a-t-il sur la photo ? '. Il peut également décrire du contenu visuel, créer des histoires fondées sur plusieurs images, extraire des informations de documents et effectuer des opérations arithmétiques de base.
Qu’est-ce que le réglage fin ?
Le réglage fin est un processus qui consiste à prendre un modèle pré-entraîné et à le former pour une tâche spécifique à l'aide d'un ensemble de données spécifique. Ce processus implique de mettre à jour les pondérations du modèle en fonction des données de la nouvelle tâche, généralement avec un taux d'apprentissage plus faible, pour effectuer de légers ajustements sans altérer radicalement les connaissances pré-entraînées.
Les modèles pré-entraînés sont généralement formés sur des ensembles de données volumineux et diversifiés et capturent de nombreuses fonctionnalités. Ils sont formés pour bien performer sur une tâche spécifique, telle que l'analyse des sentiments, la classification d'images ou toute application spécifique à un domaine. En utilisant des données spécifiques à la nouvelle tâche, le modèle peut apprendre les nuances et les spécificités de ces données, conduisant ainsi à une précision et des performances améliorées.
Le réglage fin nécessite beaucoup moins de ressources et de temps de calcul que la formation d'un modèle à partir de zéro.
Dans ce cas, nous utiliserons « TheFusion21/PokemonCards » pour affiner le modèle. Voici la structure des données de cet ensemble de données.
{
"id": "pl1-1",
"image_url": "https://images.pokemontcg.io/pl1/1_hires.png",
"caption": "A Stage 2 Pokemon Card of type Lightning with the title ""Ampharos"" and 130 HP of rarity ""Rare Holo"" evolved from Flaaffy from the set Platinum and the flavor text: ""None"". It has the attack ""Gigavolt"" with the cost Lightning, Colorless, the energy cost 2 and the damage of 30+ with the description: ""Flip a coin. If heads, this attack does 30 damage plus 30 more damage. If tails, the Defending Pokemon is now Paralyzed."". It has the attack ""Reflect Energy"" with the cost Lightning, Colorless, Colorless, the energy cost 3 and the damage of 70 with the description: ""Move an Energy card attached to Ampharos to 1 of your Benched Pokemon."". It has the ability ""Damage Bind"" with the description: ""Each Pokemon that has any damage counters on it (both yours and your opponent's) can't use any Poke-Powers."". It has weakness against Fighting +30. It has resistance against Metal -20.",
"name": "Ampharos",
"hp": "130",
"set_name": "Platinum"
}
Installation
Nous allons commencer par installer quelques packages nécessaires. Nous recommandons à nos utilisateurs de cliquer sur le lien fourni avec l'article pour faire tourner le bloc-notes et commencer à travailler.
!pip install -q datasets
!pip install -q git+https://github.com/huggingface/transformers.git
!pip install -q bitsandbytes sentencepiece accelerate loralib
!pip install -q -U git+https://github.com/huggingface/peft.git
!pip install accelerate==0.27.2
Nous allons installer la bibliothèque datasets
. Cette bibliothèque fournit des outils pour accéder et gérer des ensembles de données pour la formation et l'évaluation des modèles d'apprentissage automatique. Nous installons également des transformateurs et des bitsandbytes pour un réglage efficace.
Bitsandbytes est une bibliothèque incroyable qui permet de charger des modèles avec une précision de 4 bits, ce qui la rend extrêmement utile pour affiner de grands modèles de langage avec Qlora.
Une fois ces packages installés avec succès, nous importerons les bibliothèques nécessaires.
#import the libraries
import torch
from datasets import load_dataset
from peft import LoraConfig, get_peft_model
from PIL import Image
from transformers import IdeficsForVisionText2Text, AutoProcessor, Trainer, TrainingArguments, BitsAndBytesConfig
import torchvision.transforms as transforms
Charger le modèle quantifié
Ensuite, nous allons charger la version quantifiée du modèle, alors chargeons le modèle. Nous sélectionnerons l'appareil comme « CUDA » ; si « CUDA » n'est pas disponible, nous utiliserons le CPU.
device = "cuda" if torch.cuda.is_available() else "cpu"
checkpoint = "HuggingFaceM4/idefics-9b"
#load the model in 4-bit precision
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_use_double_quant=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16,
llm_int8_skip_modules=["lm_head", "embed_tokens"],
)
processor = AutoProcessor.from_pretrained(checkpoint, use_auth_token=True)
Nous chargerons le modèle avec une précision de 4 bits, ce qui réduit l'utilisation de la mémoire et peut accélérer le traitement. De plus, nous utiliserons une technique appelée double quantification, une technique qui peut améliorer la précision du modèle quantifié 4 bits. Ensuite, un processeur est initialisé pour gérer les entrées et sorties du modèle à l'aide du point de contrôle pré-entraîné.
model = IdeficsForVisionText2Text.from_pretrained(checkpoint, quantization_config=bnb_config, device_map="auto")
Ce code initialise le modèle IdeficsForVisionText2Text
en chargeant une version pré-entraînée à partir du point de contrôle spécifié. Ensuite, nous appliquerons les paramètres de quantification définis dans bnb_config
pour charger le modèle dans un format de précision efficace de 4 bits.
De plus, le code utilise le mappage automatique des périphériques pour distribuer les composants du modèle sur le matériel disponible, optimisant ainsi les performances et l'utilisation des ressources.
Une fois les téléchargements terminés, nous imprimerons le modèle.
print(model)
Cela imprime l'intégralité du pipeline du modèle avec la couche et les détails d'intégration.
Inférence
Nous utiliserons ce modèle pour l'inférence et testerons le modèle.
def model_inference(model, processor, prompts, max_new_tokens=50):
tokenizer = processor.tokenizer
bad_words = ["<image>", "<fake_token_around_image>"]
if len(bad_words) > 0:
bad_words_ids = tokenizer(bad_words, add_special_tokens=False).input_ids
eos_token = "</s>"
eos_token_id = tokenizer.convert_tokens_to_ids(eos_token)
inputs = processor(prompts, return_tensors="pt").to(device)
generated_ids = model.generate(**inputs, eos_token_id=[eos_token_id], bad_words_ids=bad_words_ids, max_new_tokens=max_new_tokens, early_stopping=True)
generated_text = processor.batch_decode(generated_ids, skip_special_tokens=True)[0]
print(generated_text)
La fonction traite les invites de saisie, génère du texte à l'aide du modèle tout en filtrant les jetons indésirables et imprime le texte résultant. La fonction utilise le tokenizer et le processeur pour gérer la tokenisation du texte et le décodage, ce qui garantit à son tour que le texte généré adhère aux contraintes spécifiées.
url = "https://hips.hearstapps.com/hmg-prod/images/dog-puppy-on-garden-royalty-free-image-1586966191.jpg?crop=0.752xw:1.00xh;0.175xw,0&resize=1200:*"
prompts = [
# "Instruction: provide an answer to the question. Use the image to answer.\n",
url,
"Question: What's on the picture? Answer:",
]
model_inference(model, processor, prompts, max_new_tokens=5)
Source
Question : Qu'y a-t-il sur la photo ? Réponse : Un chiot.
Nous préparerons l’ensemble de données que nous utiliserons pour notre tâche de réglage fin.
def convert_to_rgb(image):
# `image.convert("RGB")` would only work for .jpg images, as it creates a wrong background
# for transparent images. The call to `alpha_composite` handles this case
if image.mode == "RGB":
return image
image_rgba = image.convert("RGBA")
background = Image.new("RGBA", image_rgba.size, (255, 255, 255))
alpha_composite = Image.alpha_composite(background, image_rgba)
alpha_composite = alpha_composite.convert("RGB")
return alpha_composite
def ds_transforms(example_batch):
image_size = processor.image_processor.image_size
image_mean = processor.image_processor.image_mean
image_std = processor.image_processor.image_std
image_transform = transforms.Compose([
convert_to_rgb,
transforms.RandomResizedCrop((image_size, image_size), scale=(0.9, 1.0), interpolation=transforms.InterpolationMode.BICUBIC),
transforms.ToTensor(),
transforms.Normalize(mean=image_mean, std=image_std),
])
prompts = []
for i in range(len(example_batch['caption'])):
# We split the captions to avoid having very long examples, which would require more GPU ram during training
caption = example_batch['caption'][i].split(".")[0]
prompts.append(
[
example_batch['image_url'][i],
f"Question: What's on the picture? Answer: This is {example_batch['name'][i]}. {caption}</s>",
],
)
inputs = processor(prompts, transform=image_transform, return_tensors="pt").to(device)
inputs["labels"] = inputs["input_ids"]
return inputs
load and prepare dataset
ds = load_dataset("TheFusion21/PokemonCards")
ds = ds["train"].train_test_split(test_size=0.002)
train_ds = ds["train"]
eval_ds = ds["test"]
train_ds.set_transform(ds_transforms)
eval_ds.set_transform(ds_transforms)
La fonction convert_to_rgb
garantit que les images sont au format RVB, pour gérer différents types d'images. La fonction ds_transforms
traite un lot d'exemples en transformant les images, en préparant des invites de texte et en convertissant le tout dans un format adapté à la formation ou à l'inférence de modèles. La fonction permet d'appliquer les transformations nécessaires, de tokeniser les invites et de configurer les entrées et les étiquettes pour le modèle.
Nous allons charger les « TheFusion21/PokemonCards » comme suggéré en serrant le visage pour affiner le modèle. Cependant, n'hésitez pas à utiliser n'importe quel ensemble de données avec le format correct.
LoRA
L'adaptation de bas rang (LoRA) est une technique PEFT qui réduit une grande matrice en deux matrices plus petites de bas rang au sein des couches d'attention, réduisant ainsi considérablement le nombre de paramètres nécessitant un réglage fin.
model_name = checkpoint.split("/")[1]
config = LoraConfig(
r=16,
lora_alpha=32,
target_modules=["q_proj", "k_proj", "v_proj"],
lora_dropout=0.05,
bias="none",
)
model = get_peft_model(model, config)
Ce code configure et applique l'adaptation de bas rang (LoRA) à notre modèle IDEFICS9b :
- Extraire le nom du modèle : à partir du point de contrôle, extrayez le modèle.
- Configurer LoRA : définissez les paramètres LoRA, y compris le rang des matrices de bas rang sur 16, les modules cibles, les abandons et la gestion des biais.
- Définir l'abandon : définit un taux d'abandon de 5 % pour LoRA. L'abandon est une technique de régularisation visant à éviter le surajustement en mettant aléatoirement certaines des unités d'entrée à zéro pendant l'entraînement.
- Appliquer LoRA au modèle : modifiez le modèle pour inclure LoRA dans les couches spécifiées avec la configuration fournie.
model.print_trainable_parameters()
paramètres pouvant être entraînés : 19 750 912 || tous les paramètres : 8 949 430 544 || % pouvant être entraîné : 0,2206946230030432
Entraînement
Ensuite, nous affinerons le modèle,
training_args = TrainingArguments(
output_dir=f"{model_name}-pokemon",
learning_rate=2e-4,
fp16=True,
per_device_train_batch_size=2,
per_device_eval_batch_size=2,
gradient_accumulation_steps=8,
dataloader_pin_memory=False,
save_total_limit=3,
evaluation_strategy="steps",
save_strategy="steps",
save_steps=40,
eval_steps=20,
logging_steps=20,
max_steps=20,
remove_unused_columns=False,
push_to_hub=False,
label_names=["labels"],
load_best_model_at_end=True,
report_to=None,
optim="paged_adamw_8bit",
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_ds,
eval_dataset=eval_ds,
)
trainer.train()
Étape
Perte de formation
Perte de validation
20
1.450000
0.880157
40
0.702000
0.675355
Out[23]:TrainOutput(global_step=40, training_loss=1,0759869813919067, metrics={'train_runtime' : 403,1999, 'train_samples_per_second' : 1,587, 'train_steps_per_second' : 0,099, 'total_flos' : 1445219210656320.0, 'train_loss' : 1.0759869813919067, 'époque' : 0.05})
Ce code démarrera le processus de formation en fonction des paramètres spécifiés, tels que le taux d'apprentissage, la précision, la taille des lots, l'accumulation de gradient et la stratégie de pointage de contrôle. Nous utilisons une précision à virgule flottante de 16 bits pour un entraînement plus rapide et plus efficace et utiliserons l'optimiseur pour une précision de 8 bits.
# check generation after finetuning
url = "https://images.pokemontcg.io/pop6/2_hires.png"
prompts = [
url,
"Question: What's on the picture? Answer:",
]
# check generation again after finetuning
check_inference(model, processor, prompts, max_new_tokens=100)
Question : Qu'y a-t-il sur la photo ? Réponse : C'est Lucario. Une Carte Pokémon Stage 2 de type Combat avec le titre Lucario et 90 HP de rareté Rare évolué de Pikachu du set Neo Destiny et le texte d'ambiance : Il peut utiliser sa queue comme fouet
Conclusion
Avec cela, nous sommes arrivés à la fin de l’article. Nous avons pu affiner notre modèle en utilisant avec succès l'ensemble de données Pokémon. Nous pouvons pousser notre modèle à serrer les visages et utiliser le modèle à des fins d'inférence.
Le réglage fin des modèles multimodaux nécessite un équilibre minutieux entre les ressources informatiques et les stratégies de formation pour obtenir les meilleurs résultats.
Le GPU NVIDIA A100 est un excellent choix pour affiner les modèles multimodaux en raison de ses hautes performances, de sa grande capacité de mémoire et de son évolutivité. Ces fonctionnalités permettent une gestion efficace des tâches complexes et à grande échelle impliquées dans l'intégration de données visuelles et textuelles, conduisant à une formation et un déploiement de modèles plus rapides et plus efficaces.
Nous espérons que vous avez apprécié l’article !
Références
- Le cahier a été contribué par Léo Tronchon, Younes Belkada et Stas Bekman. De plus, le modèle IDEFICS a été contribué par : Lucile Saulnier, Léo Tronchon, Hugo Laurençon, Stas Bekman, Amanpreet Singh, Siddharth Karamcheti et Victor Sanh Référence du code
- Présentation d'Idefics2 : un puissant modèle de langage de vision 8B pour la communauté
- Ensemble de données utilisé