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

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:

immagine pizzaimmagine orsacchiotto immaginetostapane immagine

Nota

Le immagini precedenti appartengono a Wikimedia Commons, con gli attributi seguenti:

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 modelpossibilità 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.

Diagramma dell'architettura ML.NET per la trasformazione TensorFlow

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

  1. Creare un'applicazione console C# denominata "TransferLearningTF". Fare clic sul pulsante Next (Avanti).

  2. Scegliere .NET 6 come framework da usare. Fare clic sul pulsante Crea.

  3. 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

  1. Scaricare il file ZIP della directory degli asset del progetto e decomprimerlo.

  2. 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.

  3. Scaricare il modello Inception e decomprimere il file.

  4. Copiare il contenuto della directory inception5h appena decompressa nella directory assets/inception del progetto TransferLearningTF. Questa directory contiene il modello e i file di supporto aggiuntivi necessari per questa esercitazione, come illustrato nell'immagine seguente:

    Contenuto della directory Inception

  5. 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

  1. Aggiungere le istruzioni using seguenti all'inizio del file Program.cs:

    using Microsoft.ML;
    using Microsoft.ML.Data;
    
  2. 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");
    
  3. 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.
  4. 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 oggetto string (ImagePath) per il percorso dell'immagine. Viene Label 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

  1. Inizializzare la variabile mlContext con una nuova istanza di MLContext. Sostituire la riga con il Console.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 a DBContext in Entity Framework.

Creare uno struct per i parametri del modello Inception

  1. 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.

  1. Creare il metodo DisplayResults() subito dopo lo struct InceptionSettings, usando il codice seguente:

    void DisplayResults(IEnumerable<ImagePrediction> imagePredictionData)
    {
    
    }
    
  2. 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

  1. Creare il metodo ClassifySingleImage() subito prima del metodo DisplayResults(), con il codice seguente:

    void ClassifySingleImage(MLContext mlContext, ITransformer model)
    {
    
    }
    
  2. Creare un ImageData oggetto contenente il percorso completo e il nome del file di immagine per il singolo ImagePathoggetto . Aggiungere il codice seguente come righe successive nel ClassifySingleImage() metodo:

    var imageData = new ImageData()
    {
        ImagePath = _predictSingleImage
    };
    
  3. 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 il PredictionEnginePool servizio, che crea un ObjectPool oggetto da PredictionEngine usare in tutta l'applicazione. Vedere questa guida su come usare PredictionEnginePool in un'API Web di ASP.NET Core.

    Nota

    L'estensione del servizio PredictionEnginePool è attualmente in anteprima.

  4. 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.

  1. 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 struct InceptionSettings e subito prima del metodo DisplayResults(), usando il codice seguente:

    ITransformer GenerateModel(MLContext mlContext)
    {
    
    }
    
  2. 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.

  3. 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.

  4. 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.

  5. Aggiungere l'algoritmo di training ML.NET:

    .Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName: "LabelKey", featureColumnName: "softmax2_pre_activation"))
    
  6. 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

  1. 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 oggetto IDataView.

  2. 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

  1. 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 IDataViewoggetto , in modo che possano essere trasformati dal modello.

  2. 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 labelsdi test).
    • Restituisce le metriche relative alle prestazioni del modello.
  3. 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.
  4. Aggiungere il codice seguente per restituire il modello sottoposto a training come riga successiva:

    return model;
    

Eseguire l'applicazione.

  1. Aggiungere la chiamata a GenerateModel dopo la creazione della MLContext classe:

    ITransformer model = GenerateModel(mlContext);
    
  2. Aggiungere la chiamata al ClassifySingleImage() metodo dopo la chiamata al GenerateModel() metodo:

    ClassifySingleImage(mlContext, model);
    
  3. 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.