Partager via


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

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 :

image de pizzaimage de nounoursimage de grille-pain

Notes

Les images précédentes appartiennent à Wikimedia Commons et sont attribuées ainsi :

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.

Diagramme ML.NET de transformation TensorFlow

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

  1. Créer une application console C# appelée « TransferLearningTF ». Cliquez sur le bouton Suivant.

  2. Choisissez .NET 6 comme framework à utiliser. Cliquez sur le bouton Créer.

  3. 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

  1. Téléchargez le fichier zip du répertoire de ressources du projet et décompressez-le.

  2. 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).

  3. Téléchargez le modèle Inception et décompressez-le.

  4. Copiez le contenu décompressé du répertoire inception5h dans le répertoire assets/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 :

    Contenu du répertoire Inception

  5. 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

  1. Ajoutez les instructions using supplémentaires suivantes en haut du fichier Program.cs :

    using Microsoft.ML;
    using Microsoft.ML.Data;
    
  2. 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");
    
  3. 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.
  4. 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 une string (ImagePath) correspondant au chemin de l’image. Label sert à réutiliser et à entraîner le modèle. L’attribut PredictedLabelValue 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

  1. Initialiser la variable mlContext avec une nouvelle instance de MLContext. Remplacez la ligne Console.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

  1. 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.

  1. Créez la méthode DisplayResults() juste après le struct InceptionSettings avec le code suivant :

    void DisplayResults(IEnumerable<ImagePrediction> imagePredictionData)
    {
    
    }
    
  2. 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

  1. Créez la méthode ClassifySingleImage() juste avant la méthode DisplayResults(), en utilisant le code suivant :

    void ClassifySingleImage(MLContext mlContext, ITransformer model)
    {
    
    }
    
  2. Créez un objet ImageData contenant le chemin complet et le nom de fichier d’image de l’unique ImagePath. Ajoutez le code suivant à la fin de la méthode ClassifySingleImage() :

    var imageData = new ImageData()
    {
        ImagePath = _predictSingleImage
    };
    
  3. 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 service PredictionEnginePool, qui crée un ObjectPool d’objets PredictionEngine à utiliser dans votre application. Consultez ce guide sur l’utilisation de PredictionEnginePool dans une API web ASP.NET Core.

    Notes

    L’extension de service PredictionEnginePool est disponible en préversion.

  4. 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.

  1. 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 struct InceptionSettings et juste avant la méthode DisplayResults(), avec le code suivant :

    ITransformer GenerateModel(MLContext mlContext)
    {
    
    }
    
  2. 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.

  3. 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.

  4. 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.

  5. Ajoutez l’algorithme d’entraînement ML.NET :

    .Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName: "LabelKey", featureColumnName: "softmax2_pre_activation"))
    
  6. 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

  1. 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 objet IDataView.

  2. 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

  1. 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.

  2. 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.
  3. 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.
  4. Ajoutez le code suivant pour retourner le modèle entraîné à la ligne suivante :

    return model;
    

Exécutez l’application !

  1. Ajoutez l’appel à GenerateModel après la création de la classe MLContext :

    ITransformer model = GenerateModel(mlContext);
    
  2. Ajoutez l’appel à la méthode ClassifySingleImage() après l’appel à la méthode GenerateModel() :

    ClassifySingleImage(mlContext, model);
    
  3. 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.