Recette de fine-tuning Phi-3.5-vision

February 1, 2026 · View on GitHub

Ceci est le support officiel pour le fine-tuning de Phi-3.5-vision utilisant les bibliothèques huggingface.
Veuillez cd dans le répertoire de code vision_finetuning avant d’exécuter les commandes suivantes.

Installation

# create a new conda environment
conda create -n phi3v python=3.10
conda activate phi3v

# install pytorch
conda install pytorch==2.1.2 torchvision==0.16.2 torchaudio==2.1.2 pytorch-cuda=12.1 -c pytorch -c nvidia

# other libraries needed to run the example code
pip install -r requirements.txt

# (optional) flash attention -- Ampere+ GPUs (e.g., A100, H100)
pip install ninja
MAX_JOBS=32 pip install flash-attn==2.4.2 --no-build-isolation

# (optional) QLoRA -- Turing+ GPUs (e.g., RTX 8000)
pip install bitsandbytes==0.43.1

Démarrage rapide

Nous fournissons deux scripts d’exemple pour le fine-tuning, un pour DocVQA et un pour la classification de memes haineux.

Matériel minimal testé sur 4x RTX8000 (48 Go de RAM par GPU)

# minimal script on a mini-train split of DocVQA
torchrun --nproc_per_node=4 finetune_hf_trainer_docvqa.py

Phi-3.5-vision supporte désormais officiellement les entrées multi-images. Voici un exemple de fine-tuning sur NLVR2

torchrun --nproc_per_node=8 finetune_hf_trainer_nlvr2.py

Guide d’utilisation

Selon le matériel, les utilisateurs peuvent choisir différentes stratégies de fine-tuning. Nous supportons
le fine-tuning complet (avec Deepspeed Zero-2) avec la possibilité de geler les paramètres vision, ainsi que LoRA (y compris QLoRA 4 bits).
En général, nous recommandons d’utiliser le fine-tuning complet avec flash attention et bf16 dès que possible.

Guide pour convertir votre dataset personnalisé au format requis

Nous utilisons un dataset minimal de classification vidéo (un sous-ensemble de UCF-101) comme exemple complet pour montrer comment convertir votre dataset personnalisé au format requis et fine-tuner Phi-3.5-vision dessus.

# convert data
python convert_ucf101.py --out_dir /path/to/converted_ucf101

# training
torchrun --nproc_per_node=4 finetune_hf_trainer_ucf101.py --data_dir /path/to/converted_ucf101

Les données converties ressembleront à ceci :

> tree --filelimit=10 /path/to/converted_ucf101
/path/to/converted_ucf101
├── images
│   ├── test
│   │   ├── ApplyEyeMakeup [48 entries exceeds filelimit, not opening dir]
│   │   ├── ApplyLipstick [32 entries exceeds filelimit, not opening dir]
│   │   ├── Archery [56 entries exceeds filelimit, not opening dir]
│   │   ├── BabyCrawling [72 entries exceeds filelimit, not opening dir]
│   │   ├── BalanceBeam [32 entries exceeds filelimit, not opening dir]
│   │   ├── BandMarching [72 entries exceeds filelimit, not opening dir]
│   │   ├── BaseballPitch [80 entries exceeds filelimit, not opening dir]
│   │   ├── Basketball [88 entries exceeds filelimit, not opening dir]
│   │   ├── BasketballDunk [48 entries exceeds filelimit, not opening dir]
│   │   └── BenchPress [72 entries exceeds filelimit, not opening dir]
│   ├── train
│   │   ├── ApplyEyeMakeup [240 entries exceeds filelimit, not opening dir]
│   │   ├── ApplyLipstick [240 entries exceeds filelimit, not opening dir]
│   │   ├── Archery [240 entries exceeds filelimit, not opening dir]
│   │   ├── BabyCrawling [240 entries exceeds filelimit, not opening dir]
│   │   ├── BalanceBeam [240 entries exceeds filelimit, not opening dir]
│   │   ├── BandMarching [240 entries exceeds filelimit, not opening dir]
│   │   ├── BaseballPitch [240 entries exceeds filelimit, not opening dir]
│   │   ├── Basketball [240 entries exceeds filelimit, not opening dir]
│   │   ├── BasketballDunk [240 entries exceeds filelimit, not opening dir]
│   │   └── BenchPress [240 entries exceeds filelimit, not opening dir]
│   └── val
│       ├── ApplyEyeMakeup [24 entries exceeds filelimit, not opening dir]
│       ├── ApplyLipstick [24 entries exceeds filelimit, not opening dir]
│       ├── Archery [24 entries exceeds filelimit, not opening dir]
│       ├── BabyCrawling [24 entries exceeds filelimit, not opening dir]
│       ├── BalanceBeam [24 entries exceeds filelimit, not opening dir]
│       ├── BandMarching [24 entries exceeds filelimit, not opening dir]
│       ├── BaseballPitch [24 entries exceeds filelimit, not opening dir]
│       ├── Basketball [24 entries exceeds filelimit, not opening dir]
│       ├── BasketballDunk [24 entries exceeds filelimit, not opening dir]
│       └── BenchPress [24 entries exceeds filelimit, not opening dir]
├── ucf101_test.jsonl
├── ucf101_train.jsonl
└── ucf101_val.jsonl

34 directories, 3 files

Pour l’annotation jsonl, chaque ligne doit être un dictionnaire comme :

{"id": "val-0000000300", "source": "ucf101", "conversations": [{"images": ["val/BabyCrawling/v_BabyCrawling_g21_c04.0.jpg", "val/BabyCrawling/v_BabyCrawling_g21_c04.1.jpg", "val/BabyCrawling/v_BabyCrawling_g21_c04.2.jpg", "val/BabyCrawling/v_BabyCrawling_g21_c04.3.jpg", "val/BabyCrawling/v_BabyCrawling_g21_c04.4.jpg", "val/BabyCrawling/v_BabyCrawling_g21_c04.5.jpg", "val/BabyCrawling/v_BabyCrawling_g21_c04.6.jpg", "val/BabyCrawling/v_BabyCrawling_g21_c04.7.jpg"], "user": "Classify the video into one of the following classes: ApplyEyeMakeup, ApplyLipstick, Archery, BabyCrawling, BalanceBeam, BandMarching, BaseballPitch, Basketball, BasketballDunk, BenchPress.", "assistant": "BabyCrawling"}]}
{"id": "val-0000000301", "source": "ucf101", "conversations": [{"images": ["val/BabyCrawling/v_BabyCrawling_g09_c06.0.jpg", "val/BabyCrawling/v_BabyCrawling_g09_c06.1.jpg", "val/BabyCrawling/v_BabyCrawling_g09_c06.2.jpg", "val/BabyCrawling/v_BabyCrawling_g09_c06.3.jpg", "val/BabyCrawling/v_BabyCrawling_g09_c06.4.jpg", "val/BabyCrawling/v_BabyCrawling_g09_c06.5.jpg", "val/BabyCrawling/v_BabyCrawling_g09_c06.6.jpg", "val/BabyCrawling/v_BabyCrawling_g09_c06.7.jpg"], "user": "Classify the video into one of the following classes: ApplyEyeMakeup, ApplyLipstick, Archery, BabyCrawling, BalanceBeam, BandMarching, BaseballPitch, Basketball, BasketballDunk, BenchPress.", "assistant": "BabyCrawling"}]}

Notez que conversations est une liste, ce qui permet de supporter des conversations multi-tours si ce type de données est disponible.

Demande de quota GPU Azure

Prérequis

Un compte Azure avec le rôle Contributeur (ou un autre rôle incluant l’accès Contributeur).

Si vous n’avez pas de compte Azure, créez un compte gratuit avant de commencer.

Demander une augmentation de quota

Vous pouvez soumettre une demande d’augmentation de quota directement depuis Mes quotas. Suivez les étapes ci-dessous pour demander une augmentation de quota. Pour cet exemple, vous pouvez sélectionner n’importe quel quota ajustable dans votre abonnement.

Connectez-vous au portail Azure.

Tapez "quotas" dans la barre de recherche, puis sélectionnez Quotas.
Quota

Sur la page Aperçu, sélectionnez un fournisseur, comme Compute ou AML.

Note Pour tous les fournisseurs autres que Compute, vous verrez une colonne Demander une augmentation au lieu de la colonne Ajustable décrite ci-dessous. Vous pouvez y demander une augmentation pour un quota spécifique ou créer une demande de support pour cette augmentation.

Sur la page Mes quotas, sous Nom du quota, sélectionnez le quota que vous souhaitez augmenter. Assurez-vous que la colonne Ajustable affiche Oui pour ce quota.

En haut de la page, sélectionnez Nouvelle demande de quota, puis sélectionnez Saisir une nouvelle limite.

Increase Quota

Dans le panneau Nouvelle demande de quota, saisissez une valeur numérique pour votre nouvelle limite de quota, puis cliquez sur Soumettre.

Votre demande sera examinée et vous serez informé si elle peut être satisfaite. Cela se produit généralement en quelques minutes.

Si votre demande n’est pas satisfaite, un lien pour créer une demande de support apparaîtra. En utilisant ce lien, un ingénieur support vous aidera avec votre demande d’augmentation.

Suggestions de SKU de machines GPU Azure Compute

ND A100 v4-series

ND H100 v5-series

Standard_ND40rs_v2

Voici quelques exemples :

Si vous disposez de GPU A100 ou H100

Le fine-tuning complet offre généralement les meilleures performances. Vous pouvez utiliser la commande suivante pour fine-tuner Phi-3-V sur la classification de memes haineux.

torchrun --nproc_per_node=8 --nnodes=<num_nodes> \
  --master_addr=$MASTER_ADDR --master_port=$MASTER_PORT --node_rank=$NODE_RANK \
  finetune_hf_trainer_hateful_memes.py \
  --output_dir <output_dir> \
  --batch_size 64 \
  --use_flash_attention \
  --bf16

Si vous disposez de GPU Standard_ND40rs_v2 8x V100-32GB

Il est toujours possible de fine-tuner complètement Phi-3-V sur la classification de memes haineux. Cependant, attendez-vous à un débit beaucoup plus faible comparé aux GPU A100 ou H100 en raison de l’absence de support pour flash attention.
La précision peut aussi être impactée par l’absence de support bf16 (l’entraînement en précision mixte fp16 est utilisé à la place).

torchrun --nproc_per_node=8 --nnodes=<num_nodes> \
  --master_addr=$MASTER_ADDR --master_port=$MASTER_PORT --node_rank=$NODE_RANK \
  finetune_hf_trainer_hateful_memes.py \
  --output_dir <output_dir> \
  --batch_size 64

Si vous n’avez pas accès à des GPU de centre de données

LoRA pourrait être votre seule option. Vous pouvez utiliser la commande suivante pour fine-tuner Phi-3-V sur la classification de memes haineux.

torchrun --nproc_per_node=2 \
  finetune_hf_trainer_hateful_memes.py \
  --output_dir <output_dir> \
  --batch_size 64 \
  --use_lora

Pour les GPU Turing+ QLoRA est supporté

torchrun --nproc_per_node=2 \
  finetune_hf_trainer_hateful_memes.py \
  --output_dir <output_dir> \
  --batch_size 64 \
  --use_lora \
  --use_qlora

Hyperparamètres suggérés et précision attendue

NLVR2

torchrun --nproc_per_node=4 \
  finetune_hf_trainer_nlvr2.py \
  --bf16 --use_flash_attention \
  --batch_size 64 \
  --output_dir <output_dir> \
  --learning_rate <lr> \
  --num_train_epochs <epochs>

Méthode d’entraînementModèle vision gelétype de donnéesrang LoRAalpha LoRAtaille batchtaux d’apprentissageépoquesPrécision
fine-tuning completbf16--641e-5389.40
fine-tuning completbf16--642e-5289.20
Résultats LoRA à venir

NOTE

Les résultats DocVQA et Hateful memes ci-dessous sont basés sur la version précédente (Phi-3-vision).
Les nouveaux résultats avec Phi-3.5-vision seront mis à jour prochainement.

DocVQA (NOTE : Phi-3-vision)

torchrun --nproc_per_node=4 \
  finetune_hf_trainer_docvqa.py \
  --full_train \
  --bf16 --use_flash_attention \
  --batch_size 64 \
  --output_dir <output_dir> \
  --learning_rate <lr> \
  --num_train_epochs <epochs>

Méthode d’entraînementtype de donnéesrang LoRAalpha LoRAtaille batchtaux d’apprentissageépoquesANLS
fine-tuning completbf16--645e-6283.65
fine-tuning completfp16--645e-6282.60
modèle image gelébf16--641e-4279.19
modèle image geléfp16--641e-4278.74
LoRAbf163216642e-4282.46
LoRAfp163216642e-4282.34
QLoRAbf163216642e-4281.85
QLoRAfp163216642e-4281.85

Hateful memes (NOTE : Phi-3-vision)

torchrun --nproc_per_node=4 \
  finetune_hf_trainer_hateful_memes.py \
  --bf16 --use_flash_attention \
  --batch_size 64 \
  --output_dir <output_dir> \
  --learning_rate <lr> \
  --num_train_epochs <epochs>

Méthode d’entraînementtype de donnéesrang LoRAalpha LoRAtaille batchtaux d’apprentissageépoquesPrécision
fine-tuning completbf16--645e-5286.4
fine-tuning completfp16--645e-5285.4
modèle image gelébf16--641e-4379.4
modèle image geléfp16--641e-4378.6
LoRAbf16128256642e-4286.6
LoRAfp16128256642e-4285.2
QLoRAbf16128256642e-4284.0
QLoRAfp16128256642e-4283.8

Benchmark de vitesse (NOTE : Phi-3-vision)

Les nouveaux résultats de benchmark avec Phi-3.5-vision seront bientôt disponibles.

Le benchmark de vitesse est réalisé sur le dataset DocVQA. La longueur moyenne des séquences de ce dataset est de 2443,23 tokens (en utilisant num_crops=16 pour le modèle image).

8x A100-80GB (Ampere)

Méthode d’entraînement# nœudsGPUsflash attentionTaille batch effectiveDébit (img/s)AccélérationMémoire GPU max (Go)
fine-tuning complet18645.0411x~42
fine-tuning complet18648.6571.72x~36
fine-tuning complet2166416.9033.35x~29
fine-tuning complet4326433.4336.63x~26
modèle image gelé186417.5783.49x~29
modèle image gelé186431.7366.30x~27
LoRA18645.5911.11x~50
LoRA186412.1272.41x~16
QLoRA18644.8310.96x~32
QLoRA186410.5452.09x~10

8x V100-32GB (Volta)

Méthode d’entraînement# nœudsGPUsflash attentionTaille batch effectiveDébit (img/s)AccélérationMémoire GPU max (Go)
fine-tuning complet18642.4621x~32
fine-tuning complet216644.1821.70x~32
fine-tuning complet432645.4652.22x~32
modèle image gelé18648.9423.63x~27
LoRA18642.8071.14x~30

Problèmes connus

  • Impossible d’utiliser flash attention avec fp16 (bf16 est toujours recommandé quand disponible, et tous les GPU supportant flash attention supportent aussi bf16).
  • La sauvegarde des checkpoints intermédiaires et la reprise de l’entraînement ne sont pas encore supportées.

Avertissement :
Ce document a été traduit à l’aide du service de traduction automatique Co-op Translator. Bien que nous nous efforcions d’assurer l’exactitude, veuillez noter que les traductions automatiques peuvent contenir des erreurs ou des inexactitudes. Le document original dans sa langue d’origine doit être considéré comme la source faisant foi. Pour les informations critiques, une traduction professionnelle réalisée par un humain est recommandée. Nous déclinons toute responsabilité en cas de malentendus ou de mauvaises interprétations résultant de l’utilisation de cette traduction.