> For the complete documentation index, see [llms.txt](https://unsloth.ai/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://unsloth.ai/docs/fr/notions-de-base/vision-fine-tuning.md).

# Fine-tuning vision

Découvrez comment fine-tuner des LLM de vision/multimodaux avec Unsloth

Le fine-tuning des modèles de vision permet au modèle d’exceller dans certaines tâches où les LLM classiques ne seront pas aussi performants, comme la détection d’objets/de mouvements. **Vous pouvez aussi entraîner** [**des VLM avec RL**](/docs/fr/commencer/reinforcement-learning-rl-guide/vision-reinforcement-learning-vlm-rl.md)**.** Nous avons de nombreux notebooks gratuits pour le fine-tuning de la vision :

* [**Qwen3-VL**](/docs/fr/modeles/tutorials/qwen3-how-to-run-and-fine-tune/qwen3-vl-how-to-run-and-fine-tune.md) **(8B) Vision :** [**Notebook**](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Qwen3_VL_\(8B\)-Vision.ipynb)
* [**Ministral 3**](/docs/fr/modeles/tutorials/ministral-3.md): fine-tuning de la vision pour les questions-réponses générales : [Notebook](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Pixtral_\(12B\)-Vision.ipynb)\
  On peut concaténer des jeux de données de questions-réponses générales avec des jeux de données plus de niche afin d’éviter que le fine-tuning n’oublie les compétences du modèle de base.
* **Gemma 3 (4B) Vision :** [Notebook](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Gemma3_\(4B\)-Vision.ipynb)
* **Llama 3.2 Vision** fine-tuning pour la radiographie : [Notebook](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Llama3.2_\(11B\)-Vision.ipynb)\
  Comment pouvons-nous aider les professionnels de santé à analyser plus rapidement les radiographies, les scanners CT et les échographies.
* **Qwen2.5 VL** fine-tuning pour convertir l’écriture manuscrite en LaTeX : [Notebook](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Qwen2.5_VL_\(7B\)-Vision.ipynb)\
  Cela permet de transcrire facilement des formules mathématiques complexes en LaTeX, sans les écrire manuellement.

{% hint style="info" %}
Il est préférable de s’assurer que votre jeu de données contient des images toutes de la même taille/dimensions. Utilisez des dimensions de 300 à 1000 px pour éviter que l’entraînement ne prenne trop de temps ou n’utilise trop de ressources.
{% endhint %}

### Désactivation du fine-tuning Vision / texte seul

Pour fine-tuner des modèles de vision, nous vous permettons désormais de sélectionner quelles parties du modèle fine-tuner. Vous pouvez choisir de fine-tuner uniquement les couches de vision, ou les couches de langage, ou les couches d’attention / MLP ! Nous les activons toutes par défaut !

```python
model = FastVisionModel.get_peft_model(
    model,
    finetune_vision_layers     = True, # False si vous n'ajustez pas finement les couches de vision
    finetune_language_layers   = True, # False si vous n'ajustez pas finement les couches de langage
    finetune_attention_modules = True, # False si vous n'ajustez pas finement les couches d'attention
    finetune_mlp_modules       = True, # False si vous n'ajustez pas finement les couches MLP

    r = 16,                           # plus la valeur est grande, plus la précision est élevée, mais il peut y avoir surapprentissage
    lora_alpha = 16,                  # alpha recommandé = r au minimum
    lora_dropout = 0,
    bias = "none",
    random_state = 3407,
    use_rslora = False,               # Nous prenons en charge LoRA stabilisée en rang
    loftq_config = None,               # Et LoftQ
    target_modules = "all-linear",    # Optionnel maintenant ! Peut spécifier une liste si nécessaire
    modules_to_save=[
        "lm_head",
        "embed_tokens",
    ],
)
```

### Collateur de données pour la vision

Nous avons un collateur de données spécial rien que pour les jeux de données de vision :

{% code overflow="wrap" %}

```python
from unsloth.trainer import UnslothVisionDataCollator
from trl import SFTTrainer, SFTConfig
trainer = SFTTrainer(
    model = model,
    tokenizer = tokenizer,
    data_collator = UnslothVisionDataCollator(model, tokenizer),
    train_dataset = dataset,
    args = SFTConfig(...),
)
```

{% endcode %}

Et les arguments du collateur de données sont :

{% code expandable="true" %}

```python
class UnslothVisionDataCollator:
def __init__(
self,
model,
processor,
max_seq_length  = None, # [Facultatif] Nous le récupérons automatiquement depuis `FastVisionModel.from_pretrained(max_seq_length = ...)`
formatting_func = None, # Fonction de transformation du texte
resize = "min", # Peut être (10, 10) ou "min" pour redimensionner afin de correspondre à la taille d'image par défaut du modèle, ou "max"
                # pour ne pas redimensionner et laisser l’image intacte
ignore_index = -100, # [Facultatif] La valeur par défaut est -100

# from unsloth.chat_templates import train_on_responses_only
# trainer = train_on_responses_only(
#     trainer,
#     instruction_part = "<|start_header_id|>user<|end_header_id|>\n\n",
#     response_part = "<|start_header_id|>assistant<|end_header_id|>\n\n",
# )
train_on_responses_only = False, # ÉQUIVALENT à train_on_responses_only pour les LLM
instruction_part = None, # ÉQUIVALENT à train_on_responses_only(instruction_part = ...)
response_part    = None, # ÉQUIVALENT à train_on_responses_only(response_part = ...)
force_match      = True, # Faire correspondre aussi les retours à la ligne !

num_proc         = None, # [Facultatif] Sélectionnera automatiquement le nombre de GPU
completion_only_loss = True, # [Facultatif] Ignore les tokens de vision de remplissage - devrait toujours être True !
pad_to_multiple_of = None, # [Facultatif] Pour le remplissage du collateur de données
resize_dimension = 0, # peut être 0, 1, 'max' ou 'min'
                      # (max redimensionne selon le maximum entre la hauteur et la largeur, min selon la taille minimale, 0 selon la première dimension, etc.)
snap_to_patch_size = False, # [Facultatif] Force l’image à être un multiple de la taille du patch
)
```

{% endcode %}

### Entraînement multi-image

Pour fine-tuner ou entraîner des modèles avec plusieurs images, le changement le plus simple est de remplacer :

```python
ds_converted = ds.map(
    convert_to_conversation,
)
```

avec :

```python
ds_converted = [convert_to_conversation(sample) for sample in dataset]
```

L’utilisation de map déclenche la standardisation du jeu de données et les règles de traitement Arrow, qui peuvent être strictes et plus compliquées à définir.

### Jeu de données pour le fine-tuning de la vision

Le jeu de données pour fine-tuner un modèle de vision ou multimodal est similaire à une paire standard de questions-réponses [bibliothèque ](/docs/fr/commencer/fine-tuning-llms-guide/datasets-guide.md), mais cette fois, il inclut aussi des entrées d’images. Par exemple, le [Notebook Vision Llama 3.2](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Llama3.2_\(11B\)-Vision.ipynb#scrollTo=vITh0KVJ10qX) utilise un cas de radiographie pour montrer comment l'IA peut aider les professionnels de santé à analyser plus efficacement les radiographies, les scanners et les échographies.

Nous utiliserons une version échantillonnée du jeu de données de radiographie ROCO. Vous pouvez accéder au jeu de données [ici](https://www.google.com/url?q=https%3A%2F%2Fhuggingface.co%2Fdatasets%2Funsloth%2FRadiology_mini). Le jeu de données comprend des radiographies, des scanners et des échographies illustrant des affections et maladies médicales. Chaque image possède une légende rédigée par des experts la décrivant. L'objectif est d'ajuster finement un VLM pour en faire un outil d'analyse utile aux professionnels de santé.

Jetons un coup d'œil au jeu de données et voyons ce que montre le 1er exemple :

```
Dataset({
    features: ['image', 'image_id', 'caption', 'cui'],
    num_rows: 1978
})
```

| Image                                                                                                                                                                                                                                                                             | Légende                                                                                                                                                               |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <div><figure><img src="https://550366147-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2Fgit-blob-97d4489827403bd4795494f33d01a10979788c30%2Fxray.png?alt=media" alt="" width="164"><figcaption></figcaption></figure></div> | La radiographie panoramique montre une lésion ostéolytique dans la partie postérieure droite du maxillaire avec résorption du plancher du sinus maxillaire (flèches). |

Pour formater le jeu de données, toutes les tâches d'ajustement fin vision doivent être formatées comme suit :

```python
[
{ "role": "user",
  "content": [{"type": "text",  "text": instruction}, {"type": "image", "image": image} ]
},
{ "role": "assistant",
  "content": [{"type": "text",  "text": réponse} ]
},
]
```

Nous allons élaborer une instruction personnalisée demandant au VLM d'être un radiographe expert. Notez aussi qu'au lieu d'une seule instruction, vous pouvez ajouter plusieurs tours pour en faire une conversation dynamique.

{% code expandable="true" %}

```notebook-python
instruction = "Vous êtes un radiographe expert. Décrivez avec précision ce que vous voyez dans cette image."

def convert_to_conversation(sample):
    conversation = [
        { "role": "user",
          "content" : [
            {"type" : "text",  "text"  : instruction},
            {"type" : "image", "image" : sample["image"]} ]
        },
        { "role" : "assistant",
          "content" : [
            {"type" : "text",  "text"  : sample["caption"]} ]
        },
    ]
    return { "messages" : conversation }
pass
```

{% endcode %}

Convertissons le jeu de données au format "correct" pour l'ajustement fin :

```notebook-python
converted_dataset = [convert_to_conversation(sample) for sample in dataset]
```

Le premier exemple est maintenant structuré comme ci-dessous :

```notebook-python
converted_dataset[0]
```

{% code overflow="wrap" %}

```
{'messages': [{'role': 'user',
   'content': [{'type': 'text',
     'text': 'Vous êtes un radiographe expert. Décrivez avec précision ce que vous voyez dans cette image.'},
    {'type': 'image',
     'image': <PIL.PngImagePlugin.PngImageFile image mode=L size=657x442>}]},
  {'role': 'assistant',
   'content': [{'type': 'text',
     'text': 'La radiographie panoramique montre une lésion ostéolytique dans la partie postérieure droite du maxillaire avec résorption du plancher du sinus maxillaire (flèches).'}]}]}
```

{% endcode %}

Avant de faire un quelconque ajustement fin, peut-être que le modèle vision sait déjà analyser les images ? Vérifions si c'est le cas !

{% code expandable="true" %}

```notebook-python
FastVisionModel.for_inference(model) # Activer pour l'inférence !

image = dataset[0]["image"]
instruction = "Vous êtes un radiographe expert. Décrivez avec précision ce que vous voyez dans cette image."

messages = [
    {"role": "user", "content": [
        {"type": "image"},
        {"type": "text", "text": instruction}
    ]}
]
input_text = tokenizer.apply_chat_template(messages, add_generation_prompt = True)
inputs = tokenizer(
    image,
    input_text,
    add_special_tokens = False,
    return_tensors = "pt",
).to("cuda")

from transformers import TextStreamer
text_streamer = TextStreamer(tokenizer, skip_prompt = True)
_ = model.generate(**inputs, streamer = text_streamer, max_new_tokens = 128,
                   use_cache = True, temperature = 1.5, min_p = 0.1)
```

{% endcode %}

Et voici le résultat :

```
Cette radiographie semble être une vue panoramique de la dentition supérieure et inférieure, plus précisément une orthopantomographie (OPG).

* La radiographie panoramique montre des structures dentaires normales.
* Il y a une zone anormale en haut à droite, représentée par une zone d'os radiotransparent, correspondant à l'antre.

**Observations clés**

* L'os entre les dents supérieures gauches est relativement radio-opaque.
* Il y a deux grandes flèches au-dessus de l'image, suggérant la nécessité d'examiner cette zone de plus près. L'une des flèches est du côté gauche, et l'autre est du côté droit. Cependant, seulement
```

Pour plus de détails, consultez notre section jeux de données dans le [notebook ici](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Llama3.2_\(11B\)-Vision.ipynb#scrollTo=vITh0KVJ10qX).

### &#x20;:mag\_right:Entraînement uniquement sur les réponses de l'assistant pour les modèles de vision, VLM

Pour les modèles de langage, nous pouvons utiliser `from unsloth.chat_templates import train_on_responses_only` comme décrit précédemment. Pour les modèles de vision, utilisez les arguments supplémentaires dans `UnslothVisionDataCollator` tout comme auparavant ! Voir [#vision-data-collator](#vision-data-collator "mention") pour plus de détails sur l’utilisation du collateur de données de vision.

{% code overflow="wrap" %}

```python
class UnslothVisionDataCollator:
def __init__(
    self,
    ...
    # from unsloth.chat_templates import train_on_responses_only
    # trainer = train_on_responses_only(
    #     trainer,
    #     instruction_part = "<|start_header_id|>user<|end_header_id|>\n\n",
    #     response_part = "<|start_header_id|>assistant<|end_header_id|>\n\n",
    # )
    train_on_responses_only = False, # ÉQUIVALENT à train_on_responses_only pour les LLM
    instruction_part = None, # ÉQUIVALENT à train_on_responses_only(instruction_part = ...)
    response_part    = None, # ÉQUIVALENT à train_on_responses_only(response_part = ...)
    force_match      = True, # Faire correspondre aussi les retours à la ligne !
)
```

{% endcode %}

Par exemple pour Llama 3.2 Vision :

```python
UnslothVisionDataCollator(
    model, tokenizer,
    ...
    train_on_responses_only = True,
    instruction_part = "<|start_header_id|>user<|end_header_id|>\n\n",
    response_part = "<|start_header_id|>assistant<|end_header_id|>\n\n",
    ...
)
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://unsloth.ai/docs/fr/notions-de-base/vision-fine-tuning.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
