Samouczek: analizowanie tonacji recenzji filmów przy użyciu wstępnie wytrenowanego modelu TensorFlow w ML.NET

W tym samouczku pokazano, jak używać wstępnie wytrenowanego modelu TensorFlow do klasyfikowania tonacji w komentarzach witryny internetowej. Klasyfikator tonacji binarnej to aplikacja konsolowa języka C# opracowana przy użyciu programu Visual Studio.

Model TensorFlow używany w tym samouczku został wytrenowany przy użyciu recenzji filmów z bazy danych IMDB. Po zakończeniu tworzenia aplikacji będzie można podać tekst recenzji filmu, a aplikacja poinformuje Cię, czy recenzja ma pozytywną, czy negatywną tonację.

Ten samouczek zawiera informacje na temat wykonywania następujących czynności:

  • Ładowanie wstępnie wytrenowanego modelu TensorFlow
  • Przekształcanie tekstu komentarza witryny internetowej w funkcje odpowiednie dla modelu
  • Używanie modelu do przewidywania

Kod źródłowy tego samouczka można znaleźć w repozytorium dotnet/samples .

Wymagania wstępne

Konfigurowanie

Tworzenie aplikacji

  1. Utwórz aplikację konsolową języka C# o nazwie "TextClassificationTF". Kliknij przycisk Dalej.

  2. Wybierz platformę .NET 6 jako platformę do użycia. Kliknij przycisk Utwórz.

  3. Utwórz katalog o nazwie Dane w projekcie, aby zapisać pliki zestawu danych.

  4. Zainstaluj pakiet NuGet Microsoft.ML:

    Uwaga

    W tym przykładzie użyto najnowszej stabilnej wersji pakietów NuGet wymienionych, chyba że określono inaczej.

    W Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt i wybierz polecenie Zarządzaj pakietami NuGet. Wybierz pozycję "nuget.org" jako źródło pakietu, a następnie wybierz kartę Przeglądaj . Wyszukaj Microsoft.ML, wybierz odpowiedni pakiet, a następnie wybierz przycisk Zainstaluj . Kontynuuj instalację, zgadzając się na postanowienia licencyjne dotyczące wybranego pakietu. Powtórz te kroki dla bibliotek Microsoft.ML.TensorFlow, Microsoft.ML.SampleUtils i SciSharp.TensorFlow.Redist.

Dodawanie modelu TensorFlow do projektu

Uwaga

Model tego samouczka pochodzi z repozytorium GitHub dotnet/machinelearning-testdata . Model jest w formacie TensorFlow SavedModel.

  1. Pobierz plik zip sentiment_model i rozpakuj.

    Plik zip zawiera:

    • saved_model.pb: sam model TensorFlow. Model przyjmuje tablicę całkowitą o stałej długości (rozmiar 600) funkcji reprezentujących tekst w ciągu przeglądu imDB i generuje dwa prawdopodobieństwa, które sumują się do 1: prawdopodobieństwo, że przegląd danych wejściowych ma pozytywną tonację i prawdopodobieństwo, że przegląd wejściowy ma negatywną tonację.
    • imdb_word_index.csv: mapowanie z poszczególnych wyrazów na wartość całkowitą. Mapowanie służy do generowania funkcji wejściowych dla modelu TensorFlow.
  2. Skopiuj zawartość najbardziej sentiment_model wewnętrznego katalogu do katalogu projektu sentiment_modelTextClassificationTF. Ten katalog zawiera model i dodatkowe pliki pomocy technicznej potrzebne do tego samouczka, jak pokazano na poniższej ilustracji:

    sentiment_model zawartość katalogu

  3. W Eksplorator rozwiązań kliknij prawym przyciskiem myszy każdy z plików w katalogu i podkatalogusentiment_model, a następnie wybierz polecenie Właściwości. W obszarze Zaawansowane zmień wartość opcji Kopiuj do katalogu wyjściowego , aby skopiować, jeśli jest nowsza.

Dodawanie instrukcji using i zmiennych globalnych

  1. Dodaj następujące dodatkowe using instrukcje na początku pliku Program.cs :

    using Microsoft.ML;
    using Microsoft.ML.Data;
    using Microsoft.ML.Transforms;
    
  2. Utwórz zmienną globalną bezpośrednio po instrukcjach using do przechowywania zapisanej ścieżki pliku modelu.

    string _modelPath = Path.Combine(Environment.CurrentDirectory, "sentiment_model");
    
    • _modelPath to ścieżka pliku wytrenowanego modelu.

Modelowanie danych

Recenzje filmów są wolnym tekstem formularza. Aplikacja konwertuje tekst na format wejściowy oczekiwany przez model w wielu dyskretnych etapach.

Pierwszą z nich jest podzielenie tekstu na oddzielne wyrazy i użycie dostarczonego pliku mapowania w celu zamapowania każdego wyrazu na kodowanie całkowite. Wynikiem tej transformacji jest zmienna długość tablicy całkowitej o długości odpowiadającej liczbie wyrazów w zdaniu.

Właściwość Wartość Typ
Przeglądanie tekstu ten film jest naprawdę dobry ciąg
VariableLengthFeatures 14,22,9,66,78,... int[]

Tablica funkcji o zmiennej długości jest następnie zmieniana na stałą długość 600. Jest to długość oczekiwana przez model TensorFlow.

Właściwość Wartość Typ
Przeglądanie tekstu ten film jest naprawdę dobry ciąg
VariableLengthFeatures 14,22,9,66,78,... int[]
Funkcje 14,22,9,66,78,... int[600]
  1. Utwórz klasę danych wejściowych w dolnej części pliku Program.cs :

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

    Klasa danych wejściowych, MovieReview, ma wartość string dla komentarzy użytkownika (ReviewText).

  2. Utwórz klasę dla funkcji o zmiennej MovieReview długości po klasie:

    /// <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; }
    }
    

    Właściwość VariableLengthFeatures ma atrybut VectorType , aby wyznaczyć go jako wektor. Wszystkie elementy wektorów muszą być tego samego typu. W zestawach danych z dużą liczbą kolumn ładowanie wielu kolumn jako pojedynczego wektora zmniejsza liczbę przepływów danych podczas stosowania przekształceń danych.

    Ta klasa jest używana w ResizeFeatures akcji. Nazwy jego właściwości (w tym przypadku tylko jeden) są używane do wskazywania, które kolumny w widoku DataView mogą być używane jako dane wejściowe do niestandardowej akcji mapowania.

  3. Utwórz klasę dla funkcji o stałej długości po VariableLength klasie:

    /// <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; }
    }
    

    Ta klasa jest używana w ResizeFeatures akcji. Nazwy jego właściwości (w tym przypadku tylko jeden) są używane do wskazywania, które kolumny w widoku DataView mogą być używane jako dane wyjściowe akcji mapowania niestandardowego.

    Należy pamiętać, że nazwa właściwości Features jest określana przez model TensorFlow. Nie można zmienić tej nazwy właściwości.

  4. Utwórz klasę przewidywania po FixedLength klasie:

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

    MovieReviewSentimentPrediction jest klasą przewidywania używaną po trenowaniu modelu. MovieReviewSentimentPredictionma pojedynczą float tablicę VectorType (Prediction) i atrybut.

  5. Utwórz inną klasę do przechowywania wartości konfiguracji, takich jak długość wektora funkcji:

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

Tworzenie tekstu MLContext, słownika odnośników i akcji w celu zmiany rozmiaru funkcji

Klasa MLContext jest punktem wyjścia dla wszystkich operacji ML.NET. Inicjowanie mlContext tworzy nowe środowisko ML.NET, które można udostępnić w obiektach przepływu pracy tworzenia modelu. Jest ona podobna, koncepcyjnie, do DBContext w programie Entity Framework.

  1. Console.WriteLine("Hello World!") Zastąp wiersz następującym kodem, aby zadeklarować i zainicjować zmienną mlContext:

    MLContext mlContext = new MLContext();
    
  2. Utwórz słownik, aby kodować wyrazy jako liczby całkowite przy użyciu LoadFromTextFile metody w celu załadowania danych mapowania z pliku, jak pokazano w poniższej tabeli:

    Word Indeks
    Dzieci 362
    chcę 181
    Nieodpowiednim 355
    effects 302
    Uczucie 547

    Dodaj poniższy kod, aby utworzyć mapę odnośników:

    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. Dodaj element , Action aby zmienić rozmiar tablicy liczb całkowitych słowa o zmiennej długości do tablicy całkowitej o stałym rozmiarze z następnymi wierszami kodu:

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

Ładowanie wstępnie wytrenowanego modelu TensorFlow

  1. Dodaj kod, aby załadować model TensorFlow:

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

    Po załadowaniu modelu można wyodrębnić jego schemat wejściowy i wyjściowy. Schematy są wyświetlane tylko dla zainteresowań i nauki. Nie potrzebujesz tego kodu, aby aplikacja końcowa działała:

    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]})");
    
    

    Schemat wejściowy to tablica o stałej długości zakodowanych wyrazów całkowitych. Schemat wyjściowy to tablica zmiennoprzecinkowa prawdopodobieństwa wskazująca, czy tonacja przeglądu jest ujemna, czy dodatnia. Te wartości sumuje się do 1, ponieważ prawdopodobieństwo dodatniego jest uzupełnieniem prawdopodobieństwa, że tonacja jest ujemna.

Tworzenie potoku ML.NET

  1. Utwórz potok i podziel tekst wejściowy na wyrazy przy użyciu przekształcenia TokenizeIntoWords , aby podzielić tekst na wyrazy jako następny wiersz kodu:

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

    Przekształcenie TokenizeIntoWords używa spacji do analizowania tekstu/ciągu na wyrazy. Tworzy nową kolumnę i dzieli każdy ciąg wejściowy na wektor podciągów na podstawie separatora zdefiniowanego przez użytkownika.

  2. Zamapuj wyrazy na kodowanie całkowite przy użyciu tabeli odnośników zadeklarowanej powyżej:

    // 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. Zmień rozmiar kodowań liczb całkowitych o zmiennej długości na stałą długość wymaganą przez model:

    // Resize variable length vector to fixed length vector.
    .Append(mlContext.Transforms.CustomMapping(ResizeFeaturesAction, "Resize"))
    
  4. Klasyfikowanie danych wejściowych przy użyciu załadowanego modelu TensorFlow:

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

    Dane wyjściowe modelu TensorFlow są nazywane Prediction/Softmax. Należy pamiętać, że nazwa Prediction/Softmax jest określana przez model TensorFlow. Nie można zmienić tej nazwy.

  5. Utwórz nową kolumnę dla przewidywania danych wyjściowych:

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

    Należy skopiować kolumnę Prediction/Softmax do jednej z nazwą, która może być używana jako właściwość w klasie C#: Prediction. Znak / nie jest dozwolony w nazwie właściwości języka C#.

Tworzenie modelu ML.NET na podstawie potoku

  1. Dodaj kod, aby utworzyć model z potoku:

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

    Model ML.NET jest tworzony na podstawie łańcucha narzędzi do szacowania w potoku przez wywołanie Fit metody . W tym przypadku nie dopasowujemy żadnych danych do utworzenia modelu, ponieważ model TensorFlow został już wcześniej wytrenowany. Dostarczamy pusty obiekt widoku danych, aby spełnić wymagania Fit metody.

Używanie modelu do przewidywania

  1. Dodaj metodę PredictSentiment nad klasą MovieReview :

    void PredictSentiment(MLContext mlContext, ITransformer model)
    {
    
    }
    
  2. Dodaj następujący kod, aby utworzyć PredictionEngine element jako pierwszy wiersz w metodzie PredictSentiment() :

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

    PredictionEngine to wygodny interfejs API, który umożliwia przewidywanie dla pojedynczego wystąpienia danych. PredictionEngine nie jest bezpieczne wątkowo. Dopuszczalne jest użycie w środowiskach jednowątkowych lub prototypowych. Aby zwiększyć wydajność i bezpieczeństwo wątków w środowiskach produkcyjnych, użyj PredictionEnginePool usługi, która tworzy ObjectPoolPredictionEngine obiekty do użycia w całej aplikacji. Zobacz ten przewodnik dotyczący używania PredictionEnginePool w internetowym interfejsie API ASP.NET Core.

    Uwaga

    PredictionEnginePool Rozszerzenie usługi jest obecnie w wersji zapoznawczej.

  3. Dodaj komentarz, aby przetestować przewidywanie wytrenowanego modelu w metodzie Predict() , tworząc wystąpienie klasy MovieReview:

    var review = new MovieReview()
    {
        ReviewText = "this film is really good"
    };
    
  4. Przekaż dane komentarza testowego do Prediction Engine obiektu, dodając kolejne wiersze kodu w metodzie PredictSentiment() :

    var sentimentPrediction = engine.Predict(review);
    
  5. Funkcja Predict() tworzy przewidywanie dla pojedynczego wiersza danych:

    Właściwość Wartość Typ
    Przewidywanie [0.5459937, 0.454006255] float[]
  6. Wyświetl przewidywanie tonacji przy użyciu następującego kodu:

    Console.WriteLine($"Number of classes: {sentimentPrediction.Prediction?.Length}");
    Console.WriteLine($"Is sentiment/review positive? {(sentimentPrediction.Prediction?[1] > 0.5 ? "Yes." : "No.")}");
    
  7. Dodaj wywołanie metody PredictSentiment po wywołaniu Fit() metody:

    PredictSentiment(mlContext, model);
    

Wyniki

Skompiluj i uruchom aplikację.

Wyniki powinny być podobne do poniższych. Podczas przetwarzania są wyświetlane komunikaty. Mogą pojawić się ostrzeżenia lub komunikaty przetwarzania. Te komunikaty zostały usunięte z poniższych wyników w celu uzyskania jasności.

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

Gratulacje! Udało Ci się pomyślnie skompilować model uczenia maszynowego do klasyfikowania i przewidywania tonacji komunikatów przez ponowne korzystanie z wstępnie wytrenowanego TensorFlow modelu w ML.NET.

Kod źródłowy tego samouczka można znaleźć w repozytorium dotnet/samples .

W niniejszym samouczku zawarto informacje na temat wykonywania następujących czynności:

  • Ładowanie wstępnie wytrenowanego modelu TensorFlow
  • Przekształcanie tekstu komentarza witryny internetowej w funkcje odpowiednie dla modelu
  • Używanie modelu do przewidywania