- Présantation d'Unsloth : Simplifier le fine-tuning des grands modèles
Avez-vous déjà essayé d'entraîner un grand modèle de langage comme Llama3 ? Vous avez probablement rencontré des défis liés à la consommation de mémoire GPU, à la complexité des configurations ou à la lenteur des processus d'entraînement. Unsloth est une bibliothèque open-source conçue pour résoudre ces problèmes en optimisant les workflows de fine-tuning et d'apprentissage par renforcement.
Elle permet de réduire significativement la consommation de mémoire et d'accélérer les temps d'entraînement, tout en restant entièrement compatible avec l'écosystème Hugging Face. Par exemple, sur une carte A100, elle peut entraîner Llama3-8B deux fois plus vite qu'une configuration standard Hugging Face + PEFT, avec une réduction de 70 % de l'utilisation de la mémoire GPU.
- Vérification de l'environnement avant l'entraînement
Avant d'exécuter le script Python, assurez-vous que votre environnement est correctement configuré. Cela inclut l'activation de l'environnement virtuel et la vérification du bon chargement de la bibliothèque Unsloth.
# Activer l'environnement conda
conda activate unsloth_env
# Vérifier l'installation d'Unsloth
python -m unsloth
- Script complet pour fine-tuner Llama3 avec Unsloth
3.1 Import des modules et configuraton
from unsloth import is_bfloat16_supported
from unsloth import UnslothModel
from transformers import TrainingArguments
from trl import SFTTrainer
from datasets import load_dataset
import torch
# Détection automatique du support de bfloat16
bf16_disponible = is_bfloat16_supported()
# Chemins et paramètres essentiels
NOM_MODELE = "meta-llama/Meta-Llama-3-8B-Instruct"
CHEMIN_DATASET = "./donnees/alpaca_propre.json"
DOSSIER_SORTIE = "./llama3_entraine"
3.2 Chargement du modèle et du tokenizer
modele, tokenizer = UnslothModel.from_pretrained(
model_name = NOM_MODELE,
max_seq_length = 4096,
dtype = None,
load_in_4bit = True,
rope_scaling = {"type": "dynamic", "factor": 2.0},
)
3.3 Préparation du jeu de données
Le format Alpaca est couramment utilisé pour les tâches de génération supervisée. Voici un exemple de données :
[
{
"instruction": "Traduire le texte suivant en anglais",
"input": "Il fait beau aujourd'hui, c'est idéal pour une promenade.",
"output": "Today the weather is nice, perfect for a walk."
}
]
Chargement et formatage :
donnees = load_dataset("json", data_files=CHEMIN_DATASET, split="train")
donnees = donnees.map(
lambda exemples: tokenizer(
[f"<|start_header_id|>system<|end_header_id|>\n\n{instruction}<|eot_id|><|start_header_id|>user<|end_header_id|>\n\n{input_text}<|eot_id|><|start_header_id|>assistant<|end_header_id|>\n\n{output_text}<|eot_id|>"
for instruction, input_text, output_text in zip(exemples["instruction"], exemples["input"], exemples["output"])],
truncation = True,
padding = True,
max_length = 4096,
),
batched = True,
remove_columns = ["instruction", "input", "output"],
)
3.4 Configuration de l'entraînement
args_entrainement = TrainingArguments(
per_device_train_batch_size = 2,
gradient_accumulation_steps = 4,
warmup_steps = 10,
max_steps = 200,
learning_rate = 2e-4,
fp16 = not bf16_disponible,
bf16 = bf16_disponible,
logging_steps = 1,
optim = "adamw_8bit",
weight_decay = 0.01,
lr_scheduler_type = "linear",
seed = 3407,
output_dir = DOSSIER_SORTIE,
report_to = "none",
)
3.5 Lencement de l'entraînement
entraineur = SFTTrainer(
model = modele,
tokenizer = tokenizer,
train_dataset = donnees,
dataset_text_field = "text",
max_seq_length = 4096,
dataset_num_proc = 2,
packing = False,
args = args_entrainement,
)
entraineur.train()
entraineur.save_model(DOSSIER_SORTIE)
- Étapes post-entraînement
4.1 Fusion des poids LoRA
from transformers import AutoModelForCausalLM
from peft import PeftModel
modele_base = AutoModelForCausalLM.from_pretrained(NOM_MODELE, torch_dtype=torch.float16)
modele = PeftModel.from_pretrained(modele_base, DOSSIER_SORTIE)
modele = modele.merge_and_unload()
modele.save_pretrained(DOSSIER_SORTIE + "_fusionne")
tokenizer.save_pretrained(DOSSIER_SORTIE + "_fusionne")
4.2 Test rapide avec pipeline
from transformers import pipeline
pipe = pipeline(
"text-generation",
model = DOSSIER_SORTIE + "_fusionne",
tokenizer = DOSSIER_SORTIE + "_fusionne",
torch_dtype = torch.float16,
device_map = "auto",
)
resultat = pipe("Expliquez les avantages du fine-tuning avec Unsloth", max_new_tokens=128)
print(resultat[0]["generated_text"])
- Résolution des problèmes courants
- Problème de mémoire GPU : Réduisez la taille du batch ou activez le quantization 4-bit.
- La perte ne diminue pas : Vérifiez la qualité des données et la cohérence des templates.
- Unsloth supporte-t-il d'autres modèles ? Oui, comme Qwen, Gemma, ou DeepSeek.