Delen via


Zelfstudie: Een ML.NET-classificatiemodel trainen om afbeeldingen te categoriseren

Leer hoe u een classificatiemodel traint om afbeeldingen te categoriseren met behulp van een vooraf getraind TensorFlow-model voor afbeeldingsverwerking.

Het TensorFlow-model is getraind om afbeeldingen in duizend categorieën te classificeren. Omdat het TensorFlow-model weet hoe patronen in afbeeldingen moeten worden herkend, kan het ML.NET model een deel ervan in de pijplijn gebruiken om onbewerkte afbeeldingen te converteren naar functies of invoer om een classificatiemodel te trainen.

In deze handleiding leer je hoe je:

  • Het probleem begrijpen
  • Het vooraf getrainde TensorFlow-model opnemen in de ML.NET-pijplijn
  • Het ML.NET-model trainen en evalueren
  • Een testafbeelding classificeren

U vindt de broncode voor deze zelfstudie in de opslagplaats dotnet/samples . De .NET-projectconfiguratie voor deze zelfstudie is standaard gericht op .NET Core 2.2.

Vereiste voorwaarden

De juiste machine learning-taak selecteren

Diep leren

Deep Learning is een subset van Machine Learning, die een revolutie vormt voor gebieden als computer vision en spraakherkenning.

Deep Learning-modellen worden getraind met behulp van grote sets gelabelde gegevens en neurale netwerken die meerdere leerlagen bevatten. Deep Learning:

  • Presteert beter voor sommige taken, zoals computer vision.
  • Hiervoor zijn enorme hoeveelheden trainingsgegevens vereist.

Afbeeldingsclassificatie is een specifieke classificatietaak waarmee we afbeeldingen automatisch kunnen classificeren in categorieën zoals:

  • Het detecteren van een menselijk gezicht in een afbeelding of niet.
  • Katten detecteren versus honden.

Of net als in de volgende afbeeldingen, bepalen of een afbeelding een voedsel, speelgoed of apparaat is:

pizza afbeelding teddybeer afbeelding afbeelding broodrooster

Opmerking

De voorgaande beelden behoren tot De Commons van Wikimedia en worden als volgt toegeschreven:

Voor het trainen van een volledig nieuw afbeeldingsclassificatiemodel moeten miljoenen parameters, een ton met gelabelde trainingsgegevens en een grote hoeveelheid rekenresources (honderden GPU-uren) worden ingesteld. Hoewel het niet zo effectief is als het trainen van een aangepast model, kunt u met behulp van een vooraf getraind model dit proces versnellen door te werken met duizenden afbeeldingen versus miljoenen gelabelde afbeeldingen en vrij snel een aangepast model te bouwen (binnen een uur op een machine zonder GPU). In deze zelfstudie wordt het proces nog verder geschaald, met behulp van slechts een dozijn trainingsafbeeldingen.

Het Inception model is getraind om afbeeldingen te classificeren in duizend categorieën, maar voor deze zelfstudie moet u afbeeldingen classificeren in een kleinere categorieset en alleen die categorieën. U kunt de Inception modelmogelijkheid gebruiken om afbeeldingen te herkennen en te classificeren in de nieuwe beperkte categorieën van uw aangepaste afbeeldingsclassificatie.

  • Voedsel
  • Speelgoed
  • Apparaat

Deze zelfstudie maakt gebruik van het deep learning-model TensorFlow Inception, een populair model voor afbeeldingsherkenning dat is getraind op de ImageNet dataset. Het TensorFlow-model classificeert volledige afbeeldingen in duizend klassen, zoals 'Umbrella', 'Jersey' en 'Vaatwasser'.

Omdat het Inception model model al is voorgetraind op duizenden verschillende afbeeldingen, bevat het intern de beeldkenmerken die nodig zijn voor afbeeldingsidentificatie. We kunnen gebruikmaken van deze interne afbeeldingsfuncties in het model om een nieuw model met veel minder klassen te trainen.

Zoals wordt weergegeven in het volgende diagram, voegt u een verwijzing toe naar de ML.NET NuGet-pakketten in uw .NET- of .NET Framework-toepassingen. Achter de schermen omvat ML.NET de systeemeigen TensorFlow bibliotheek, die u in staat stelt code te schrijven waarmee een bestaand getraind modelbestand TensorFlow wordt geladen.

TensorFlow Transform ML.NET Architectuurdiagram

Classificatie met meerdere klassen

Nadat u het TensorFlow-beginmodel hebt gebruikt om functies te extraheren die geschikt zijn als invoer voor een klassiek machine learning-algoritme, voegt u een ML.NET classificatie met meerdere klassen toe.

De specifieke trainer die in dit geval wordt gebruikt, is het multinomiale logistieke regressie-algoritme.

Het algoritme dat door deze trainer wordt geïmplementeerd, presteert goed op problemen met een groot aantal functies, wat het geval is voor een Deep Learning-model dat op afbeeldingsgegevens werkt.

Zie Deep Learning versus machine learning voor meer informatie.

Gegevens

Er zijn twee gegevensbronnen: het .tsv bestand en de afbeeldingsbestanden. Het tags.tsv bestand bevat twee kolommen: de eerste wordt gedefinieerd als ImagePath en de tweede is de Label corresponderende afbeelding. Het volgende voorbeeldbestand heeft geen koprij en is als volgt:

broccoli.jpg	food
pizza.jpg	food
pizza2.jpg	food
teddy2.jpg	toy
teddy3.jpg	toy
teddy4.jpg	toy
toaster.jpg	appliance
toaster2.png	appliance

De trainings- en testafbeeldingen bevinden zich in de assetsmappen die u in een zip-bestand downloadt. Deze beelden behoren tot Wikimedia Commons.

Wikimedia Commons, de gratis mediaopslagplaats. Opgehaald 10:48, 17 oktober 2018 van: https://commons.wikimedia.org/wiki/Pizzahttps://commons.wikimedia.org/wiki/Toasterhttps://commons.wikimedia.org/wiki/Teddy_bear

Configuratie

Een project maken

  1. Maak een C# -consoletoepassing met de naam TransferLearningTF. Klik op de knop Volgende.

  2. Kies .NET 8 als framework dat u wilt gebruiken. Klik op de knop Maken.

  3. Installeer het Microsoft.ML NuGet-pakket:

    Opmerking

    In dit voorbeeld wordt de laatste stabiele versie van de vermelde NuGet-pakketten gebruikt, tenzij anders vermeld.

    • Klik in Solution Explorer met de rechtermuisknop op uw project en selecteer NuGet-pakketten beheren.
    • Kies 'nuget.org' als pakketbron, selecteer het tabblad Bladeren, zoek naar Microsoft.ML.
    • Selecteer de knop Installeren .
    • Selecteer de knop OK in het dialoogvenster Voorbeeldwijzigingen .
    • Selecteer de knop Accepteren in het dialoogvenster Licentie accepteren als u akkoord gaat met de licentievoorwaarden voor de vermelde pakketten.
    • Herhaal deze stappen voor Microsoft.ML.ImageAnalytics, SciSharp.TensorFlow.Redist en Microsoft.ML.TensorFlow.

Assets downloaden

  1. Downloaden het zip-bestand van de projectbestandenmap en pak het uit.

  2. Kopieer de map naar de assetsprojectmap TransferLearningTF . Deze map en de submappen bevatten de gegevens en ondersteuningsbestanden (met uitzondering van het Inception-model, dat u in de volgende stap gaat downloaden en toevoegen) die nodig zijn voor deze tutorial.

  3. Download het Inception model en pak het uit.

  4. Kopieer de inhoud van de inception5h map die u zojuist hebt uitgepakt naar uw TransferLearningTFassets/inception map. Deze map bevat het model en aanvullende ondersteuningsbestanden die nodig zijn voor deze zelfstudie, zoals wordt weergegeven in de volgende afbeelding:

    Inhoud van de beginmap

  5. Klik in Solution Explorer met de rechtermuisknop op elk van de bestanden in de assetmap en submappen en selecteer Eigenschappen. Wijzig onder Geavanceerd de waarde van Kopiëren naar Uitvoermap naar Kopiëren als nieuwer.

Klassen maken en paden definiëren

  1. Voeg de volgende aanvullende using instructies toe aan het begin van het bestand Program.cs :

    using Microsoft.ML;
    using Microsoft.ML.Data;
    
  2. Voeg de volgende code toe aan de regel rechts onder de using instructies om de assetpaden op te geven:

    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. Maak klassen voor uw invoergegevens en voorspellingen.

    public class ImageData
    {
        [LoadColumn(0)]
        public string? ImagePath;
    
        [LoadColumn(1)]
        public string? Label;
    }
    

    ImageData is de klasse invoerafbeeldingsgegevens en heeft de volgende String velden:

    • ImagePath bevat de naam van het afbeeldingsbestand.
    • Label bevat een waarde voor het afbeeldingslabel.
  4. Voeg een nieuwe klasse toe aan uw project voor ImagePrediction:

    public class ImagePrediction : ImageData
    {
        public float[]? Score;
    
        public string? PredictedLabelValue;
    }
    

    ImagePrediction is de voorspellingsklasse voor afbeeldingen en heeft de volgende velden:

    • Score bevat het betrouwbaarheidspercentage voor een bepaalde afbeeldingsclassificatie.
    • PredictedLabelValue bevat een waarde voor het voorspelde label voor afbeeldingsclassificatie.

    ImagePrediction is de klasse die wordt gebruikt voor voorspelling nadat het model is getraind. Het heeft een string (ImagePath) voor het afbeeldingspad. Het Label model wordt gebruikt om het model opnieuw te gebruiken en te trainen. De PredictedLabelValue wordt gebruikt tijdens de voorspelling en evaluatie. Voor evaluatie worden invoer met trainingsgegevens, de voorspelde waarden en het model gebruikt.

Variabelen initialiseren

  1. Initialiseer de mlContext variabele met een nieuw exemplaar van MLContext. Vervang de Console.WriteLine("Hello World!") regel door de volgende code:

    MLContext mlContext = new MLContext();
    

    De MLContext klasse is een startpunt voor alle ML.NET bewerkingen en het initialiseren mlContext van een nieuwe ML.NET-omgeving die kan worden gedeeld in de werkstroomobjecten voor het maken van modellen. Het is vergelijkbaar, conceptueel gezien, met DBContext in Entity Framework.

Een struct maken voor De parameters van het Beginmodel

  1. Het Beginmodel heeft verschillende parameters die u moet doorgeven. Maak een struct om de parameterwaarden te koppelen aan gebruiksvriendelijke namen met de volgende code, net nadat de mlContext variabele is geïnitialiseerd:

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

Een weergavehulpprogrammamethode maken

Omdat u de afbeeldingsgegevens en de gerelateerde voorspellingen meer dan één keer weergeeft, maakt u een weergavehulpprogrammamethode voor het afhandelen van de weergave van de afbeeldings- en voorspellingsresultaten.

  1. Maak de DisplayResults() methode, net na de InceptionSettings struct, met behulp van de volgende code:

    void DisplayResults(IEnumerable<ImagePrediction> imagePredictionData)
    {
    
    }
    
  2. Vul de hoofdtekst van de DisplayResults methode in:

    foreach (ImagePrediction prediction in imagePredictionData)
    {
        Console.WriteLine($"Image: {Path.GetFileName(prediction.ImagePath)} predicted as: {prediction.PredictedLabelValue} with score: {prediction.Score?.Max()} ");
    }
    

Een methode maken om een voorspelling te doen

  1. Maak de ClassifySingleImage() methode, net vóór de DisplayResults() methode, met behulp van de volgende code:

    void ClassifySingleImage(MLContext mlContext, ITransformer model)
    {
    
    }
    
  2. Maak een ImageData object dat het volledig gekwalificeerde pad en de afbeeldingsbestandsnaam voor het enkele ImagePath bevat. Voeg de volgende code toe als de volgende regels in de ClassifySingleImage() methode:

    var imageData = new ImageData()
    {
        ImagePath = _predictSingleImage
    };
    
  3. Maak één voorspelling door de volgende code toe te voegen als de volgende regel in de ClassifySingleImage methode:

    // Make prediction function (input = ImageData, output = ImagePrediction)
    var predictor = mlContext.Model.CreatePredictionEngine<ImageData, ImagePrediction>(model);
    var prediction = predictor.Predict(imageData);
    

    Als u de voorspelling wilt ophalen, gebruikt u de methode Predict( ). PredictionEngine is een handige API, waarmee u een voorspelling kunt uitvoeren op één exemplaar van gegevens. PredictionEngine is niet thread-safe. Het is acceptabel om te gebruiken in omgevingen met één thread of prototype. Voor verbeterde prestaties en threadveiligheid in productieomgevingen gebruikt u de PredictionEnginePool service, waarmee u objecten ObjectPoolPredictionEngine maakt voor gebruik in uw toepassing. Raadpleeg deze handleiding voor het gebruik PredictionEnginePool in een ASP.NET Core Web-API.

    Opmerking

    PredictionEnginePool de service-extensie is momenteel beschikbaar als preview-versie.

  4. Het voorspellingsresultaat weergeven als de volgende regel code in de ClassifySingleImage() methode:

    Console.WriteLine($"Image: {Path.GetFileName(imageData.ImagePath)} predicted as: {prediction.PredictedLabelValue} with score: {prediction.Score?.Max()} ");
    

De ML.NET-modelpijplijn maken

Een ML.NET modelpijplijn is een keten van schattingen. Er wordt geen uitvoering uitgevoerd tijdens de pijplijnconstructie. De estimatorobjecten worden gemaakt maar niet uitgevoerd.

  1. Een methode toevoegen om het model te genereren

    Deze methode is het hart van de handleiding. Er wordt een pijplijn voor het model gemaakt en de pijplijn getraind om het ML.NET model te produceren. Ook wordt het model geëvalueerd op basis van enkele eerder ongelezen testgegevens.

    Maak de GenerateModel() methode, net na de InceptionSettings struct en net vóór de DisplayResults() methode, met behulp van de volgende code:

    ITransformer GenerateModel(MLContext mlContext)
    {
    
    }
    
  2. Voeg de schattingen toe om de pixels te laden, het formaat ervan te wijzigen en te extraheren uit de afbeeldingsgegevens:

    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))
    

    De afbeeldingsgegevens moeten worden verwerkt in de indeling die het TensorFlow-model verwacht. In dit geval worden de afbeeldingen in het geheugen geladen, het formaat ervan gewijzigd in een consistente grootte en worden de pixels geëxtraheerd in een numerieke vector.

  3. Voeg de estimator toe om het TensorFlow-model te laden en deze te beoordelen:

    .Append(mlContext.Model.LoadTensorFlowModel(_inceptionTensorFlowModel).
        ScoreTensorFlowModel(outputColumnNames: new[] { "softmax2_pre_activation" }, inputColumnNames: new[] { "input" }, addBatchDimensionInput: true))
    

    Deze fase in de pijplijn laadt het TensorFlow-model in het geheugen en verwerkt vervolgens de vector van pixelwaarden via het TensorFlow-modelnetwerk. Invoer toepassen op een Deep Learning-model en een uitvoer genereren met behulp van het model, wordt scoren genoemd. Wanneer u het model in zijn geheel gebruikt, wordt er door middel van waardering een deductie of voorspelling gemaakt.

    In dit geval gebruikt u al het TensorFlow-model, behalve de laatste laag, de laag die deductie maakt. De uitvoer van de penultimatelaag is gelabeld softmax_2_preactivation. De uitvoer van deze laag is effectief een vector van functies die de oorspronkelijke invoerafbeeldingen karakteriseren.

    Deze functievector die door het TensorFlow-model wordt gegenereerd, wordt gebruikt als invoer voor een ML.NET trainingsalgoritmen.

  4. Voeg de estimator toe om de tekenreekslabels in de trainingsgegevens toe te wijzen aan sleutelwaarden voor gehele getallen:

    .Append(mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "LabelKey", inputColumnName: "Label"))
    

    De ML.NET trainer die hierna wordt toegevoegd, vereist dat de labels in key indeling zijn in plaats van willekeurige tekenreeksen. Een sleutel is een getal met een directe koppeling aan een tekenreekswaarde.

  5. Voeg het ML.NET trainingsalgoritmen toe:

    .Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName: "LabelKey", featureColumnName: "softmax2_pre_activation"))
    
  6. Voeg de estimator toe om de voorspelde sleutelwaarde weer toe te wijzen aan een tekenreeks:

    .Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabelValue", "PredictedLabel"))
    .AppendCacheCheckpoint(mlContext);
    

Het model trainen

  1. Laad de trainingsgegevens met behulp van de Wrapper LoadFromTextFile . Voeg de volgende code toe als de volgende regel in de GenerateModel() methode:

    IDataView trainingData = mlContext.Data.LoadFromTextFile<ImageData>(path:  _trainTagsTsv, hasHeader: false);
    

    Gegevens in ML.NET worden weergegeven als een IDataView-interface. IDataView is een flexibele, efficiënte manier om tabelgegevens (numeriek en tekst) te beschrijven. Gegevens kunnen vanuit een tekstbestand of in realtime (bijvoorbeeld SQL-database of logboekbestanden) naar een IDataView object worden geladen.

  2. Train het model met de gegevens die hierboven zijn geladen:

    ITransformer model = pipeline.Fit(trainingData);
    

    De Fit() methode traint uw model door de trainingsgegevensset toe te passen op de pijplijn.

De nauwkeurigheid van het model evalueren

  1. Laad en transformeer de testgegevens door de volgende code toe te voegen aan de volgende regel van de GenerateModel methode:

    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);
    

    Er zijn enkele voorbeeldafbeeldingen die u kunt gebruiken om het model te evalueren. Net als de trainingsgegevens moeten deze worden geladen in een IDataView, zodat ze kunnen worden getransformeerd door het model.

  2. Voeg de volgende code toe aan de GenerateModel() methode om het model te evalueren:

    MulticlassClassificationMetrics metrics =
        mlContext.MulticlassClassification.Evaluate(predictions,
            labelColumnName: "LabelKey",
            predictedLabelColumnName: "PredictedLabel");
    

    Zodra u de voorspellingsset hebt, wordt de methode Evaluate() gebruikt :

    • Evalueert het model (vergelijkt de voorspelde waarden met de testgegevensset labels).
    • Retourneert de metrische gegevens over de prestaties van het model.
  3. De metrische gegevens over de nauwkeurigheid van het model weergeven

    Gebruik de volgende code om de metrische gegevens weer te geven, de resultaten te delen en er vervolgens actie op te ondernemen:

    Console.WriteLine($"LogLoss is: {metrics.LogLoss}");
    Console.WriteLine($"PerClassLogLoss is: {String.Join(" , ", metrics.PerClassLogLoss.Select(c => c.ToString()))}");
    

    De volgende metrische gegevens worden geëvalueerd voor afbeeldingsclassificatie:

    • Log-loss - zie Logboekverlies. U wilt dat logboekverlies zo dicht mogelijk bij nul ligt.
    • Per class Log-loss. U wilt dat logboekverlies per klasse zo dicht mogelijk bij nul ligt.
  4. Voeg de volgende code toe om het getrainde model als volgende regel te retourneren:

    return model;
    

De toepassing uitvoeren

  1. Voeg de aanroep toe aan GenerateModel na het maken van de MLContext klasse:

    ITransformer model = GenerateModel(mlContext);
    
  2. Voeg de aanroep toe aan de ClassifySingleImage() methode na de aanroep naar de GenerateModel() methode:

    ClassifySingleImage(mlContext, model);
    
  3. Voer uw console-app uit (Ctrl + F5). Uw resultaten moeten vergelijkbaar zijn met de volgende uitvoer. (U ziet mogelijk waarschuwingen of het verwerken van berichten, maar deze berichten zijn verwijderd uit de volgende resultaten ter duidelijkheid.)

    =============== 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
    

Gefeliciteerd! U hebt nu een classificatiemodel gebouwd in ML.NET om afbeeldingen te categoriseren met behulp van een vooraf getrainde TensorFlow voor afbeeldingsverwerking.

U vindt de broncode voor deze zelfstudie in de opslagplaats dotnet/samples .

In deze tutorial leerde je hoe je:

  • Het probleem begrijpen
  • Het vooraf getrainde TensorFlow-model opnemen in de ML.NET-pijplijn
  • Het ML.NET-model trainen en evalueren
  • Een testafbeelding classificeren

Bekijk de GitHub-opslagplaats met Machine Learning-voorbeelden om een uitgebreid voorbeeld van afbeeldingsclassificatie te verkennen.