Esercitazione: Analizzare il sentiment delle recensioni di film usando un modello TensorFlow con training preliminare in ML.NET
Questa esercitazione illustra come usare un modello TensorFlow con training preliminare per classificare il sentiment nei commenti del sito Web. Il classificatore di valutazione binario è un'applicazione console C# sviluppata con Visual Studio.
Il modello TensorFlow usato in questa esercitazione è stato sottoposto a training usando recensioni di film dal database IMDB. Al termine dello sviluppo dell'applicazione, sarà possibile fornire il testo della recensione cinematografica e l'applicazione indicherà se la recensione ha un sentiment positivo o negativo.
In questa esercitazione verranno illustrate le procedure per:
- Caricare un modello TensorFlow con training preliminare
- Trasformare il testo del commento del sito Web in funzionalità adatte per il modello
- Usare il modello per eseguire una stima
È possibile trovare il codice sorgente per questa esercitazione nel repository dotnet/samples.
Prerequisiti
- Visual Studio 2022 con il carico di lavoro ".NET Desktop Development" installato.
Installazione
Creare l'applicazione
Creare un'applicazione console C# denominata "TextClassificationTF". Fare clic sul pulsante Next (Avanti).
Scegliere .NET 6 come framework da usare. Fare clic sul pulsante Crea.
Creare una directory denominata Data nel progetto per salvare i file del set di dati.
Installare il pacchetto NuGet Microsoft.ML:
Nota
In questo esempio viene usata la versione stabile più recente dei pacchetti NuGet menzionati, se non diversamente specificato.
In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e selezionare Gestisci pacchetti NuGet. Scegliere "nuget.org" come origine del pacchetto e quindi selezionare la scheda Sfoglia . Cercare Microsoft.ML, selezionare il pacchetto desiderato e quindi selezionare il pulsante Installa . Procedere con l'installazione accettando le condizioni di licenza per il pacchetto scelto. Ripetere questi passaggi per Microsoft.ML.TensorFlow, Microsoft.ML.SampleUtils e SciSharp.TensorFlow.Redist.
Aggiungere il modello TensorFlow al progetto
Nota
Il modello per questa esercitazione proviene dal repository GitHub dotnet/machinelearning-testdata . Il modello è in formato TensorFlow SavedModel.
Scaricare il file ZIP sentiment_model e decomprimere.
Il file ZIP contiene:
saved_model.pb
: il modello TensorFlow stesso. Il modello accetta una matrice di valori interi a lunghezza fissa (dimensione 600) di caratteristiche che rappresentano il testo in una stringa di revisione IMDB e restituisce due probabilità che sommano a 1: la probabilità che la revisione di input abbia un sentiment positivo e la probabilità che la revisione di input abbia un sentiment negativo.imdb_word_index.csv
: mapping da singole parole a un valore intero. Il mapping viene usato per generare le funzionalità di input per il modello TensorFlow.
Copiare il contenuto della directory più
sentiment_model
interna nella directory del progettosentiment_model
TextClassificationTF. Questa directory contiene il modello e i file di supporto aggiuntivi necessari per questa esercitazione, come illustrato nell'immagine seguente:In Esplora soluzioni fare clic con il pulsante destro del mouse su ognuno dei file nella directory e nella
sentiment_model
sottodirectory e scegliere Proprietà. In Avanzate modificare il valore di Copia nella directory di output in Copia se più recente.
Aggiungere istruzioni using e variabili globali
Aggiungere le istruzioni
using
seguenti all'inizio del file Program.cs:using Microsoft.ML; using Microsoft.ML.Data; using Microsoft.ML.Transforms;
Creare una variabile globale subito dopo le istruzioni using per contenere il percorso del file del modello salvato.
string _modelPath = Path.Combine(Environment.CurrentDirectory, "sentiment_model");
_modelPath
è il percorso del file del modello sottoposto a training.
Modellare i dati
Le recensioni di film sono testo in formato libero. L'applicazione converte il testo nel formato di input previsto dal modello in diverse fasi discrete.
Il primo consiste nel suddividere il testo in parole separate e usare il file di mapping fornito per eseguire il mapping di ogni parola a una codifica integer. Il risultato di questa trasformazione è una matrice integer a lunghezza variabile con una lunghezza corrispondente al numero di parole nella frase.
Proprietà | Valore | Tipo |
---|---|---|
ReviewText | questo film è davvero buono | string |
VariableLengthFeatures | 14,22,9,66,78,... | int[] |
La matrice di caratteristiche a lunghezza variabile viene quindi ridimensionata a una lunghezza fissa di 600. Si tratta della lunghezza prevista dal modello TensorFlow.
Proprietà | Valore | Tipo |
---|---|---|
ReviewText | questo film è davvero buono | string |
VariableLengthFeatures | 14,22,9,66,78,... | int[] |
Funzionalità | 14,22,9,66,78,... | int[600] |
Creare una classe per i dati di input nella parte inferiore del file Program.cs :
/// <summary> /// Class to hold original sentiment data. /// </summary> public class MovieReview { public string? ReviewText { get; set; } }
La classe di dati di input,
MovieReview
, ha unstring
oggetto per i commenti dell'utente (ReviewText
).Creare una classe per le funzionalità di lunghezza variabile dopo la
MovieReview
classe :/// <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
VariableLengthFeatures
proprietà ha un attributo VectorType per designarlo come vettore. Tutti gli elementi vettoriali devono essere dello stesso tipo. Nei set di dati con un numero elevato di colonne, il caricamento di più colonne come singolo vettore riduce il numero di passaggi di dati quando si applicano trasformazioni dei dati.Questa classe viene usata nell'azione
ResizeFeatures
. I nomi delle relative proprietà (in questo caso solo uno) vengono usati per indicare quali colonne in DataView possono essere usate come input per l'azione di mapping personalizzata.Creare una classe per le funzionalità a lunghezza fissa, dopo la
VariableLength
classe :/// <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; } }
Questa classe viene usata nell'azione
ResizeFeatures
. I nomi delle relative proprietà (in questo caso solo uno) vengono usati per indicare quali colonne in DataView possono essere usate come output dell'azione di mapping personalizzata.Si noti che il nome della proprietà
Features
è determinato dal modello TensorFlow. Non è possibile modificare questo nome di proprietà.Creare una classe per la stima dopo la
FixedLength
classe :/// <summary> /// Class to contain the output values from the transformation. /// </summary> public class MovieReviewSentimentPrediction { [VectorType(2)] public float[]? Prediction { get; set; } }
MovieReviewSentimentPrediction
è la classe di stima usata dopo il training del modello.MovieReviewSentimentPrediction
ha una singolafloat
matrice (Prediction
) e unVectorType
attributo.Creare un'altra classe per contenere i valori di configurazione, ad esempio la lunghezza del vettore di funzionalità:
static class Config { public const int FeatureLength = 600; }
Creare mlContext, dizionario di ricerca e azione per ridimensionare le funzionalità
La classe MLContext è un punto di partenza per tutte le operazioni ML.NET. L'inizializzazione di mlContext
crea un nuovo ambiente ML.NET che può essere condiviso tra gli oggetti del flusso di lavoro di creazione del modello. Dal punto di vista concettuale è simile a DBContext
in Entity Framework.
Sostituire la
Console.WriteLine("Hello World!")
riga con il codice seguente per dichiarare e inizializzare la variabile mlContext:MLContext mlContext = new MLContext();
Creare un dizionario per codificare le parole come numeri interi usando il
LoadFromTextFile
metodo per caricare i dati di mapping da un file, come illustrato nella tabella seguente:Word Indice Bambini 362 want 181 Sbagliato 355 effects 302 Sensazione 547 Aggiungere il codice seguente per creare la mappa di ricerca:
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: ',' );
Aggiungere un
Action
oggetto per ridimensionare la matrice integer di lunghezza variabile a una matrice integer di dimensioni fisse, con le righe successive di codice:Action<VariableLength, FixedLength> ResizeFeaturesAction = (s, f) => { var features = s.VariableLengthFeatures; Array.Resize(ref features, Config.FeatureLength); f.Features = features; };
Caricare il modello TensorFlow pre-sottoposto a training
Aggiungere codice per caricare il modello TensorFlow:
TensorFlowModel tensorFlowModel = mlContext.Model.LoadTensorFlowModel(_modelPath);
Dopo aver caricato il modello, è possibile estrarre il relativo schema di input e output. Gli schemi vengono visualizzati solo per interesse e apprendimento. Non è necessario questo codice per la funzione dell'applicazione finale:
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]})");
Lo schema di input è la matrice a lunghezza fissa di parole con codifica integer. Lo schema di output è una matrice float di probabilità che indica se il sentiment di una revisione è negativo o positivo. Questi valori sommano a 1, poiché la probabilità di essere positivi è il complemento della probabilità del sentiment essere negativo.
Creare la pipeline di ML.NET
Creare la pipeline e suddividere il testo di input in parole usando TokenizeIntoWords trasforma per suddividere il testo in parole come riga di codice successiva:
IEstimator<ITransformer> pipeline = // Split the text into individual words mlContext.Transforms.Text.TokenizeIntoWords("TokenizedWords", "ReviewText")
La trasformazione TokenizeIntoWords usa spazi per analizzare il testo/stringa in parole. Crea una nuova colonna e divide ogni stringa di input in un vettore di sottostringa in base al separatore definito dall'utente.
Eseguire il mapping delle parole alla codifica integer usando la tabella di ricerca dichiarata in precedenza:
// 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"))
Ridimensionare le codifiche integer di lunghezza variabile a lunghezza fissa richiesta dal modello:
// Resize variable length vector to fixed length vector. .Append(mlContext.Transforms.CustomMapping(ResizeFeaturesAction, "Resize"))
Classificare l'input con il modello TensorFlow caricato:
// Passes the data to TensorFlow for scoring .Append(tensorFlowModel.ScoreTensorFlowModel("Prediction/Softmax", "Features"))
L'output del modello TensorFlow è denominato
Prediction/Softmax
. Si noti che il nomePrediction/Softmax
è determinato dal modello TensorFlow. Non è possibile modificare questo nome.Creare una nuova colonna per la stima dell'output:
// Retrieves the 'Prediction' from TensorFlow and copies to a column .Append(mlContext.Transforms.CopyColumns("Prediction", "Prediction/Softmax"));
È necessario copiare la
Prediction/Softmax
colonna in una con un nome che può essere usato come proprietà in una classe C#:Prediction
. Il/
carattere non è consentito in un nome di proprietà C#.
Creare il modello di ML.NET dalla pipeline
Aggiungere il codice per creare il modello dalla pipeline:
// Create an executable model from the estimator pipeline IDataView dataView = mlContext.Data.LoadFromEnumerable(new List<MovieReview>()); ITransformer model = pipeline.Fit(dataView);
Un modello di ML.NET viene creato dalla catena di estimatori nella pipeline chiamando il
Fit
metodo . In questo caso, non si adattano dati per creare il modello, poiché il modello TensorFlow è già stato sottoposto a training. Viene fornito un oggetto visualizzazione dati vuoto per soddisfare i requisiti delFit
metodo.
Usare il modello per eseguire una stima
Aggiungere il metodo sopra la
PredictSentiment
MovieReview
classe:void PredictSentiment(MLContext mlContext, ITransformer model) { }
Aggiungere il codice seguente per creare la
PredictionEngine
prima riga nelPredictSentiment()
metodo:var engine = mlContext.Model.CreatePredictionEngine<MovieReview, MovieReviewSentimentPrediction>(model);
PredictionEngine è un'API pratico, che consente di eseguire una stima in una singola istanza di dati.
PredictionEngine
non è thread-safe. È accettabile usare in ambienti a thread singolo o prototipo. Per migliorare le prestazioni e la sicurezza dei thread negli ambienti di produzione, usare ilPredictionEnginePool
servizio, che crea unObjectPool
oggetto daPredictionEngine
usare in tutta l'applicazione. Vedere questa guida su come usarePredictionEnginePool
in un'API Web di ASP.NET Core.Nota
L'estensione del servizio
PredictionEnginePool
è attualmente in anteprima.Aggiungere un commento per testare la stima del modello sottoposto a training nel metodo
Predict()
creando un'istanza diMovieReview
:var review = new MovieReview() { ReviewText = "this film is really good" };
Passare i dati del commento di test all'oggetto
Prediction Engine
aggiungendo le righe successive di codice nelPredictSentiment()
metodo:var sentimentPrediction = engine.Predict(review);
La funzione Predict() effettua una stima su una singola riga di dati:
Proprietà Valore Tipo Stima [0.5459937, 0.454006255] float[] Visualizzare la stima del sentiment usando il codice seguente:
Console.WriteLine($"Number of classes: {sentimentPrediction.Prediction?.Length}"); Console.WriteLine($"Is sentiment/review positive? {(sentimentPrediction.Prediction?[1] > 0.5 ? "Yes." : "No.")}");
Aggiungere una chiamata a
PredictSentiment
dopo aver chiamato ilFit()
metodo:PredictSentiment(mlContext, model);
Risultati
Compilare ed eseguire l'applicazione.
I risultati dovrebbero essere simili a quanto riportato di seguito. Durante l'elaborazione, vengono visualizzati alcuni messaggi. Possono essere mostrati avvisi o messaggi relativi all'elaborazione. Questi messaggi sono stati rimossi dai risultati seguenti per maggiore chiarezza.
Number of classes: 2
Is sentiment/review positive ? Yes
Congratulazioni! È stato creato un modello di Machine Learning per classificare e stimare il sentiment dei messaggi riutilizzando un modello pre-sottoposto TensorFlow
a training in ML.NET.
È possibile trovare il codice sorgente per questa esercitazione nel repository dotnet/samples.
In questa esercitazione sono state illustrate le procedure per:
- Caricare un modello TensorFlow pre-sottoposto a training
- Trasformare il testo del commento del sito Web in funzionalità adatte per il modello
- Usare il modello per eseguire una stima