Transformers documentation

Classification d'images

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Classification d'images

La classification d’images consiste à attribuer une étiquette ou une classe à une image. Contrairement à la classification de texte ou d’audio, les entrées sont les valeurs de pixels qui composent une image. La classification d’images présente de nombreuses applications, telles que la détection des dommages après une catastrophe naturelle, le suivi de la santé des cultures ou l’aide au dépistage d’images médicales pour détecter des signes de maladie.

Ce guide illustre comment :

  1. Effectuez le fine-tuning de ViT sur le jeu de données Food-101 pour classifier un aliment présent dans une image.
  2. Utilisez votre modèle affiné pour l'inférence.

Pour consulter toutes les architectures et points de contrôle compatibles avec cette tâche, nous vous recommandons de consulter la page de la tâche

Avant de commencer, assurez-vous d'avoir installé toutes les bibliothèques nécessaires :

pip install transformers datasets evaluate accelerate pillow torchvision scikit-learn trackio

Nous vous encourage à vous connecter à votre compte Hugging Face pour téléverser et partager votre modèle avec la communauté. Lorsque le système vous le demande, saisissez votre jeton pour vous connecter :

>>> from huggingface_hub import notebook_login

>>> notebook_login()

Charger le jeu de données Food-101

Commencez par charger un sous-ensemble plus petit du jeu de données Food-101 à partir de la bibliothèque 🤗 Datasets. Cela vous permettra de faire des essais et de vous assurer que tout fonctionne correctement avant de consacrer plus de temps à l’entraînement sur l’ensemble complet du jeu de données.

>>> from datasets import load_dataset

>>> food = load_dataset("ethz/food101", split="train[:5000]")

Divisez le split train du jeu de données en un ensemble d’entraînement et un ensemble de test à l’aide de la méthode train_test_split :

>>> food = food.train_test_split(test_size=0.2)

Puis, jetez un œil à un exemple :

>>> food["train"][0]
{'image': <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=512x512 at 0x7F52AFC8AC50>,
 'label': 79}

Chaque exemple du jeu de données comporte deux champs :

  • image : une image PIL de l’aliment
  • label : la classe d'étiquette de l'article alimentaire

Pour faciliter la récupération du nom de l'étiquette à partir de l'identifiant de l'étiquette par le modèle, créez un dictionnaire qui associe le nom de l'étiquette à un entier et vice versa :

>>> labels = food["train"].features["label"].names
>>> label2id, id2label = dict(), dict()
>>> for i, label in enumerate(labels):
...     label2id[label] = str(i)
...     id2label[str(i)] = label

Vous pouvez maintenant convertir l'identifiant de la classe en nom de classe :

>>> id2label[str(79)]
'prime_rib'

Prétraitement

L'étape suivante consiste à charger un processeur d'images ViT afin de convertir l'image en tenseur :

>>> from transformers import AutoImageProcessor

>>> checkpoint = "google/vit-base-patch16-224-in21k"
>>> image_processor = AutoImageProcessor.from_pretrained(checkpoint)

Appliquez des transformations d’images aux images afin de rendre le modèle plus robuste face au surapprentissage. Vous utiliserez ici le module transforms de torchvision, mais vous pouvez également utiliser n’importe quelle bibliothèque d’images de votre choix.

Recouper une partie aléatoire de l'image, la redimensionner, puis la normaliser à l'aide de la moyenne et de l'écart-type de l'image :

>>> from torchvision.transforms import RandomResizedCrop, Compose, Normalize, ToTensor

>>> normalize = Normalize(mean=image_processor.image_mean, std=image_processor.image_std)
>>> size = (
...     image_processor.size["shortest_edge"]
...     if "shortest_edge" in image_processor.size
...     else (image_processor.size["height"], image_processor.size["width"])
... )
>>> _transforms = Compose([RandomResizedCrop(size), ToTensor(), normalize])

Créez ensuite une fonction de prétraitement pour appliquer les transformations et retourner les pixel_values — les entrées du modèle — de l'image :

>>> def transforms(examples):
...     examples["pixel_values"] = [_transforms(img.convert("RGB")) for img in examples["image"]]
...     del examples["image"]
...     return examples

Pour appliquer la fonction de prétraitement à l’ensemble du jeu de données, utilisez la méthode with_transform de 🤗 Datasets. Les transformations sont appliquées à la volée lors du chargement d’un élément du jeu de données :

>>> food = food.with_transform(transforms)

Créez maintenant un lot d’exemples à l’aide de DefaultDataCollator. Contrairement aux autres collators de données de 🤗 Transformers, DefaultDataCollator n’applique pas de prétraitement supplémentaire tel que le padding.

>>> from transformers import DefaultDataCollator

>>> data_collator = DefaultDataCollator()

Évaluer

Inclure une métrique pendant l’entraînement est souvent utile pour évaluer les performances de votre modèle. Vous pouvez charger rapidement une méthode d’évaluation avec la bibliothèque 🤗 Evaluate. Pour cette tâche, chargez la métrique accuracy (consultez le quick tour de 🤗 Evaluate pour en savoir plus sur la façon de charger et de calculer une métrique) :

>>> import evaluate

>>> accuracy = evaluate.load("accuracy")

Créez ensuite une fonction qui transmet vos prédictions et vos étiquettes à compute pour calculer la précision :

>>> import numpy as np


>>> def compute_metrics(eval_pred):
...     predictions, labels = eval_pred
...     predictions = np.argmax(predictions, axis=1)
...     return accuracy.compute(predictions=predictions, references=labels)

Votre fonction compute_metrics est prête, et vous y reviendrez lors de la configuration de l’entraînement.

Entraînement

Si vous n’êtes pas familier avec l’ajustement fin d’un modèle à l’aide du Trainer, consultez le tutoriel de base ici !

Vous êtes prêt à démarrer l’entraînement de votre modèle ! Chargez ViT avec AutoModelForImageClassification. Spécifiez le nombre de classes ainsi que le nombre de classes attendues, et les correspondances des étiquettes :

>>> from transformers import AutoModelForImageClassification, TrainingArguments, Trainer

>>> model = AutoModelForImageClassification.from_pretrained(
...     checkpoint,
...     num_labels=len(labels),
...     id2label=id2label,
...     label2id=label2id,
... )

À ce stade, il ne reste que trois étapes :

  1. Définissez vos hyperparamètres d’entraînement dans TrainingArguments. Il est important de ne pas supprimer les colonnes inutilisées, car cela ferait disparaître la colonne image. Sans la colonne image, vous ne pouvez pas créer pixel_values. Définissez remove_unused_columns=False pour éviter ce comportement ! Le seul autre paramètre requis est output_dir, qui spécifie l’endroit où enregistrer votre modèle. Vous pousserez ce modèle vers le Hub en définissant push_to_hub=True (vous devez être connecté à Hugging Face pour téléverser votre modèle). À la fin de chaque époque, le Trainer évaluera la précision et enregistrera le point de contrôle d’entraînement.
  2. Transmettez les arguments d’entraînement à Trainer en même temps que le modèle, le jeu de données, le tokenizer, le data collator et la fonction compute_metrics.
  3. Appel de train() pour l’ajustement fin de votre modèle.
>>> training_args = TrainingArguments(
...     output_dir="my_awesome_food_model",
...     remove_unused_columns=False,
...     eval_strategy="epoch",
...     save_strategy="epoch",
...     learning_rate=5e-5,
...     per_device_train_batch_size=16,
...     gradient_accumulation_steps=4,
...     per_device_eval_batch_size=16,
...     num_train_epochs=3,
...     warmup_steps=0.1,
...     logging_steps=10,
...     report_to="trackio",
...     run_name="food101",
...     load_best_model_at_end=True,
...     metric_for_best_model="accuracy",
...     push_to_hub=True,
... )

>>> trainer = Trainer(
...     model=model,
...     args=training_args,
...     data_collator=data_collator,
...     train_dataset=food["train"],
...     eval_dataset=food["test"],
...     processing_class=image_processor,
...     compute_metrics=compute_metrics,
... )

>>> trainer.train()

Une fois l’entraînement terminé, partagez votre modèle sur le Hub à l’aide de la méthode push_to_hub() afin que chacun puisse l’utiliser :

>>> trainer.push_to_hub()

Pour un exemple plus approfondi sur la façon d’affiner un modèle pour la classification d’images, consultez le notebook PyTorch correspondant.

Inférence

Parfait, maintenant que vous avez affiné un modèle, vous pouvez l'utiliser pour l'inférence !

Chargez une image sur laquelle vous souhaitez effectuer une inférence :

>>> ds = load_dataset("ethz/food101", split="validation[:10]")
>>> image = ds["image"][0]
image of beignets

La manière la plus simple de tester votre modèle finement ajusté pour l’inférence est de l’utiliser dans un pipeline(). Instanciez un pipeline pour la classification d’images avec votre modèle, puis passez-lui votre image :

>>> from transformers import pipeline

>>> classifier = pipeline("image-classification", model="my_awesome_food_model")
>>> classifier(image)
[{'score': 0.31856709718704224, 'label': 'beignets'},
 {'score': 0.015232225880026817, 'label': 'bruschetta'},
 {'score': 0.01519392803311348, 'label': 'chicken_wings'},
 {'score': 0.013022331520915031, 'label': 'pork_chop'},
 {'score': 0.012728818692266941, 'label': 'prime_rib'}]

Vous pouvez également reproduire manuellement les résultats de pipeline si vous le souhaitez :

Chargez un processeur d’images pour prétraiter l’image et renvoyer l’input sous forme de tenseurs PyTorch :

>>> from transformers import AutoImageProcessor
>>> import torch

>>> image_processor = AutoImageProcessor.from_pretrained("my_awesome_food_model")
>>> inputs = image_processor(image, return_tensors="pt")

Passez vos entrées au modèle et renvoyez les logits :

>>> from transformers import AutoModelForImageClassification

>>> model = AutoModelForImageClassification.from_pretrained("my_awesome_food_model")
>>> with torch.no_grad():
...     logits = model(**inputs).logits

Obtenez l'étiquette prédite ayant la probabilité la plus élevée, et utilisez le mapping id2label du modèle pour la convertir en étiquette :

>>> predicted_label = logits.argmax(-1).item()
>>> model.config.id2label[predicted_label]
'beignets'
Update on GitHub