Tutoriel : Entraîner un modèle de classification ML.NET pour catégoriser des images
Découvrez comment entraîner un modèle de classification pour catégoriser des images à l’aide d’un modèle TensorFlow préentraîné pour le traitement d’images.
Le modèle TensorFlow a été entraîné pour catégoriser les images en mille catégories. Étant donné que le modèle TensorFlow sait comment reconnaître des modèles dans des images, le modèle ML.NET peut utiliser une partie de celui-ci dans son pipeline pour convertir des images brutes en caractéristiques ou entrées pour entraîner un modèle de classification.
Dans ce tutoriel, vous allez apprendre à :
- Comprendre le problème
- Incorporer le modèle TensorFlow préentraîné dans le pipeline ML.NET
- Entraîner et évaluer le modèle ML.NET
- Classifier une image de test
Vous trouverez le code source de ce tutoriel dans le référentiel dotnet/samples. Par défaut, la configuration de projet .NET pour ce tutoriel cible .NET Core 2.2.
Prérequis
- Visual Studio 2022
- Le fichier .zip du répertoire de ressources du tutoriel
- Le modèle Machine Learning InceptionV1
Sélectionner la bonne tâche de machine learning
Apprentissage approfondi
Le Deep Learning est un sous-ensemble du Machine Learning, qui révolutionne des domaines comme la Vision par ordinateur et la Reconnaissance vocale.
L’entraînement des modèles Deep Learning s’effectue à l’aide de grands ensembles de données étiquetées et de réseaux neuronaux comportant plusieurs couches d’apprentissage. Le Deep Learning présente différentes caractéristiques :
- Il fonctionne mieux sur certaines tâches comme la Vision par ordinateur.
- Nécessite d’énormes quantités de données d’entraînement.
La classification d’images est une tâche de classification spécifique qui nous permet de classifier automatiquement des images en catégories comme :
- détecter ou non la présence d’un visage dans une image ;
- détecter des chats ou des chiens.
On peut également, comme dans les images suivantes, déterminer si une image représente un aliment, un jouet ou un appareil :
Notes
Les images précédentes appartiennent à Wikimedia Commons et sont attribuées ainsi :
- « 220px-Pepperoni_pizza.jpg », domaine public, https://commons.wikimedia.org/w/index.php?curid=79505 ;
- « 119px-Nalle_-_a_small_brown_teddy_bear.jpg », de Jonik (photographie personnelle), CC BY-SA 2.0, https://commons.wikimedia.org/w/index.php?curid=48166 ;
- « 193px Broodrooster.jpg », de M. Minderhoud (travail personnel), CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=27403.
Pour entraîner un modèle de Classification d’images à partir de zéro, il faut définir des millions de paramètres, disposer d’une multitude de données d’apprentissage étiquetées et posséder une grande quantité de ressources de calcul (des centaines d’heures GPU). S’il n’est pas aussi efficace que l’apprentissage d’un modèle personnalisé à partir de zéro, l’utilisation d’un modèle préentraîné permet de raccourcir ce processus : il s’agit de travailler avec des milliers (et non des millions) d’images étiquetées et de créer assez vite un modèle personnalisé (en une heure sur un ordinateur sans GPU). Ce tutoriel met à l’échelle ce processus encore davantage, en utilisant seulement une douzaine d’images d’entraînement.
Inception model
est entraîné pour classer des images dans un millier de catégories, mais pour ce tutoriel, nous devons les classer exclusivement dans un plus petit jeu de catégories. Vous pouvez utiliser la capacité de Inception model
à identifier et à classer des images aux nouvelles catégories, en nombre limité, de votre classifieur d’images personnalisé.
- Aliment
- Jouet
- Appliance
Ce tutoriel utilise le modèle Deep Learning TensorFlow Inception, un modèle de reconnaissance d’image populaire entraîné sur le jeu de données ImageNet
. Le modèle TensorFlow catégorise les images entières en mille classes, comme « Umbrella », « Jersey » et « Dishwasher ».
Étant donné que Inception model
a déjà été préentraîné sur des milliers d’images différentes, en interne, il contient les caractéristiques des images nécessaires à leur identification. Nous pouvons utiliser ces fonctionnalités d’image internes dans le modèle pour entraîner un nouveau modèle avec beaucoup moins de classes.
Comme le montre le diagramme suivant, vous ajoutez une référence aux packages NuGet ML.NET dans vos applications .NET Core ou .NET Framework. En coulisses, ML.NET inclut la bibliothèque native TensorFlow
qui permet d’écrire du code afin de charger un fichier de modèle TensorFlow
existant.
Classification multiclasse
Après avoir utilisé le modèle d’origine TensorFlow pour extraire des caractéristiques appropriées en tant qu’entrée pour un algorithme Machine Learning classique, nous ajoutons un classifieur multiclasse ML.NET.
Le formateur spécifique utilisé dans ce cas est l’algorithme de régression logistique multinomiale.
L’algorithme implémenté par ce formateur fonctionne bien sur les problèmes avec un grand nombre de caractéristiques, ce qui est le cas pour un modèle Deep Learning fonctionnant sur des données d’image.
Pour plus d’informations, consultez Deep Learning et Machine Learning.
Données
Il y a deux sources de données : le fichier .tsv
et les fichiers image. Le fichier tags.tsv
comporte deux colonnes : la première est définie comme ImagePath
et la deuxième est le Label
correspondant à l’image. L’exemple de fichier suivant ne possède pas de ligne d’en-tête :
broccoli.jpg food
pizza.jpg food
pizza2.jpg food
teddy2.jpg toy
teddy3.jpg toy
teddy4.jpg toy
toaster.jpg appliance
toaster2.png appliance
Les images d’apprentissage et de test se trouvent dans les dossiers de ressources que vous allez télécharger dans un fichier zip. Elles appartiennent à Wikimedia Commons.
Wikimedia Commons, le dépôt de fichiers multimédias sous licence libre. Récupéré le 17 octobre 2018 à 10 h 48 aux adresses : https://commons.wikimedia.org/wiki/Pizzahttps://commons.wikimedia.org/wiki/Toasterhttps://commons.wikimedia.org/wiki/Teddy_bear
Programme d’installation
Création d’un projet
Créer une application console C# appelée « TransferLearningTF ». Cliquez sur le bouton Suivant.
Choisissez .NET 6 comme framework à utiliser. Cliquez sur le bouton Créer.
Installez le package NuGet Microsoft.ML :
Notes
Cet exemple utilise la dernière version stable des packages NuGet mentionnés, sauf indication contraire.
- Dans l'Explorateur de solutions, cliquez avec le bouton droit sur votre projet, puis sélectionnez Gérer les packages NuGet.
- Choisissez « nuget.org » comme source du package, sélectionnez l’onglet Parcourir et recherchez Microsoft.ML.
- Sélectionnez le bouton Installer.
- Sélectionnez le bouton OK dans la boîte de dialogue Aperçu des modifications.
- Sélectionnez le bouton J’accepte dans la boîte de dialogue Acceptation de la licence si vous acceptez les termes du contrat de licence pour les packages de la liste.
- Répétez ces étapes pour Microsoft.ML.ImageAnalytics, SciSharp.TensorFlow.Redist et Microsoft.ML.TensorFlow.
Télécharger les éléments multimédias
Téléchargez le fichier zip du répertoire de ressources du projet et décompressez-le.
Copiez le répertoire
assets
dans votre répertoire de projet TransferLearningTF. Ce répertoire et ses sous-répertoires contiennent les fichiers de données et d’aide nécessaires à ce tutoriel (sauf pour le modèle Inception, que vous allez télécharger et ajouter à l’étape suivante).Téléchargez le modèle Inception et décompressez-le.
Copiez le contenu décompressé du répertoire
inception5h
dans le répertoireassets/inception
de votre projet TransferLearningTF. Ce répertoire contient le modèle et les fichiers d’aide supplémentaires nécessaires à ce tutoriel, comme le montre l’image suivante :Dans l’Explorateur de solutions, cliquez sur chacun des fichiers du répertoire et des sous-répertoires de ressources et sélectionnez Propriétés. Sous Avancé, définissez la valeur Copier dans le répertoire de sortie sur Copier si plus récent.
Créer des classes et définir des chemins
Ajoutez les instructions
using
supplémentaires suivantes en haut du fichier Program.cs :using Microsoft.ML; using Microsoft.ML.Data;
Ajoutez le code suivant à la ligne située en dessous des instructions using pour spécifier les chemins d’accès aux ressources :
string _assetsPath = Path.Combine(Environment.CurrentDirectory, "assets"); string _imagesFolder = Path.Combine(_assetsPath, "images"); string _trainTagsTsv = Path.Combine(_imagesFolder, "tags.tsv"); string _testTagsTsv = Path.Combine(_imagesFolder, "test-tags.tsv"); string _predictSingleImage = Path.Combine(_imagesFolder, "toaster3.jpg"); string _inceptionTensorFlowModel = Path.Combine(_assetsPath, "inception", "tensorflow_inception_graph.pb");
Créez des classes pour les données d’entrée et les prédictions.
public class ImageData { [LoadColumn(0)] public string? ImagePath; [LoadColumn(1)] public string? Label; }
ImageData
est la classe de données d’images d’entrée, qui comprend les champs String suivants :ImagePath
contient le nom du fichier image.Label
contient la valeur de l’étiquette d’image.
Ajoutez une nouvelle classe à votre projet pour
ImagePrediction
:public class ImagePrediction : ImageData { public float[]? Score; public string? PredictedLabelValue; }
ImagePrediction
est la classe de prédiction des images, qui comprend les champs suivants :Score
contient le pourcentage de confiance d’une classification d’image donnée.PredictedLabelValue
contient la valeur de l’étiquette de classification d’image prédite.
ImagePrediction
représente la classe utilisée pour la prédiction, une fois le modèle formé. Elle comporte unestring
(ImagePath
) correspondant au chemin de l’image.Label
sert à réutiliser et à entraîner le modèle. L’attributPredictedLabelValue
est utilisé pendant la prédiction et l’évaluation. L’évaluation utilise une entrée avec les données d’apprentissage, les valeurs prédites et le modèle.
Initialiser les variables
Initialiser la variable
mlContext
avec une nouvelle instance deMLContext
. Remplacez la ligneConsole.WriteLine("Hello World!")
par le code suivant :MLContext mlContext = new MLContext();
La classe MLContext est un point de départ pour toutes les opérations ML.NET, et l’initialisation de
mlContext
crée un environnement ML.NET qui peut être partagé par les objets de flux de travail de création de modèle. Sur le plan conceptuel, elle est similaire àDBContext
dans Entity Framework.
Créer un struct pour les paramètres du modèle Inception
Le modèle Inception comporte plusieurs paramètres qu’il faut passer. Créez un struct permettant de mapper les valeurs de paramètre sur les noms conviviaux avec le code suivant, juste après l’initialisation de la variable
mlContext
:struct InceptionSettings { public const int ImageHeight = 224; public const int ImageWidth = 224; public const float Mean = 117; public const float Scale = 1; public const bool ChannelsLast = true; }
Créer une méthode d’utilitaire d’affichage
Étant donné que vous allez afficher les données d’image et les prédictions associées plusieurs fois, créez une méthode d’utilitaire d’affichage qui gère l’affichage des données d’image et des résultats de prédiction.
Créez la méthode
DisplayResults()
juste après le structInceptionSettings
avec le code suivant :void DisplayResults(IEnumerable<ImagePrediction> imagePredictionData) { }
Renseignez le corps de la méthode
DisplayResults
:foreach (ImagePrediction prediction in imagePredictionData) { Console.WriteLine($"Image: {Path.GetFileName(prediction.ImagePath)} predicted as: {prediction.PredictedLabelValue} with score: {prediction.Score?.Max()} "); }
Créer une méthode pour effectuer une prédiction
Créez la méthode
ClassifySingleImage()
juste avant la méthodeDisplayResults()
, en utilisant le code suivant :void ClassifySingleImage(MLContext mlContext, ITransformer model) { }
Créez un objet
ImageData
contenant le chemin complet et le nom de fichier d’image de l’uniqueImagePath
. Ajoutez le code suivant à la fin de la méthodeClassifySingleImage()
:var imageData = new ImageData() { ImagePath = _predictSingleImage };
Effectuez une prédiction unique en ajoutant le code suivant comme ligne suivante dans la méthode
ClassifySingleImage
:// Make prediction function (input = ImageData, output = ImagePrediction) var predictor = mlContext.Model.CreatePredictionEngine<ImageData, ImagePrediction>(model); var prediction = predictor.Predict(imageData);
Pour obtenir la prédiction, utilisez la méthode Predict(). PredictionEngine est une API utile qui vous permet d’exécuter une prédiction sur une seule instance de données.
PredictionEngine
n’est pas thread-safe. Il est acceptable de l’utiliser dans des environnements monothreads ou prototypes. Pour améliorer les performances et la sécurité des threads dans les environnements de production, utilisez le servicePredictionEnginePool
, qui crée unObjectPool
d’objetsPredictionEngine
à utiliser dans votre application. Consultez ce guide sur l’utilisation dePredictionEnginePool
dans une API web ASP.NET Core.Notes
L’extension de service
PredictionEnginePool
est disponible en préversion.Affichez le résultat de la prédiction à la fin de la méthode
ClassifySingleImage()
:Console.WriteLine($"Image: {Path.GetFileName(imageData.ImagePath)} predicted as: {prediction.PredictedLabelValue} with score: {prediction.Score?.Max()} ");
Construire le pipeline de modèle ML.NET
Un pipeline de modèle ML.NET est une chaîne d’estimateurs. Aucune exécution ne se produit pendant la construction du pipeline. Les objets estimateurs sont créés, mais non exécutés.
Ajouter une méthode pour générer le modèle
Cette méthode est au cœur du tutoriel. Elle crée un pipeline pour le modèle et entraîne le pipeline pour produire le modèle ML.NET. Elle évalue également le modèle par rapport à certaines données de test précédemment invisibles.
Créez la méthode
GenerateModel()
, juste après le structInceptionSettings
et juste avant la méthodeDisplayResults()
, avec le code suivant :ITransformer GenerateModel(MLContext mlContext) { }
Ajoutez les estimateurs pour charger, redimensionner et extraire les pixels des données d’image :
IEstimator<ITransformer> pipeline = mlContext.Transforms.LoadImages(outputColumnName: "input", imageFolder: _imagesFolder, inputColumnName: nameof(ImageData.ImagePath)) // The image transforms transform the images into the model's expected format. .Append(mlContext.Transforms.ResizeImages(outputColumnName: "input", imageWidth: InceptionSettings.ImageWidth, imageHeight: InceptionSettings.ImageHeight, inputColumnName: "input")) .Append(mlContext.Transforms.ExtractPixels(outputColumnName: "input", interleavePixelColors: InceptionSettings.ChannelsLast, offsetImage: InceptionSettings.Mean))
Les données d’image doivent être traitées dans le format attendu par le modèle TensorFlow. Dans ce cas, les images sont chargées en mémoire, redimensionnées à une taille cohérente, et les pixels sont extraits dans un vecteur numérique.
Ajoutez l’estimateur pour charger le modèle TensorFlow et le noter :
.Append(mlContext.Model.LoadTensorFlowModel(_inceptionTensorFlowModel). ScoreTensorFlowModel(outputColumnNames: new[] { "softmax2_pre_activation" }, inputColumnNames: new[] { "input" }, addBatchDimensionInput: true))
Cette étape du pipeline charge le modèle TensorFlow en mémoire, puis traite le vecteur des valeurs de pixels via le réseau du modèle TensorFlow. L’application d’entrées à un modèle Deep Learning et la génération d’une sortie à l’aide du modèle sont appelées scoring. Lorsque vous utilisez le modèle dans son intégralité, le scoring effectue une inférence ou une prédiction.
Dans ce cas, vous utilisez tout le modèle TensorFlow, à l’exception de la dernière couche, qui est la couche qui effectue l’inférence. La sortie de l’avant-dernière couche est étiquetée
softmax_2_preactivation
. La sortie de cette couche est en fait un vecteur de caractéristiques qui caractérisent les images d’entrée d’origine.Ce vecteur de caractéristiques généré par le modèle TensorFlow sera utilisé comme entrée dans un algorithme d’apprentissage ML.NET.
Ajoutez l’estimateur pour mapper les étiquettes de chaîne dans les données d’apprentissage aux valeurs de clé entières :
.Append(mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "LabelKey", inputColumnName: "Label"))
Le formateur ML.NET qui est ajouté à la suite nécessite que ses étiquettes soient au format
key
plutôt que des chaînes arbitraires. Une clé est un nombre qui a un mappage un-à-un à une valeur de chaîne.Ajoutez l’algorithme d’entraînement ML.NET :
.Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName: "LabelKey", featureColumnName: "softmax2_pre_activation"))
Ajoutez l’estimateur pour mapper la valeur de clé prédite dans une chaîne :
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabelValue", "PredictedLabel")) .AppendCacheCheckpoint(mlContext);
Entraîner le modèle
Chargez les données d’apprentissage à l’aide du wrapper LoadFromTextFile. Ajoutez le code suivant comme première ligne de la méthode
GenerateModel()
:IDataView trainingData = mlContext.Data.LoadFromTextFile<ImageData>(path: _trainTagsTsv, hasHeader: false);
Les données dans ML.NET sont représentées en tant qu’interface IDataView.
IDataView
est un moyen flexible et efficace de décrire des données tabulaires (numériques et texte). Les données peuvent être chargées à partir d’un fichier texte ou en temps réel (par exemple, fichiers journaux ou de base de données SQL) dans un objetIDataView
.Effectuez l’apprentissage du modèle avec les données chargées ci-dessus :
ITransformer model = pipeline.Fit(trainingData);
La méthode
Fit()
entraîne votre modèle en appliquant le jeu de données d’entraînement au pipeline.
Évaluer la précision du modèle
Chargez et transformez les données de test en ajoutant le code suivant à la ligne suivante de la méthode
GenerateModel
:IDataView testData = mlContext.Data.LoadFromTextFile<ImageData>(path: _testTagsTsv, hasHeader: false); IDataView predictions = model.Transform(testData); // Create an IEnumerable for the predictions for displaying results IEnumerable<ImagePrediction> imagePredictionData = mlContext.Data.CreateEnumerable<ImagePrediction>(predictions, true); DisplayResults(imagePredictionData);
Il existe quelques exemples d’images que vous pouvez utiliser pour évaluer le modèle. Comme les données d’entraînement, celles-ci doivent être chargées dans un
IDataView
, afin qu’elles puissent être transformées par le modèle.Ajoutez le code suivant à la méthode
GenerateModel()
pour évaluer le modèle :MulticlassClassificationMetrics metrics = mlContext.MulticlassClassification.Evaluate(predictions, labelColumnName: "LabelKey", predictedLabelColumnName: "PredictedLabel");
Une fois la prédiction définie, la méthode Evaluate() :
- Évalue le modèle (compare les valeurs prédites avec le jeu de données de test
labels
). - Retourne les indicateurs de performances du modèle.
- Évalue le modèle (compare les valeurs prédites avec le jeu de données de test
Afficher les métriques de précision du modèle
Utilisez le code suivant pour afficher les métriques, partager les résultats et agir dessus :
Console.WriteLine($"LogLoss is: {metrics.LogLoss}"); Console.WriteLine($"PerClassLogLoss is: {String.Join(" , ", metrics.PerClassLogLoss.Select(c => c.ToString()))}");
Les indicateurs suivants sont évalués pour la classification d’images :
Log-loss
(voir Perte logarithmique). Vous voulez que la perte logarithmique soit aussi proche de zéro que possible.Per class Log-loss
. La perte logarithmique doit être aussi proche de zéro que possible.
Ajoutez le code suivant pour retourner le modèle entraîné à la ligne suivante :
return model;
Exécutez l’application !
Ajoutez l’appel à
GenerateModel
après la création de la classe MLContext :ITransformer model = GenerateModel(mlContext);
Ajoutez l’appel à la méthode
ClassifySingleImage()
après l’appel à la méthodeGenerateModel()
:ClassifySingleImage(mlContext, model);
Exécutez votre application console (Ctrl + F5). Vous devriez obtenir les résultats suivants. (Des messages d’avertissement ou de traitement peuvent s’afficher, mais nous les avons supprimés dans les résultats suivants pour plus de clarté.)
=============== Training classification model =============== Image: broccoli2.jpg predicted as: food with score: 0.8955513 Image: pizza3.jpg predicted as: food with score: 0.9667718 Image: teddy6.jpg predicted as: toy with score: 0.9797683 =============== Classification metrics =============== LogLoss is: 0.0653774699265059 PerClassLogLoss is: 0.110315812569315 , 0.0204391272836966 , 0 =============== Making single image classification =============== Image: toaster3.jpg predicted as: appliance with score: 0.9646884
Félicitations ! Vous avez maintenant créé un modèle de classification dans ML.NET pour catégoriser les images à l’aide d’un TensorFlow préentraîné pour le traitement des images.
Vous trouverez le code source de ce tutoriel dans le référentiel dotnet/samples.
Dans ce didacticiel, vous avez appris à :
- Comprendre le problème
- Incorporer le modèle TensorFlow préentraîné dans le pipeline ML.NET
- Entraîner et évaluer le modèle ML.NET
- Classifier une image de test
Consultez le référentiel GitHub d’exemples Machine Learning pour voir un exemple développé de classification d’images.