Tutoriel : Analyser les sentiments dans les commentaires des sites web à l’aide d’une classification binaire dans ML.NET

Ce tutoriel vous montre comment créer une application console .NET Core qui classifie les sentiments analysés dans les commentaires des sites web et qui exécute l’action appropriée. Le classifieur binaire de sentiments utilise C# dans Visual Studio 2022.

Dans ce tutoriel, vous allez apprendre à :

  • Création d’une application console
  • Préparer les données
  • Chargement des données
  • Générer et entraîner le modèle
  • Évaluer le modèle
  • Utiliser le modèle pour effectuer une prédiction
  • Afficher les résultats

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

Prérequis

Création d’une application console

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

  2. Choisissez .NET 6 comme infrastructure à 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.

Préparer vos données

Notes

Les jeux de données utilisés dans ce tutoriel proviennent de 'From Group to Individual Labels using Deep Features' (Kotzias et. al,. KDD 2015), hébergé dans le référentiel UCI Machine Learning (Dua, D. et Karra Taniskidou, E. (2017). Référentiel UCI Machine Learning [http://archive.ics.uci.edu/ml]. Irvine, CA: University of California, School of Information and Computer Science.

  1. Téléchargez le fichier zip du jeu de données UCI Sentiment Labeled Sentences, puis décompressez-le.

  2. Copiez le fichier yelp_labelled.txt dans le répertoire Données que vous avez créé.

  3. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le fichier yelp_labeled.txt 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;
    using SentimentAnalysis;
    using static Microsoft.ML.DataOperationsCatalog;
    
  2. Ajoutez le code suivant à la ligne située juste sous les instructions using pour créer un champ contenant le chemin d’accès du fichier de jeu de données récemment téléchargé :

    string _dataPath = Path.Combine(Environment.CurrentDirectory, "Data", "yelp_labelled.txt");
    
  3. Créez ensuite des classes pour les données d’entrée et les prédictions. Ajoutez une nouvelle classe à votre projet :

    • Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le projet, puis sélectionnez Ajouter>Nouvel élément.

    • Dans la boîte de dialogue Ajouter un nouvel élément, sélectionnez Classe, puis remplacez la valeur du champ Nom par SentimentData.cs. Ensuite, sélectionnez le bouton Ajouter.

  4. Le fichier SentimentData.cs s’ouvre dans l’éditeur de code. Ajoutez l'instruction suivante using en haut du fichier SentimentData.cs :

    using Microsoft.ML.Data;
    
  5. Supprimez la définition de classe existante et ajoutez le code suivant, qui contient deux classes, SentimentData et SentimentPrediction, au fichier SentimentData.cs :

    public class SentimentData
    {
        [LoadColumn(0)]
        public string? SentimentText;
    
        [LoadColumn(1), ColumnName("Label")]
        public bool Sentiment;
    }
    
    public class SentimentPrediction : SentimentData
    {
    
        [ColumnName("PredictedLabel")]
        public bool Prediction { get; set; }
    
        public float Probability { get; set; }
    
        public float Score { get; set; }
    }
    

Comment les données ont-elles été préparées ?

La classe du jeu de données d’entrée, SentimentData, a une valeur string pour les commentaires utilisateur (SentimentText) et une valeur bool (Sentiment) égale à 1 (sentiment positif) ou 0 (sentiment négatif). Les deux champs ont des attributs LoadColumn associés, qui spécifient l’ordre du fichier de données de chaque champ. Par ailleurs, la propriété Sentiment a un attribut ColumnName qui la désigne comme champ Label. L’exemple de fichier suivant ne possède pas de ligne d’en-tête :

SentimentText Sentiment (Label)
La serveuse était un peu lente durant le service. 0
La pâte n’est pas bonne. 0
Waouh... J’ai adoré cet endroit. 1
Le service a été très rapide. 1

SentimentPrediction est la classe de prédiction utilisée après l’entraînement du modèle. Elle hérite de SentimentData afin que l’entrée SentimentText puisse être affichée en même temps que la prédiction de sortie. La valeur booléenne Prediction est la valeur que le modèle prédit quand la nouvelle entrée SentimentText lui est fournie.

La classe de sortie SentimentPrediction contient deux autres propriétés calculées par le modèle : Score, le score brut calculé par le modèle, et Probability, le score étalonné à la probabilité que le texte ait un sentiment positif.

Pour ce tutoriel, la propriété la plus importante est Prediction.

Chargement des données

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.

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.

Vous préparez l’application et chargez ensuite les données :

  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. Ajoutez le code suivant comme prochaine ligne de code :

    TrainTestData splitDataView = LoadData(mlContext);
    
  3. Créez une méthode LoadData() en bas du fichier Program.cs à l’aide du code suivant :

    TrainTestData LoadData(MLContext mlContext)
    {
    
    }
    

    La méthode LoadData() exécute les tâches suivantes :

    • Charge les données.
    • Fractionne le jeu de données chargé en jeux de données d’apprentissage et de test.
    • Retourne les jeux de données d’apprentissage et de test fractionnés.
  4. Ajoutez le code suivant comme première ligne de la méthode LoadData() :

    IDataView dataView = mlContext.Data.LoadFromTextFile<SentimentData>(_dataPath, hasHeader: false);
    

    La méthode LoadFromTextFile() définit le schéma de données et lit le fichier. Elle prend les variables de chemin de données et retourne un IDataView.

Fractionner le jeu de données pour l’apprentissage et le test du modèle

Quand vous préparez un modèle, vous utilisez une partie du jeu de données pour entraîner le modèle et une partie du jeu de données pour tester la précision du modèle.

  1. Pour fractionner les données chargées dans les jeux de données nécessaires, ajoutez le code suivant sur la ligne suivant la méthode LoadData() :

    TrainTestData splitDataView = mlContext.Data.TrainTestSplit(dataView, testFraction: 0.2);
    

    Le code précédent utilise la méthode TrainTestSplit() pour diviser le jeu de données chargé en deux jeux de données d’apprentissage et de test, et les retourner dans la classe DataOperationsCatalog.TrainTestData. Spécifiez le pourcentage de données du jeu de test avec le paramètre testFraction. La valeur par défaut est 10 %, mais dans cet exemple, vous spécifiez 20 % pour évaluer davantage de données.

  2. Retournez splitDataView à la fin de la méthode LoadData() :

    return splitDataView;
    

Générer et entraîner le modèle

  1. Ajoutez l’appel suivant à la méthode BuildAndTrainModel sous l’appel à la méthode LoadData :

    ITransformer model = BuildAndTrainModel(mlContext, splitDataView.TrainSet);
    

    La méthode BuildAndTrainModel() exécute les tâches suivantes :

    • Extrait et transforme les données.
    • Effectue l’apprentissage du modèle.
    • Prédit les sentiments en fonction des données de test.
    • Retourne le modèle.
  2. Créez la méthode BuildAndTrainModel() sous la méthode LoadData(), en utilisant le code suivant :

    ITransformer BuildAndTrainModel(MLContext mlContext, IDataView splitTrainSet)
    {
    
    }
    

Extraire et transformer les données

  1. Appelez FeaturizeText sur la ligne de code suivante :

    var estimator = mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Features", inputColumnName: nameof(SentimentData.SentimentText))
    

    La méthode FeaturizeText() dans le code précédent convertit la colonne de texte (SentimentText) en une colonne Features de type clé numérique, qui est utilisée par l’algorithme de machine learning, et l’ajoute comme nouvelle colonne au jeu de données :

    SentimentText Sentiments Fonctionnalités
    La serveuse était un peu lente durant le service. 0 [0.76, 0.65, 0.44, …]
    La pâte n’est pas bonne. 0 [0.98, 0.43, 0.54, …]
    Waouh... J’ai adoré cet endroit. 1 [0.35, 0.73, 0.46, …]
    Le service a été très rapide. 1 [0.39, 0, 0.75, …]

Ajouter un algorithme d’apprentissage

Cette application utilise un algorithme de classification qui classe les éléments ou lignes de données. Elle classe les commentaires des sites web comme positifs ou négatifs. Vous devez donc utiliser la tâche de classification binaire.

Ajoutez la tâche de machine learning aux définitions de transformations des données en ajoutant la ligne de code suivante dans BuildAndTrainModel() :

.Append(mlContext.BinaryClassification.Trainers.SdcaLogisticRegression(labelColumnName: "Label", featureColumnName: "Features"));

SdcaLogisticRegressionBinaryTrainer est votre algorithme d’entraînement de classification. Il est ajouté à estimator et accepte les caractéristiques SentimentText (Features) ainsi que les paramètres d’entrée Label pour apprendre à partir des données d’historique.

Entraîner le modèle

Ajustez le modèle aux données splitTrainSet et retournez le modèle entraîné en ajoutant la ligne de code suivante dans la méthode BuildAndTrainModel() :

Console.WriteLine("=============== Create and Train the Model ===============");
var model = estimator.Fit(splitTrainSet);
Console.WriteLine("=============== End of training ===============");
Console.WriteLine();

La méthode Fit() entraîne votre modèle en transformant le jeu de données et en appliquant l’entraînement.

Retourner le modèle entraîné à utiliser pour l’évaluation

Retournez le modèle à la fin de la méthode BuildAndTrainModel() :

return model;

Évaluer le modèle

Une fois que votre modèle est formé, vérifiez ses performances avec vos données de test.

  1. Créez la méthode Evaluate() juste après BuildAndTrainModel(), en utilisant le code suivant :

    void Evaluate(MLContext mlContext, ITransformer model, IDataView splitTestSet)
    {
    
    }
    

    La méthode Evaluate() exécute les tâches suivantes :

    • Charge le jeu de données de test.
    • Crée l’évaluateur BinaryClassification.
    • Évalue le modèle et crée des métriques.
    • Affiche les métriques.
  2. Ajoutez un appel à la nouvelle méthode sous l’appel de la méthode BuildAndTrainModel, en utilisant le code suivant :

    Evaluate(mlContext, model, splitDataView.TestSet);
    
  3. Transformez les données splitTestSet en ajoutant le code suivant à Evaluate() :

    Console.WriteLine("=============== Evaluating Model accuracy with Test data===============");
    IDataView predictions = model.Transform(splitTestSet);
    

    Le code précédent utilise la méthode Transform() pour prédire plusieurs lignes d’entrée d’un jeu de données de test.

  4. Évaluez le modèle en ajoutant la ligne de code suivante dans la méthode Evaluate() :

    CalibratedBinaryClassificationMetrics metrics = mlContext.BinaryClassification.Evaluate(predictions, "Label");
    

Une fois que vous avez le jeu de prédiction (predictions), la méthode Evaluate() évalue le modèle : elle compare les valeurs prédites aux valeurs Labels réelles dans le jeu de données de test et retourne un objet CalibratedBinaryClassificationMetrics contenant les métriques relatives aux performances du modèle.

Affichage des métriques pour la validation du modèle

Utilisez le code suivant pour afficher les métriques :

Console.WriteLine();
Console.WriteLine("Model quality metrics evaluation");
Console.WriteLine("--------------------------------");
Console.WriteLine($"Accuracy: {metrics.Accuracy:P2}");
Console.WriteLine($"Auc: {metrics.AreaUnderRocCurve:P2}");
Console.WriteLine($"F1Score: {metrics.F1Score:P2}");
Console.WriteLine("=============== End of model evaluation ===============");
  • La métrique Accuracy donne la précision du modèle, qui correspond à la proportion de prédictions correctes dans le jeu de test.

  • La métrique AreaUnderRocCurve indique le degré de confiance conféré aux résultats de la classification des classes positif/négatif. Vous voulez que la métrique AreaUnderRocCurve soit le plus proche possible de la valeur 1.

  • La métrique F1Score donne le score F1 du modèle, qui mesure l’équilibre entre la précision et le rappel. Vous voulez que la métrique F1Score soit le plus proche possible de la valeur 1.

Prédire les résultats des données de test

  1. Créez la méthode UseModelWithSingleItem() juste après la méthode Evaluate(), en utilisant le code suivant :

    void UseModelWithSingleItem(MLContext mlContext, ITransformer model)
    {
    
    }
    

    La méthode UseModelWithSingleItem() exécute les tâches suivantes :

    • Crée un commentaire unique de données de test.
    • Prédit les sentiments en fonction des données de test.
    • Combine les données de test et les prédictions pour générer des rapports.
    • Affiche les résultats prédits.
  2. Ajoutez un appel à la nouvelle méthode juste en dessous de l’appel de la méthode Evaluate(), en utilisant le code suivant :

    UseModelWithSingleItem(mlContext, model);
    
  3. Ajoutez le code suivant comme première ligne dans la méthode UseModelWithSingleItem() :

    PredictionEngine<SentimentData, SentimentPrediction> predictionFunction = mlContext.Model.CreatePredictionEngine<SentimentData, SentimentPrediction>(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.

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

    SentimentData sampleStatement = new SentimentData
    {
        SentimentText = "This was a very bad steak"
    };
    
  5. Passez les données de commentaire de test à PredictionEngine en ajoutant les lignes de code suivantes dans la méthode UseModelWithSingleItem() :

    var resultPrediction = predictionFunction.Predict(sampleStatement);
    

    La fonction Predict() effectue une prédiction sur une seule ligne de données.

  6. Affichez SentimentText et la prédiction de sentiment correspondante en utilisant le code suivant :

    Console.WriteLine();
    Console.WriteLine("=============== Prediction Test of model with a single sample and test dataset ===============");
    
    Console.WriteLine();
    Console.WriteLine($"Sentiment: {resultPrediction.SentimentText} | Prediction: {(Convert.ToBoolean(resultPrediction.Prediction) ? "Positive" : "Negative")} | Probability: {resultPrediction.Probability} ");
    
    Console.WriteLine("=============== End of Predictions ===============");
    Console.WriteLine();
    

Utiliser le modèle pour la prédiction

Déployer et prédire des éléments par lots

  1. Créez la méthode UseModelWithBatchItems() juste après la méthode UseModelWithSingleItem(), en utilisant le code suivant :

    void UseModelWithBatchItems(MLContext mlContext, ITransformer model)
    {
    
    }
    

    La méthode UseModelWithBatchItems() exécute les tâches suivantes :

    • Crée les données de test par lots.
    • Prédit les sentiments en fonction des données de test.
    • Combine les données de test et les prédictions pour générer des rapports.
    • Affiche les résultats prédits.
  2. Ajoutez un appel à la nouvelle méthode juste en dessous de l’appel de la méthode UseModelWithSingleItem(), en utilisant le code suivant :

    UseModelWithBatchItems(mlContext, model);
    
  3. Ajoutez des commentaires pour tester les prédictions du modèle formé dans la méthode UseModelWithBatchItems() :

    IEnumerable<SentimentData> sentiments = new[]
    {
        new SentimentData
        {
            SentimentText = "This was a horrible meal"
        },
        new SentimentData
        {
            SentimentText = "I love this spaghetti."
        }
    };
    

Prédire le sentiment de commentaire

Utilisez le modèle pour prédire le sentiment de données de commentaire à l’aide de la méthode Transform() :

IDataView batchComments = mlContext.Data.LoadFromEnumerable(sentiments);

IDataView predictions = model.Transform(batchComments);

// Use model to predict whether comment data is Positive (1) or Negative (0).
IEnumerable<SentimentPrediction> predictedResults = mlContext.Data.CreateEnumerable<SentimentPrediction>(predictions, reuseRowObject: false);

Combiner et afficher les prédictions

Créez un en-tête des prédictions à l’aide du code suivant :

Console.WriteLine();

Console.WriteLine("=============== Prediction Test of loaded model with multiple samples ===============");

Comme SentimentPrediction est hérité de SentimentData, la méthode Transform() a rempli SentimentText avec les champs prédits. À mesure que le processus ML.NET progresse, chaque composant ajoute des colonnes, ce qui rend l’affichage des résultats plus facile :

foreach (SentimentPrediction prediction  in predictedResults)
{
    Console.WriteLine($"Sentiment: {prediction.SentimentText} | Prediction: {(Convert.ToBoolean(prediction.Prediction) ? "Positive" : "Negative")} | Probability: {prediction.Probability} ");
}
Console.WriteLine("=============== End of predictions ===============");

Résultats

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. Ils ont été supprimés des résultats ci-dessous par souci de clarté.

Model quality metrics evaluation
--------------------------------
Accuracy: 83.96%
Auc: 90.51%
F1Score: 84.04%

=============== End of model evaluation ===============

=============== Prediction Test of model with a single sample and test dataset ===============

Sentiment: This was a very bad steak | Prediction: Negative | Probability: 0.1027377
=============== End of Predictions ===============

=============== Prediction Test of loaded model with a multiple samples ===============

Sentiment: This was a horrible meal | Prediction: Negative | Probability: 0.1369192
Sentiment: I love this spaghetti. | Prediction: Positive | Probability: 0.9960636
=============== End of predictions ===============

=============== End of process ===============
Press any key to continue . . .

Félicitations ! Vous venez de créer un modèle d’apprentissage automatique pour la classification et la prédiction des sentiments de messages.

La création de modèles efficaces est un processus itératif. Celui-ci présente une qualité initiale médiocre, car le tutoriel utilise de petits jeux de données pour permettre un apprentissage rapide du modèle. Si vous n’êtes pas satisfait de la qualité du modèle, essayez de l’améliorer en fournissant de plus gros jeux de données d’entraînement ou en choisissant d’autres algorithmes d’entraînement avec des hyperparamètres différents pour chacun.

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

Étapes suivantes

Dans ce didacticiel, vous avez appris à :

  • Création d’une application console
  • Préparer les données
  • Chargement des données
  • Générer et entraîner le modèle
  • Évaluer le modèle
  • Utiliser le modèle pour effectuer une prédiction
  • Afficher les résultats

Passer au tutoriel suivant pour en savoir plus