Esercitazione: Eseguire il training di un modello di classificazione ML.NET per classificare le immagini
Informazioni su come eseguire il training di un modello di classificazione per classificare le immagini usando un modello TensorFlow con training preliminare per l'elaborazione delle immagini.
È stato eseguito il training del modello TensorFlow per classificare le immagini in migliaia di categorie. Poiché il modello TensorFlow sa come riconoscere i modelli nelle immagini, il modello ML.NET può usarlo nella pipeline per convertire le immagini non elaborate in funzionalità o input per eseguire il training di un modello di classificazione.
In questa esercitazione verranno illustrate le procedure per:
- Informazioni sul problema
- Incorporare il modello TensorFlow con training preliminare nella pipeline di ML.NET
- Eseguire il training e valutare il modello di ML.NET
- Classificare un'immagine di test
È possibile trovare il codice sorgente per questa esercitazione nel repository dotnet/samples. Per impostazione predefinita, la configurazione del progetto .NET per questa esercitazione è destinata a .NET Core 2.2.
Prerequisiti
- Visual Studio 2022
- File ZIP della directory assets dell'esercitazione
- Modello di Machine Learning InceptionV1
Selezionare l'attività di Machine Learning corretta
Deep Learning
Il Deep Learning è un subset di Machine Learning, che sta rivoluzionando aree come visione artificiale e riconoscimento vocale.
I modelli di Deep Learning vengono sottoposti a training con set di grandi dimensioni di dati con etichetta e reti neurali contenenti più livelli di apprendimento. Il Deep Learning:
- Offre prestazioni migliori in alcune attività come visione artificiale.
- Richiede enormi quantità di dati di training.
La classificazione delle immagini è un'attività di classificazione specifica che consente di classificare automaticamente le immagini in categorie, ad esempio:
- Rilevamento di un volto umano in un'immagine.
- Rilevamento di gatti e cani.
Oppure, come nelle immagini seguenti, determinare se un'immagine è un cibo, un toy o un'appliance:
Nota
Le immagini precedenti appartengono a Wikimedia Commons, con gli attributi seguenti:
- "220px-Pepperoni_pizza.jpg" pubblico dominio, https://commons.wikimedia.org/w/index.php?curid=79505,
- "119px-Nalle_-_a_small_brown_teddy_bear.jpg" di Jonik - Fotografia autoprodotta, CC BY-SA 2.0, https://commons.wikimedia.org/w/index.php?curid=48166.
- "193px-Broodrooster.jpg" di M.Minderhoud - Opera propria, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=27403
Il training di un modello di classificazione delle immagini da zero richiede l'impostazione di milioni di parametri, una tonata di dati di training etichettati e una grande quantità di risorse di calcolo (centinaia di ore GPU). Anche se non è efficace come il training di un modello personalizzato da zero, l'uso di un modello con training preliminare consente di modificare questo processo usando migliaia di immagini rispetto a milioni di immagini etichettate e creare un modello personalizzato abbastanza rapidamente (entro un'ora in un computer senza GPU). Questa esercitazione consente di ridimensionare ulteriormente il processo, usando solo una dozzina di immagini di training.
Viene Inception model
eseguito il training per classificare le immagini in migliaia di categorie, ma per questa esercitazione è necessario classificare le immagini in un set di categorie più piccolo e solo tali categorie. È possibile usare la Inception model
possibilità di riconoscere e classificare le immagini nelle nuove categorie limitate del classificatore di immagini personalizzato.
- Food
- Giocattoli
- Appliance
Questa esercitazione usa il modello di deep learning TensorFlow Inception , un modello di riconoscimento delle immagini diffuso sottoposto a training nel ImageNet
set di dati. Il modello TensorFlow classifica intere immagini in migliaia di classi, ad esempio "Umbrella", "Jersey" e "Lavastoviglie".
Poiché è Inception model
già stato sottoposto a training preliminare su migliaia di immagini diverse, contiene internamente le funzionalità dell'immagine necessarie per l'identificazione dell'immagine . È possibile usare queste funzionalità di immagine interne nel modello per eseguire il training di un nuovo modello con un numero molto inferiore di classi.
Come illustrato nel diagramma seguente, viene aggiunto un riferimento ai pacchetti NuGet ML.NET nelle applicazioni .NET Core o .NET Framework. Sotto le quinte, ML.NET include e fa riferimento alla libreria nativa TensorFlow
che consente di scrivere codice che carica un file di modello con TensorFlow
training esistente.
Classificazione multiclasse
Dopo aver usato il modello di creazione TensorFlow per estrarre le funzionalità adatte come input per un algoritmo di Machine Learning classico, viene aggiunto un classificatore ML.NET multiclasse.
Il formatore specifico usato in questo caso è l'algoritmo di regressione logistica multinomiale.
L'algoritmo implementato da questo formatore offre prestazioni elevate sui problemi relativi a un numero elevato di funzionalità, che è il caso di un modello di Deep Learning che opera sui dati delle immagini.
Per altre informazioni, vedere Deep Learning e Machine Learning .
Dati
Ci sono due origini dati: il file .tsv
e i file di immagine. Il file tags.tsv
contiene due colonne: la prima è definita come ImagePath
e la seconda è l'oggetto Label
corrispondente all'immagine. Il file di esempio seguente non ha una riga di intestazione e ha l'aspetto seguente:
broccoli.jpg food
pizza.jpg food
pizza2.jpg food
teddy2.jpg toy
teddy3.jpg toy
teddy4.jpg toy
toaster.jpg appliance
toaster2.png appliance
Le immagini di training e di test si trovano nelle cartelle assets che verranno scaricate in un file ZIP. Queste immagini appartengono a Wikimedia Commons.
Wikimedia Commons, il repository di file multimediali gratuiti. Recuperato 10:48, 17 ottobre 2018 da: https://commons.wikimedia.org/wiki/Pizzahttps://commons.wikimedia.org/wiki/Toasterhttps://commons.wikimedia.org/wiki/Teddy_bear
Installazione
Creare un progetto
Creare un'applicazione console C# denominata "TransferLearningTF". Fare clic sul pulsante Next (Avanti).
Scegliere .NET 6 come framework da usare. Fare clic sul pulsante Crea.
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, selezionare la scheda Sfoglia e cercare Microsoft.ML.
- Selezionare il pulsante Installa.
- Selezionare il pulsante OK nella finestra di dialogo Anteprima modifiche .
- Selezionare il pulsante Accetto nella finestra di dialogo Accettazione licenza se si accettano le condizioni di licenza per i pacchetti elencati.
- Ripetere questi passaggi per Microsoft.ML.ImageAnalytics, SciSharp.TensorFlow.Redist e Microsoft.ML.TensorFlow.
Scaricare gli asset
Scaricare il file ZIP della directory degli asset del progetto e decomprimerlo.
Copiare la directory
assets
nella directory del progetto TransferLearningTF. Questa directory e le relative sottodirectory contengono i file di dati e supporto (fatta eccezione per il modello Inception, che verrà scaricato e aggiunto nel passaggio successivo) richiesti per questa esercitazione.Scaricare il modello Inception e decomprimere il file.
Copiare il contenuto della directory
inception5h
appena decompressa nella directoryassets/inception
del progetto TransferLearningTF. 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 assets e nelle relative sottodirectory e selezionare Proprietà. In Avanzate modificare il valore di Copia nella directory di output in Copia se più recente.
Creare le classi e definire i percorsi
Aggiungere le istruzioni
using
seguenti all'inizio del file Program.cs:using Microsoft.ML; using Microsoft.ML.Data;
Aggiungere il codice seguente alla riga immediatamente sotto le istruzioni using per specificare i percorsi degli asset:
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");
Creare classi per i dati di input e le stime.
public class ImageData { [LoadColumn(0)] public string? ImagePath; [LoadColumn(1)] public string? Label; }
ImageData
è la classe dei dati di immagine di input e ha i campi String seguenti:ImagePath
contiene il nome del file di immagine.Label
contiene un valore per l'etichetta dell'immagine.
Aggiungere una nuova classe al progetto per
ImagePrediction
:public class ImagePrediction : ImageData { public float[]? Score; public string? PredictedLabelValue; }
ImagePrediction
è la classe di stima delle immagini e ha i campi seguenti:Score
contiene la percentuale di probabilità per una data classificazione dell'immagine.PredictedLabelValue
contiene un valore per l'etichetta di classificazione dell'immagine stimata.
ImagePrediction
è la classe usata per la stima dopo il training del modello. Ha un oggettostring
(ImagePath
) per il percorso dell'immagine. VieneLabel
usato per riutilizzare e eseguire il training del modello.PredictedLabelValue
viene usato durante la valutazione e la stima. Per la valutazione vengono usati un input con dati di training, i valori stimati e il modello.
Inizializzare le variabili
Inizializzare la variabile
mlContext
con una nuova istanza diMLContext
. Sostituire la riga con ilConsole.WriteLine("Hello World!")
codice seguente:MLContext mlContext = new MLContext();
La MLContext classe è un punto di partenza per tutte le operazioni ML.NET e l'inizializzazione
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 aDBContext
in Entity Framework.
Creare uno struct per i parametri del modello Inception
Il modello Inception include diversi parametri che è necessario passare. Creare uno struct per eseguire il mapping dei valori dei parametri ai nomi descrittivi con il codice seguente, subito dopo l'inizializzazione della
mlContext
variabile: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; }
Creare un metodo dell'utilità di visualizzazione
Poiché i dati dell'immagine e le relative stime verranno visualizzati più volte, creare un metodo dell'utilità di visualizzazione per gestire la visualizzazione dell'immagine e dei risultati delle stime.
Creare il metodo
DisplayResults()
subito dopo lo structInceptionSettings
, usando il codice seguente:void DisplayResults(IEnumerable<ImagePrediction> imagePredictionData) { }
Compilare il corpo del
DisplayResults
metodo:foreach (ImagePrediction prediction in imagePredictionData) { Console.WriteLine($"Image: {Path.GetFileName(prediction.ImagePath)} predicted as: {prediction.PredictedLabelValue} with score: {prediction.Score?.Max()} "); }
Creare un metodo per effettuare una stima
Creare il metodo
ClassifySingleImage()
subito prima del metodoDisplayResults()
, con il codice seguente:void ClassifySingleImage(MLContext mlContext, ITransformer model) { }
Creare un
ImageData
oggetto contenente il percorso completo e il nome del file di immagine per il singoloImagePath
oggetto . Aggiungere il codice seguente come righe successive nelClassifySingleImage()
metodo:var imageData = new ImageData() { ImagePath = _predictSingleImage };
Eseguire una singola stima aggiungendo il codice seguente come riga successiva nel
ClassifySingleImage
metodo:// Make prediction function (input = ImageData, output = ImagePrediction) var predictor = mlContext.Model.CreatePredictionEngine<ImageData, ImagePrediction>(model); var prediction = predictor.Predict(imageData);
Per ottenere la stima, usare il metodo Predict(). 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.Visualizzare i risultati della stima come riga di codice successiva nel metodo
ClassifySingleImage()
:Console.WriteLine($"Image: {Path.GetFileName(imageData.ImagePath)} predicted as: {prediction.PredictedLabelValue} with score: {prediction.Score?.Max()} ");
Costruire la pipeline del modello di ML.NET
Una pipeline di modelli ML.NET è una catena di stima. Nessuna esecuzione durante la costruzione della pipeline. Gli oggetti di stima vengono creati ma non eseguiti.
Aggiungere un metodo per generare il modello
Questo metodo è il cuore dell'esercitazione. Crea una pipeline per il modello e esegue il training della pipeline per produrre il modello di ML.NET. Valuta anche il modello rispetto ad alcuni dati di test precedentemente non visualizzati.
Creare il metodo
GenerateModel()
, subito dopo lo structInceptionSettings
e subito prima del metodoDisplayResults()
, usando il codice seguente:ITransformer GenerateModel(MLContext mlContext) { }
Aggiungere gli stimatori per caricare, ridimensionare ed estrarre i pixel dai dati dell'immagine:
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))
I dati dell'immagine devono essere elaborati nel formato previsto dal modello TensorFlow. In questo caso, le immagini vengono caricate in memoria, ridimensionate in una dimensione coerente e i pixel vengono estratti in un vettore numerico.
Aggiungere lo strumento di stima per caricare il modello TensorFlow e contrassegnarlo:
.Append(mlContext.Model.LoadTensorFlowModel(_inceptionTensorFlowModel). ScoreTensorFlowModel(outputColumnNames: new[] { "softmax2_pre_activation" }, inputColumnNames: new[] { "input" }, addBatchDimensionInput: true))
Questa fase nella pipeline carica il modello TensorFlow in memoria, quindi elabora il vettore di valori pixel tramite la rete del modello TensorFlow. L'applicazione di input a un modello di Deep Learning e la generazione di un output usando il modello, viene definita Assegnazione dei punteggi. Quando si usa il modello nell'intera durata, il punteggio effettua un'inferenza o una stima.
In questo caso si usa tutto il modello TensorFlow, ad eccezione dell'ultimo livello, ovvero il livello che rende l'inferenza. L'output del penultimo livello è etichettato
softmax_2_preactivation
. L'output di questo livello è effettivamente un vettore di funzionalità che caratterizza le immagini di input originali.Questo vettore di funzionalità generato dal modello TensorFlow verrà usato come input per un algoritmo di training ML.NET.
Aggiungere lo strumento di stima per eseguire il mapping delle etichette di stringa nei dati di training ai valori di chiave integer:
.Append(mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "LabelKey", inputColumnName: "Label"))
Il formatore ML.NET aggiunto successivamente richiede che le etichette siano in
key
formato anziché stringhe arbitrarie. Una chiave è un numero che ha un mapping uno a uno a un valore stringa.Aggiungere l'algoritmo di training ML.NET:
.Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName: "LabelKey", featureColumnName: "softmax2_pre_activation"))
Aggiungere lo strumento di stima per eseguire il mapping del valore della chiave stimata in una stringa:
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabelValue", "PredictedLabel")) .AppendCacheCheckpoint(mlContext);
Eseguire il training del modello
Caricare i dati di training usando il wrapper LoadFromTextFile . Aggiungere il codice seguente al metodo
GenerateModel()
come riga successiva:IDataView trainingData = mlContext.Data.LoadFromTextFile<ImageData>(path: _trainTagsTsv, hasHeader: false);
I dati in ML.NET sono rappresentati come interfaccia IDataView.
IDataView
è un modo flessibile ed efficiente di descrivere i dati tabulari (numerici e di testo). È possibile caricare dati da un file di testo o in tempo reale, ad esempio da un database SQL o file di log, in un oggettoIDataView
.Eseguire il training del modello con i dati caricati in precedenza:
ITransformer model = pipeline.Fit(trainingData);
Il
Fit()
metodo esegue il training del modello applicando il set di dati di training alla pipeline.
Valutare l'accuratezza del modello
Caricare e trasformare i dati di test aggiungendo il codice seguente alla riga successiva del
GenerateModel
metodo: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);
Esistono alcune immagini di esempio che è possibile usare per valutare il modello. Come i dati di training, questi devono essere caricati in un
IDataView
oggetto , in modo che possano essere trasformati dal modello.Aggiungere il codice seguente al
GenerateModel()
metodo per valutare il modello:MulticlassClassificationMetrics metrics = mlContext.MulticlassClassification.Evaluate(predictions, labelColumnName: "LabelKey", predictedLabelColumnName: "PredictedLabel");
Dopo aver impostato la stima, il metodo Evaluate():
- Valuta il modello (confronta i valori stimati con il set di dati
labels
di test). - Restituisce le metriche relative alle prestazioni del modello.
- Valuta il modello (confronta i valori stimati con il set di dati
Visualizzare le metriche di accuratezza del modello
Usare il codice seguente per visualizzare le metriche, condividere i risultati e quindi intervenire su di essi:
Console.WriteLine($"LogLoss is: {metrics.LogLoss}"); Console.WriteLine($"PerClassLogLoss is: {String.Join(" , ", metrics.PerClassLogLoss.Select(c => c.ToString()))}");
Le metriche seguenti vengono valutate per la classificazione delle immagini:
Log-loss
: vedere Perdita di log. Il valore desiderato per LogLoss è il valore più prossimo a 0.Per class Log-loss
. Il valore desiderato per LogLoss per classe è il valore più prossimo a 0.
Aggiungere il codice seguente per restituire il modello sottoposto a training come riga successiva:
return model;
Eseguire l'applicazione.
Aggiungere la chiamata a
GenerateModel
dopo la creazione della MLContext classe:ITransformer model = GenerateModel(mlContext);
Aggiungere la chiamata al
ClassifySingleImage()
metodo dopo la chiamata alGenerateModel()
metodo:ClassifySingleImage(mlContext, model);
Eseguire l'app console (CTRL + F5). I risultati saranno simili all'output seguente. È possibile che vengano visualizzati avvisi o messaggi di elaborazione, ma questi messaggi sono stati rimossi dai risultati seguenti per chiarezza.
=============== 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
Congratulazioni! È stato creato un modello di classificazione in ML.NET per classificare le immagini usando un TensorFlow pre-sottoposto a training per l'elaborazione delle immagini.
È possibile trovare il codice sorgente per questa esercitazione nel repository dotnet/samples.
In questa esercitazione sono state illustrate le procedure per:
- Informazioni sul problema
- Incorporare il modello TensorFlow pre-sottoposto a training nella pipeline di ML.NET
- Eseguire il training e valutare il modello di ML.NET
- Classificare un'immagine di test
Consultare il repository GitHub degli esempi di Machine Learning per esaminare un esempio di classificazione delle immagini esteso.