Accéder au contenu principal

Fine-Tuning Qwen3 : Un guide pas à pas

Un guide étape par étape pour affiner le modèle Qwen3-32B sur l'ensemble de données de raisonnement médical en l'espace d'une heure.
Actualisé 30 avr. 2025  · 8 min de lecture

S'appuyant sur le succès de QwQ et de Qwen2.5Qwen3 représente une avancée majeure en matière de raisonnement, de créativité et de capacités conversationnelles. Avec un accès ouvert aux modèles denses et mélange d'experts (MoE)allant de 0,6B à 235B-A22B, Qwen3 est conçu pour exceller dans un large éventail de tâches.

Dans ce tutoriel, nous allons affiner le modèle Qwen3-32B sur un ensemble de données de raisonnement médical. L'objectif est d'optimiser la capacité du modèle à raisonner et à répondre avec précision aux questions des patients, en veillant à ce qu'il adopte une approche précise et efficace pour répondre aux questions médicales. 

Nous tenons nos lecteurs informés des dernières nouveautés en matière d'IA en leur envoyant The Median, notre lettre d'information gratuite du vendredi qui analyse les principaux sujets de la semaine. Abonnez-vous et restez à la pointe de la technologie en quelques minutes par semaine :

Si vous souhaitez en savoir plus sur le Qwen 3 et ses performances, consultez notre guide d'introduction au modèle, Qwen 3 : Fonctionnalités, comparaison avec DeepSeek-R1, accès, et plus encore.

Affiner les images de caractéristiques de Qwen3

Image par l'auteur

1. Mise en place

Accédez à votre RunPod et assurez-vous d'avoir un minimum de 5 $ sur votre compte. Choisissez ensuite le modèle A100 SXM et sélectionnez la dernière version de PyTorch. Enfin, cliquez sur le bouton "Déployer à la demande" pour lancer votre Pod.

Mise en place du pod Runpod

Source : Mes gousses

Modifiez vos paramètres Pod et ajustez la taille du disque du conteneur à 100 Go. De plus, incluez votre jeton d'accès à Hugging Face en tant que variable d'environnement.

Modification de la variable d'environnement "stockage et paramétrage

Source : Mes gousses

Une fois les paramètres appliqués, cliquez sur "Connect" pour lancer Jupyter Lab. 

Runpod, le pod est en marche

Source : Mes gousses

Jupyter Lab est livré préinstallé avec les paquets et les extensions nécessaires, ce qui vous permet de commencer la formation sans installation supplémentaire.

Runpod, Jupyter Notebook.

Source : Mes gousses

Avant de poursuivre, assurez-vous que tous les paquets Python requis sont installés et à jour. 

Exécutez les commandes suivantes dans une cellule Jupyter Notebook :

%%capture
%pip install -U accelerate 
%pip install -U peft 
%pip install -U trl 
%pip install -U bitsandbytes
%pip install -U transformers

Utilisez le jeton d'accès Hugging Face que vous avez enregistré précédemment pour vous connecter à Hugging Face Hub. 

from huggingface_hub import login
import os

hf_token = os.environ.get("HF_TOKEN")
login(hf_token)

2. Chargement du modèle et du tokenizer

Même si nous disposons de 80 Go de VRAM, nous chargerons le modèle Qwen3 en utilisant une quantification de 4 bits. quantification de 4 bits. Cela nous permettra d'adapter facilement le modèle au GPU et de l'affiner sans problème. 

Téléchargez et chargez le modèle Qwen3-32B et le tokenizer depuis Hugging Face Hub.

from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import torch

bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=False,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16,
)

model_dir = "Qwen/Qwen3-32B"
tokenizer = AutoTokenizer.from_pretrained(model_dir, use_fast=True)
model = AutoModelForCausalLM.from_pretrained(
    model_dir,
    quantization_config=bnb_config,   
    device_map="auto",  
    torch_dtype=torch.bfloat16,
    trust_remote_code=True             
)

model.config.use_cache = False
model.config.pretraining_tp = 1

Téléchargement du modèle et du tokenizer3. Chargement et traitement de l'ensemble de données

Dans cette section, nous nous concentrerons sur le développement d'un style d'invite qui encourage le modèle à s'engager dans une réflexion critique. Nous créerons une structure d'invite qui comprendra une invite système avec des espaces réservés pour la question, une chaîne de pensée et la réponse finale. 

train_prompt_style = """Below is an instruction that describes a task, paired with an input that provides further context. 
Write a response that appropriately completes the request. 
Before answering, think carefully about the question and create a step-by-step chain of thoughts to ensure a logical and accurate response.

### Instruction:
You are a medical expert with advanced knowledge in clinical reasoning, diagnostics, and treatment planning. 
Please answer the following medical question. 

### Question:
{}

### Response:
<think>
{}
</think>
{}"""

Ensuite, nous allons créer la fonction Python qui utilisera le style d'invite de train et lui appliquera la valeur correspondante pour créer la colonne "texte".

EOS_TOKEN = tokenizer.eos_token  # Must add EOS_TOKEN

def formatting_prompts_func(examples):
    inputs = examples["Question"]
    complex_cots = examples["Complex_CoT"]
    outputs = examples["Response"]
    texts = []
    for question, cot, response in zip(inputs, complex_cots, outputs):
        # Append the EOS token to the response if it's not already there
        if not response.endswith(tokenizer.eos_token):
            response += tokenizer.eos_token
        text = train_prompt_style.format(question, cot, response)
        texts.append(text)
    return {"text": texts}

Ensuite, nous chargerons les 2000 premiers échantillons de la base de données de FreedomIntelligence/medical-o1-reasoning-SFT puis nous appliquerons la fonction formatting_prompts_func pour créer la colonne "texte".

from datasets import load_dataset

dataset = load_dataset(
    "FreedomIntelligence/medical-o1-reasoning-SFT",
    "en",
    split="train[0:2000]",
    trust_remote_code=True,
)
dataset = dataset.map(
    formatting_prompts_func,
    batched=True,
)
dataset["text"][10]

Comme vous pouvez le constater, la colonne de texte contient l'invite du système, les instructions, les questions, la chaîne de pensée et les réponses à la question.

11ème échantillon de l'ensemble de données

Le nouvel entraîneur STF n'accepte pas le tokenizer, nous allons donc convertir le tokenizer en un collateur de données à l'aide de la fonction de transformation simple.

from transformers import DataCollatorForLanguageModeling

data_collator = DataCollatorForLanguageModeling(
    tokenizer=tokenizer,
    mlm=False
)

4. Inférence du modèle avant la mise au point

Le style de l'invite à la déduction est différent de celui de l'invite au train. Il comprend tout le style de l'invite de formation, à l'exception de la chaîne de pensée et de la réponse.

inference_prompt_style = """Below is an instruction that describes a task, paired with an input that provides further context. 
Write a response that appropriately completes the request. 
Before answering, think carefully about the question and create a step-by-step chain of thoughts to ensure a logical and accurate response.

### Instruction:
You are a medical expert with advanced knowledge in clinical reasoning, diagnostics, and treatment planning. 
Please answer the following medical question. 

### Question:
{}

### Response:
<think>

"""

Pour tester les performances du modèle avant de l'affiner, nous prendrons le 11e échantillon de l'ensemble de données et le fournirons au modèle après l'avoir formaté et converti en jetons.

question = dataset[10]['Question']
inputs = tokenizer(
    [inference_prompt_style.format(question) + tokenizer.eos_token],
    return_tensors="pt"
).to("cuda")

outputs = model.generate(
    input_ids=inputs.input_ids,
    attention_mask=inputs.attention_mask,
    max_new_tokens=1200,
    eos_token_id=tokenizer.eos_token_id,
    use_cache=True,
)
response = tokenizer.batch_decode(outputs, skip_special_tokens=True)
print(response[0].split("### Response:")[1])

En conséquence, nous avons reçu un long délai de réflexion et aucune réponse, même après l'envoi des 1200 nouveaux jetons. Ceci est très différent de l'ensemble de données, qui est court et concis.

Inférence du modèle avant la mise au point

5. Mise en place du modèle

Nous allons maintenant mettre en œuvre LoRA (Low-Rank Adaptation). La méthode LoRA consiste à geler la majorité des paramètres du modèle et à introduire un petit ensemble de paramètres susceptibles d'être entraînés, qui sont ajoutés sous la forme d'une décomposition de faible rang. Cela permet au modèle de s'adapter à de nouvelles tâches sans qu'il soit nécessaire de mettre à jour ou de stocker l'ensemble des poids du modèle.

Cette approche est économe en mémoire, plus rapide et moins coûteuse, tout en permettant d'obtenir une précision comparable à celle d'un réglage fin complet.

from peft import LoraConfig, get_peft_model

# LoRA config
peft_config = LoraConfig(
    lora_alpha=16,                           # Scaling factor for LoRA
    lora_dropout=0.05,                       # Add slight dropout for regularization
    r=64,                                    # Rank of the LoRA update matrices
    bias="none",                             # No bias reparameterization
    task_type="CAUSAL_LM",                   # Task type: Causal Language Modeling
    target_modules=[
        "q_proj",
        "k_proj",
        "v_proj",
        "o_proj",
        "gate_proj",
        "up_proj",
        "down_proj",
    ],  # Target modules for LoRA
)

model = get_peft_model(model, peft_config)

Nous allons maintenant configurer et initialiser le SFTTrainer (Supervised Fine-Tuning Trainer), une abstraction de haut niveau fournie par les bibliothèques transformers et trl de Hugging Face. Le SFTTrainer simplifie le processus de mise au point en intégrant les composants clés - tels que le jeu de données, le modèle, le collecteur de données, les arguments d'entraînement et la configuration LoRA - dans un flux de travail unique et rationalisé. 

from trl import SFTTrainer
from transformers import TrainingArguments


# Training Arguments
training_arguments = TrainingArguments(
    output_dir="output",
    per_device_train_batch_size=1,
    per_device_eval_batch_size=1,
    gradient_accumulation_steps=2,
    optim="paged_adamw_32bit",
    num_train_epochs=1,
    logging_steps=0.2,
    warmup_steps=10,
    logging_strategy="steps",
    learning_rate=2e-4,
    fp16=False,
    bf16=False,
    group_by_length=True,
    report_to="none"
)

# Initialize the Trainer
trainer = SFTTrainer(
    model=model,
    args=training_arguments,
    train_dataset=dataset,
    peft_config=peft_config,
    data_collator=data_collator,
)

6. Modèle de formation

Avant de commencer l'entraînement, nous allons vider le cache et libérer un peu de RAM et de VRAM du GPU afin d'éviter les problèmes de mémoire défaillante (OOM) pendant le processus d'entraînement. Voici comment nous pouvons y parvenir :

import gc, torch
gc.collect()
torch.cuda.empty_cache()
model.config.use_cache = False
trainer.train()

Lorsque l'entraînement commence, vous remarquerez que votre pod utilise 100 % du GPU et 85 % de la VRAM du GPU. Cela indique que nous avons atteint le point idéal.

Utilisation de la mémoire et du calcul du GPU

L'entraînement a duré 42 minutes et, comme vous pouvez le constater, la perte d'entraînement s'est progressivement réduite.

Perte de formation

7. Inférence du modèle après la mise au point

Nous allons maintenant tester le modèle affiné sur le même échantillon que précédemment et comparer les résultats.

question = dataset[10]['Question']
inputs = tokenizer(
    [inference_prompt_style.format(question) + tokenizer.eos_token],
    return_tensors="pt"
).to("cuda")

outputs = model.generate(
    input_ids=inputs.input_ids,
    attention_mask=inputs.attention_mask,
    max_new_tokens=1200,
    eos_token_id=tokenizer.eos_token_id,
    use_cache=True,
)
response = tokenizer.batch_decode(outputs, skip_special_tokens=True)
print(response[0].split("### Response:")[1])

Nous avons raccourci la section de réflexion et la réponse précise, ce qui correspond à l'ensemble des données. C'est un résultat étonnant.

Inférence de modèle après réglage fin

Testons les performances du Qwen3 affiné sur un autre échantillon de l'ensemble de données.

question = dataset[100]['Question']
inputs = tokenizer(
    [inference_prompt_style.format(question) + tokenizer.eos_token],
    return_tensors="pt"
).to("cuda")

outputs = model.generate(
    input_ids=inputs.input_ids,
    attention_mask=inputs.attention_mask,
    max_new_tokens=1200,
    eos_token_id=tokenizer.eos_token_id,
    use_cache=True,
)
response = tokenizer.batch_decode(outputs, skip_special_tokens=True)
print(response[0].split("### Response:")[1])

Une fois de plus, le processus de réflexion a été précis et court, et la réponse a été exacte, comme dans l'ensemble des données.

Inférence de modèle après réglage fin

Si vous avez des difficultés à régler votre modèle Qwen3, veuillez consulter le cahier d'accompagnement : réglage-qwen-3.

8. Sauvegarde du modèle 

L'étape finale consiste à enregistrer le modèle et le tokenizer et à les télécharger vers le hub Hugging Face, ce qui nous permet de construire une application ou de partager le modèle avec la communauté open-source. 

new_model_name = "Qwen-3-32B-Medical-Reasoning"
model.push_to_hub(new_model_name)
tokenizer.push_to_hub(new_model_name)

Une fois le modèle et le tokenizer téléchargés, un lien vers le référentiel sera généré. Par exemple : kingabzpro/Qwen-3-32B-Medical-Reasoning - Hugging Face

kingabzpro/Qwen-3-32B-Medical-Reasoning Mode repository on the Hugging face

Source : kingabzpro/Qwen-3-32B-Raisonnement médical

Le référentiel de modèles contient les balises appropriées, une description, un cahier d'accompagnement et tous les fichiers nécessaires pour que vous puissiez les charger et les tester vous-même.

Conclusion

Qwen-3 représente une autre étape importante vers la démocratisation de l'IA. Vous pouvez facilement télécharger Qwen-3, l'exécuter sur votre PC (sans accès à Internet), le peaufiner ou même l'héberger sur votre serveur local. Qwen-3 incarne véritablement les principes de l'IA ouverte.

Dans ce tutoriel, nous avons appris à affiner le modèle Qwen-3 sur un ensemble de données de raisonnement médical à l'aide de la plateforme Runpod. Fait remarquable, l'ensemble du processus a coûté moins de 3 dollars. Pour améliorer encore les performances de votre réglage fin, vous pouvez entraîner le modèle sur l'ensemble des données pendant au moins 3 époques.

Vous pouvez en savoir plus sur le modèle Qwen 3 grâce à notre guide, Qwen 3 : Fonctionnalités, comparaison avec DeepSeek-R1, accès, et plus encore. Vous pouvez également consulter nos guides sur Comment utiliser Qwen 2.4-VL en local ? et Ajustement de DeepSeek R1 (modèle de raisonnement).


Abid Ali Awan's photo
Author
Abid Ali Awan
LinkedIn
Twitter

En tant que data scientist certifié, je suis passionné par l'utilisation des technologies de pointe pour créer des applications innovantes d'apprentissage automatique. Avec une solide expérience en reconnaissance vocale, en analyse de données et en reporting, en MLOps, en IA conversationnelle et en NLP, j'ai affiné mes compétences dans le développement de systèmes intelligents qui peuvent avoir un impact réel. En plus de mon expertise technique, je suis également un communicateur compétent, doué pour distiller des concepts complexes dans un langage clair et concis. En conséquence, je suis devenu un blogueur recherché dans le domaine de la science des données, partageant mes idées et mes expériences avec une communauté grandissante de professionnels des données. Actuellement, je me concentre sur la création et l'édition de contenu, en travaillant avec de grands modèles linguistiques pour développer un contenu puissant et attrayant qui peut aider les entreprises et les particuliers à tirer le meilleur parti de leurs données.

Sujets

Les meilleurs cours de DataCamp

Cursus

Developing Large Language Models

16hrs hr
Learn to develop large language models (LLMs) with PyTorch and Hugging Face, using the latest deep learning and NLP techniques.
Afficher les détailsRight Arrow
Commencer le cours
Voir plusRight Arrow
Apparenté

blog

Les 50 meilleures questions et réponses d'entretien sur AWS pour 2025

Un guide complet pour explorer les questions d'entretien AWS de base, intermédiaires et avancées, ainsi que des questions basées sur des situations réelles.
Zoumana Keita 's photo

Zoumana Keita

15 min

blog

Architecture de l'entrepôt de données : Tendances, outils et techniques

Apprenez l'essentiel de l'architecture d'un entrepôt de données, des composants clés aux meilleures pratiques, pour construire un système de données évolutif et efficace !
Kurtis Pykes 's photo

Kurtis Pykes

15 min

blog

Q2 2023 DataCamp Donates Digest

DataCamp Donates a offert plus de 20k bourses d'études à nos partenaires à but non lucratif au deuxième trimestre 2023. Découvrez comment des apprenants défavorisés et assidus ont transformé ces opportunités en réussites professionnelles qui ont changé leur vie.
Nathaniel Taylor-Leach's photo

Nathaniel Taylor-Leach

blog

Les 20 meilleures questions d'entretien pour les flocons de neige, à tous les niveaux

Vous êtes actuellement à la recherche d'un emploi qui utilise Snowflake ? Préparez-vous à répondre à ces 20 questions d'entretien sur le flocon de neige pour décrocher le poste !
Nisha Arya Ahmed's photo

Nisha Arya Ahmed

15 min

blog

2022-2023 Rapport annuel DataCamp Classrooms

À l'aube de la nouvelle année scolaire, DataCamp Classrooms est plus motivé que jamais pour démocratiser l'apprentissage des données, avec plus de 7 650 nouveaux Classrooms ajoutés au cours des 12 derniers mois.
Nathaniel Taylor-Leach's photo

Nathaniel Taylor-Leach

8 min

blog

Célébration de Saghar Hazinyar : Une boursière de DataCamp Donates et une diplômée de Code to Inspire

Découvrez le parcours inspirant de Saghar Hazinyar, diplômée de Code to Inspire, qui a surmonté les défis en Afghanistan et s'est épanouie grâce à une bourse de DataCamp Donates.
Fereshteh Forough's photo

Fereshteh Forough

4 min

Voir plusVoir plus