Tutoriel : Analyser les sentiments des critiques de films en utilisant un modèle TensorFlow préentraîné dans ML.NET

Ce tutoriel vous montre comment utiliser un modèle TensorFlow préentraîné pour classifier les sentiments dans les commentaires d’un site web. Le classifieur de sentiments binaires est une application console C# développée en utilisant Visual Studio.

Le modèle TensorFlow utilisé dans ce tutoriel a été entraîné en utilisant des évaluations de films provenant de la base de données IMDB. Une fois que vous avez terminé le développement de l’application, vous pourrez fournir un texte d’évaluation d’un film et l’application vous indiquera si cette évaluation a un sentiment positif ou négatif.

Dans ce tutoriel, vous allez apprendre à :

  • Charger un modèle TensorFlow préentraîné
  • Transformer le texte des commentaires d’un site web en caractéristiques convenant au modèle
  • Utiliser le modèle pour effectuer une prédiction

Vous trouverez le code source de ce tutoriel dans le référentiel dotnet/samples.

Prérequis

  • Visual Studio 2022 avec la charge de travail « Développement .NET Desktop » installée.

Programme d’installation

Création de l'application

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

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

  3. Créez un répertoire nommé Data dans votre projet pour enregistrer les fichiers du jeu de données.

  4. 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. Recherchez Microsoft.ML, sélectionnez le package souhaité, puis sélectionnez le bouton Installer. Poursuivez l’installation en acceptant les termes du contrat de licence pour le package choisi. Répétez ces étapes pour Microsoft.ML.TensorFlow, Microsoft.ML.SampleUtils et SciSharp.TensorFlow.Redist.

Ajouter le modèle TensorFlow au projet

Notes

Le modèle pour ce tutoriel provient du dépôt GitHub dotnet/machinelearning-testdata. Le modèle est au format TensorFlow SavedModel.

  1. Téléchargez le fichier zip sentiment_model, puis décompressez-le.

    Le fichier .zip contient :

    • saved_model.pb : le modèle TensorFlow lui-même. Le modèle prend un tableau d’entiers de longueur fixe (taille de 600) de caractéristiques représentant le texte dans une chaîne d’évaluation IMDB et génère deux probabilités dont la somme est égale à 1 : la probabilité que l’évaluation en entrée ait un sentiment positif et la probabilité que l’évaluation en entrée ait un sentiment négatif.
    • imdb_word_index.csv : un mappage de mots individuels à une valeur entière. Le mappage est utilisé pour générer les caractéristiques d’entrée pour le modèle TensorFlow.
  2. Copiez le contenu du répertoire sentiment_model le plus interne dans le répertoire sentiment_model de votre projet TextClassificationTF. 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 sentiment_model

  3. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur chacun des fichiers du répertoire sentiment_model et des sous-répertoires, 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.

Ajouter des instructions using et des variables globales

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

    using Microsoft.ML;
    using Microsoft.ML.Data;
    using Microsoft.ML.Transforms;
    
  2. Créez une variable globale juste après les instructions using pour y placer le chemin du fichier de modèle enregistré.

    string _modelPath = Path.Combine(Environment.CurrentDirectory, "sentiment_model");
    
    • _modelPath est le chemin du fichier du modèle entraîné.

Modéliser les données

Les évaluations des films sont du texte de forme libre. Votre application convertit le texte au format d’entrée attendu par le modèle au cours de plusieurs étapes discrètes.

La première consiste à diviser le texte en mots distincts et à utiliser le fichier de mappage fourni pour mapper chaque mot à un code représenté par un entier. Le résultat de cette transformation est un tableau d’entiers de longueur variable, dont la longueur correspond au nombre de mots de la phrase.

Propriété Valeur Type
ReviewText ce film est vraiment bon string
VariableLengthFeatures 14,22,9,66,78,... int[]

Le tableau de caractéristiques de longueur variable est ensuite redimensionné avec une longueur fixe de 600. C’est la longueur attendue par le modèle TensorFlow.

Propriété Valeur Type
ReviewText ce film est vraiment bon string
VariableLengthFeatures 14,22,9,66,78,... int[]
Fonctionnalités 14,22,9,66,78,... int[600]
  1. Créez une classe pour vos données d’entrée dans le bas du fichier Program.cs :

    /// <summary>
    /// Class to hold original sentiment data.
    /// </summary>
    public class MovieReview
    {
        public string? ReviewText { get; set; }
    }
    

    La classe de données d’entrée, MovieReview, a une string pour les commentaires de l’utilisateur (ReviewText).

  2. Créez une classe pour les caractéristiques de longueur variable après la classe MovieReview :

    /// <summary>
    /// Class to hold the variable length feature vector. Used to define the
    /// column names used as input to the custom mapping action.
    /// </summary>
    public class VariableLength
    {
        /// <summary>
        /// This is a variable length vector designated by VectorType attribute.
        /// Variable length vectors are produced by applying operations such as 'TokenizeWords' on strings
        /// resulting in vectors of tokens of variable lengths.
        /// </summary>
        [VectorType]
        public int[]? VariableLengthFeatures { get; set; }
    }
    

    La propriété VariableLengthFeatures a un attribut VectorType pour la désigner comme vecteur. Tous les éléments du vecteur doivent être du même type. Dans les jeux de données comportant un grand nombre de colonnes, le chargement de plusieurs colonnes sous forme de vecteur unique réduit le nombre de passes dans les données quand vous appliquez des transformations de données.

    Cette classe est utilisée dans l’action ResizeFeatures. Les noms de ses propriétés (une seule dans le cas présent) sont utilisés pour indiquer les colonnes de la DataView qui peuvent être utilisées comme entrée dans l’action de mappage personnalisé.

  3. Créez une classe pour les caractéristiques de longueur fixe, après la classe VariableLength :

    /// <summary>
    /// Class to hold the fixed length feature vector. Used to define the
    /// column names used as output from the custom mapping action,
    /// </summary>
    public class FixedLength
    {
        /// <summary>
        /// This is a fixed length vector designated by VectorType attribute.
        /// </summary>
        [VectorType(Config.FeatureLength)]
        public int[]? Features { get; set; }
    }
    

    Cette classe est utilisée dans l’action ResizeFeatures. Les noms de ses propriétés (une seule dans le cas présent) sont utilisés pour indiquer les colonnes de la DataView qui peuvent être utilisées comme sortie dans l’action de mappage personnalisé.

    Notez que le nom de la propriété Features est déterminé par le modèle TensorFlow. Vous ne pouvez pas changer le nom de cette propriété.

  4. Créez une classe pour la prédiction après la classe FixedLength :

    /// <summary>
    /// Class to contain the output values from the transformation.
    /// </summary>
    public class MovieReviewSentimentPrediction
    {
        [VectorType(2)]
        public float[]? Prediction { get; set; }
    }
    

    MovieReviewSentimentPrediction est la classe de prédiction utilisée après l’entraînement du modèle. MovieReviewSentimentPrediction a un seul tableau float (Prediction) et un attribut VectorType.

  5. Créez une autre classe destinées à contenir des valeurs de configuration, comme la longueur du vecteur de caractéristiques :

    static class Config
    {
        public const int FeatureLength = 600;
    }
    

Créer le MLContext, le dictionnaire de recherche et l’action pour redimensionner les caractéristiques

La classe MLContext constitue un point de départ pour toutes les opérations ML.NET. L’initialisation de mlContext crée un environnement ML.NET qui peut être partagé par les objets du workflow de création de modèle. Sur le plan conceptuel, elle est similaire à DBContext dans Entity Framework.

  1. Remplacez la ligne Console.WriteLine("Hello World!") par le code suivant pour déclarer et initialiser la variable mlContext :

    MLContext mlContext = new MLContext();
    
  2. Créez un dictionnaire pour coder les mots sous forme d’entiers en utilisant la méthode LoadFromTextFile pour charger les données de mappage à partir d’un fichier, comme indiqué dans le tableau suivant :

    Word Index
    kids 362
    vouloir 181
    wrong (mauvais) 355
    effects 302
    feeling (sentiment) 547

    Ajoutez le code ci-dessous pour créer le mappage de recherche :

    var lookupMap = mlContext.Data.LoadFromTextFile(Path.Combine(_modelPath, "imdb_word_index.csv"),
        columns: new[]
            {
                new TextLoader.Column("Words", DataKind.String, 0),
                new TextLoader.Column("Ids", DataKind.Int32, 1),
            },
        separatorChar: ','
        );
    
  3. Ajoutez une Action pour redimensionner le tableau d’entiers de longueur variable (représentant des mots) en un tableau d’entiers de taille fixe, avec les lignes de code suivantes :

    Action<VariableLength, FixedLength> ResizeFeaturesAction = (s, f) =>
    {
        var features = s.VariableLengthFeatures;
        Array.Resize(ref features, Config.FeatureLength);
        f.Features = features;
    };
    

Charger le modèle TensorFlow préentraîné

  1. Ajoutez du code pour charger le modèle TensorFlow :

    TensorFlowModel tensorFlowModel = mlContext.Model.LoadTensorFlowModel(_modelPath);
    

    Une fois le modèle chargé, vous pouvez extraire son schéma d’entrée et de sortie. Les schémas sont affichés seulement à titre d’information pour vous permettre de les découvrir. Vous n’avez pas besoin de ce code pour que l’application finale fonctionne :

    DataViewSchema schema = tensorFlowModel.GetModelSchema();
    Console.WriteLine(" =============== TensorFlow Model Schema =============== ");
    var featuresType = (VectorDataViewType)schema["Features"].Type;
    Console.WriteLine($"Name: Features, Type: {featuresType.ItemType.RawType}, Size: ({featuresType.Dimensions[0]})");
    var predictionType = (VectorDataViewType)schema["Prediction/Softmax"].Type;
    Console.WriteLine($"Name: Prediction/Softmax, Type: {predictionType.ItemType.RawType}, Size: ({predictionType.Dimensions[0]})");
    
    

    Le schéma d’entrée est le tableau de longueur fixe de mots codés en entiers. Le schéma de sortie est un tableau de nombres à virgule flottante de probabilités indiquant si le sentiment d’une évaluation est négatif ou positif. La somme de ces valeurs est égale à 1, car la probabilité que le sentiment soit positif est le complément de la probabilité que le sentiment soit négatif.

Créer le pipeline ML.NET

  1. Créez le pipeline et fractionnez le texte d’entrée en mots en utilisant la transformation TokenizeIntoWords pour décomposer le texte en mots dans la ligne de code suivante :

    IEstimator<ITransformer> pipeline =
        // Split the text into individual words
        mlContext.Transforms.Text.TokenizeIntoWords("TokenizedWords", "ReviewText")
    

    La transformation TokenizeIntoWords utilise les espaces pour analyser le texte/la chaîne en mots. Il crée une colonne et fractionne chaque chaîne d’entrée en un vecteur de sous-chaînes en fonction du séparateur défini par l’utilisateur.

  2. Mappez les mots à leur code sous forme d’entier en utilisant la table de recherche que vous avez déclarée plus haut :

    // Map each word to an integer value. The array of integer makes up the input features.
    .Append(mlContext.Transforms.Conversion.MapValue("VariableLengthFeatures", lookupMap,
        lookupMap.Schema["Words"], lookupMap.Schema["Ids"], "TokenizedWords"))
    
  3. Redimensionnez les codes sous forme d’entiers de longueur variable en un tableau de longueur fixe, qui est requis par le modèle :

    // Resize variable length vector to fixed length vector.
    .Append(mlContext.Transforms.CustomMapping(ResizeFeaturesAction, "Resize"))
    
  4. Classifiez l’entrée avec le modèle TensorFlow chargé :

    // Passes the data to TensorFlow for scoring
    .Append(tensorFlowModel.ScoreTensorFlowModel("Prediction/Softmax", "Features"))
    

    La sortie du modèle TensorFlow est appelée Prediction/Softmax. Notez que le nom Prediction/Softmax est déterminé par le modèle TensorFlow. Vous ne pouvez pas changer ce nom.

  5. Créez une colonne pour la prédiction en sortie :

    // Retrieves the 'Prediction' from TensorFlow and copies to a column
    .Append(mlContext.Transforms.CopyColumns("Prediction", "Prediction/Softmax"));
    

    Vous devez copier la colonne Prediction/Softmax dans une colonne avec un nom qui peut être utilisé comme propriété dans une classe C# : Prediction. Le caractère / n’est pas autorisé dans un nom de propriété C#.

Créer le modèle ML.NET à partir du pipeline

  1. Ajoutez le code pour créer le modèle à partir du pipeline :

    // Create an executable model from the estimator pipeline
    IDataView dataView = mlContext.Data.LoadFromEnumerable(new List<MovieReview>());
    ITransformer model = pipeline.Fit(dataView);
    

    Un modèle ML.NET est créé à partir de la chaîne d’estimateurs dans le pipeline en appelant la méthode Fit. Dans le cas présent, nous n’ajustons aucune donnée pour créer le modèle, car le modèle TensorFlow a déjà été entraîné précédemment. Nous fournissons un objet de vue de données vide pour répondre aux exigences de la méthode Fit.

Utiliser le modèle pour effectuer une prédiction

  1. Ajoutez la méthode PredictSentiment au-dessus de la classe MovieReview :

    void PredictSentiment(MLContext mlContext, ITransformer model)
    {
    
    }
    
  2. Ajoutez le code suivant pour créer le PredictionEngine comme première ligne de la méthode PredictSentiment() :

    var engine = mlContext.Model.CreatePredictionEngine<MovieReview, MovieReviewSentimentPrediction>(model);
    

    PredictionEngine est une API pratique qui vous permet d’effectuer 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 de prototype. 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.

  3. Ajoutez un commentaire pour tester la prédiction du modèle formé dans la méthode Predict() en créant une instance de MovieReview :

    var review = new MovieReview()
    {
        ReviewText = "this film is really good"
    };
    
  4. Passez les données des commentaires de test à Prediction Engine en ajoutant les lignes de code suivantes dans la méthode PredictSentiment() :

    var sentimentPrediction = engine.Predict(review);
    
  5. La fonction Predict() fait une prédiction sur une seule ligne de données :

    Propriété Valeur Type
    Prédiction [0,5459937, 0,454006255] float[]
  6. Affichez la prédiction du sentiment en utilisant le code suivant :

    Console.WriteLine($"Number of classes: {sentimentPrediction.Prediction?.Length}");
    Console.WriteLine($"Is sentiment/review positive? {(sentimentPrediction.Prediction?[1] > 0.5 ? "Yes." : "No.")}");
    
  7. Ajoutez un appel à PredictSentiment après avoir appelé la méthode Fit() :

    PredictSentiment(mlContext, model);
    

Résultats

Créez et exécutez votre application.

Vos résultats doivent être similaires à ce qui suit. Durant le processus, des messages sont affichés. Vous pouvez voir des avertissements ou des messages de traitement. Ces messages ont été supprimés des résultats suivants par souci de clarté.

Number of classes: 2
Is sentiment/review positive ? Yes

Félicitations ! Vous venez de créer un modèle Machine Learning pour la classification et la prédiction des sentiments de messages en réutilisant un modèle TensorFlow dans ML.NET.

Vous trouverez le code source de ce tutoriel dans le référentiel dotnet/samples.

Dans ce didacticiel, vous avez appris à :

  • Charger un modèle TensorFlow préentraîné
  • Transformer le texte des commentaires d’un site web en caractéristiques convenant au modèle
  • Utiliser le modèle pour effectuer une prédiction