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 zelfstudie leert u het volgende:
- Inzicht in het probleem
- 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 . Standaard is de .NET-projectconfiguratie voor deze zelfstudie gericht op .NET core 2.2.
Vereisten
- Visual Studio 2022
- De map assets van de zelfstudie .ZIP-bestand
- Het Machine Learning-model Van InceptionV1
De juiste machine learning-taak selecteren
Deep learning
Deep Learning is een subset van Machine Learning, die een revolutie teweegbrengen op 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 op sommige taken, zoals Computer Vision.
- Vereist enorme hoeveelheden trainingsgegevens.
Afbeeldingsclassificatie is een specifieke classificatietaak waarmee we afbeeldingen automatisch kunnen classificeren in categorieën zoals:
- Een menselijk gezicht in een afbeelding detecteren of niet.
- Katten versus honden detecteren.
Of, zoals in de volgende afbeeldingen, om te bepalen of een afbeelding een voedsel, speelgoed of apparaat is:
Notitie
De voorgaande afbeeldingen zijn eigendom van Wikimedia Commons en worden als volgt toegeschreven:
- "220px-Pepperoni_pizza.jpg" Openbaar domein, https://commons.wikimedia.org/w/index.php?curid=79505,
- "119px-Nalle_-_a_small_brown_teddy_bear.jpg" Door Jonik - Zelffotografeerd, CC BY-SA 2.0, https://commons.wikimedia.org/w/index.php?curid=48166.
- "193px-Broodrooster.jpg" By M.Minderhoud - Eigen werk, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=27403
Als u een volledig nieuw afbeeldingsclassificatiemodel wilt trainen, moet u miljoenen parameters, een groot aantal gelabelde trainingsgegevens en een enorme hoeveelheid rekenresources (honderden GPU-uren) instellen. Hoewel het niet zo effectief is als het trainen van een aangepast model, kunt u met een vooraf getraind model dit proces versnellen door te werken met duizenden installatiekopieën versus miljoenen gelabelde afbeeldingen en vrij snel een aangepast model te bouwen (binnen een uur op een computer zonder GPU). In deze zelfstudie wordt het proces nog verder omlaag geschaald met behulp van slechts een dozijn trainingsafbeeldingen.
De Inception model
is getraind om afbeeldingen in duizend categorieën te classificeren, maar voor deze zelfstudie moet u afbeeldingen classificeren in een kleinere categorieset en alleen die categorieën. U kunt de Inception model
mogelijkheid gebruiken om afbeeldingen te herkennen en te classificeren in de nieuwe beperkte categorieën van uw aangepaste afbeeldingsclassificatie.
- Voedsel
- Toy
- Apparaat
In deze zelfstudie wordt gebruikgemaakt van het Deep Learning-model tensorFlow , een populair model voor afbeeldingsherkenning dat is getraind op de ImageNet
gegevensset. Het TensorFlow-model classificeert volledige afbeeldingen in duizend klassen, zoals 'Umbrella', 'Jersey' en 'Vaatwasser'.
Omdat de Inception model
al vooraf is getraind op duizenden verschillende afbeeldingen, bevat het intern de installatiekopieën die nodig zijn voor afbeeldingsidentificatie. We kunnen gebruikmaken van deze interne installatiekopieën in het model om een nieuw model met veel minder klassen te trainen.
Zoals in het volgende diagram wordt weergegeven, voegt u een verwijzing toe naar de ML.NET NuGet-pakketten in uw .NET Core- of .NET Framework-toepassingen. ML.NET bevat en verwijst naar de systeemeigen TensorFlow
bibliotheek waarmee u code kunt schrijven waarmee een bestaand getraind TensorFlow
modelbestand wordt geladen.
Classificatie met meerdere klassen
Nadat we het beginmodel van TensorFlow hebben gebruikt om functies te extraheren die geschikt zijn als invoer voor een klassiek machine learning-algoritme, voegen we 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 is geïmplementeerd, presteert goed bij problemen met een groot aantal functies, wat het geval is voor een deep learning-model dat werkt op afbeeldingsgegevens.
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 is gedefinieerd als ImagePath
en de tweede de Label
kolom die overeenkomt met de afbeelding. Het volgende voorbeeldbestand heeft geen veldnamenrij en ziet er als volgt uit:
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 assets-mappen die u in een ZIP-bestand downloadt. Deze beelden zijn van Wikimedia Commons.
Wikimedia Commons, de gratis mediaopslagplaats. Opgehaald op 10:48, 17 oktober 2018 van: https://commons.wikimedia.org/wiki/Pizzahttps://commons.wikimedia.org/wiki/Toasterhttps://commons.wikimedia.org/wiki/Teddy_bear
Instellen
Een project maken
Maak een C# -consoletoepassing met de naam TransferLearningTF. Klik op de knop Next
Kies .NET 6 als het framework dat u wilt gebruiken. Klik op de knop Maken.
Installeer het Microsoft.ML NuGet-pakket:
Notitie
In dit voorbeeld wordt de meest recente 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 en zoek naar Microsoft.ML.
- Selecteer de knop Installeren .
- Selecteer de knop OK in het dialoogvenster Voorbeeld van wijzigingen .
- Selecteer de knop Ik ga akkoord in het dialoogvenster Licentie-acceptatie 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
Download het zip-bestand van de map met projectactiva en pak het bestand uit.
Kopieer de map naar de
assets
projectmap TransferLearningTF . Deze map en de bijbehorende 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 zelfstudie.Download het Inception-model en pak het uit.
Kopieer de inhoud van de
inception5h
map die zojuist is uitgepakt naar de projectmapassets/inception
TransferLearningTF. Deze map bevat het model en de aanvullende ondersteuningsbestanden die nodig zijn voor deze zelfstudie, zoals wordt weergegeven in de volgende afbeelding: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 in Kopiëren indien nieuwer.
Klassen maken en paden definiëren
Voeg de volgende aanvullende
using
instructies toe aan het begin van het bestand Program.cs :using Microsoft.ML; using Microsoft.ML.Data;
Voeg de volgende code toe aan de regel direct 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");
Maak klassen voor uw invoergegevens en voorspellingen.
public class ImageData { [LoadColumn(0)] public string? ImagePath; [LoadColumn(1)] public string? Label; }
ImageData
is de gegevensklasse van de invoerafbeelding en heeft de volgende String velden:ImagePath
bevat de naam van het installatiekopieënbestand.Label
bevat een waarde voor het afbeeldingslabel.
Voeg een nieuwe klasse toe aan uw project voor
ImagePrediction
:public class ImagePrediction : ImageData { public float[]? Score; public string? PredictedLabelValue; }
ImagePrediction
is de voorspellingsklasse van de afbeelding en heeft de volgende velden:Score
bevat het betrouwbaarheidspercentage voor een bepaalde afbeeldingsclassificatie.PredictedLabelValue
bevat een waarde voor het label voor de voorspelde afbeeldingsclassificatie.
ImagePrediction
is de klasse die wordt gebruikt voor voorspelling nadat het model is getraind. Het heeft eenstring
(ImagePath
) voor het pad naar de installatiekopieën. DeLabel
wordt gebruikt om het model opnieuw te gebruiken en te trainen. DePredictedLabelValue
wordt gebruikt tijdens voorspelling en evaluatie. Voor de evaluatie wordt een invoer met trainingsgegevens, de voorspelde waarden en het model gebruikt.
Variabelen initialiseren
Initialiseer de
mlContext
variabele met een nieuw exemplaar vanMLContext
. Vervang deConsole.WriteLine("Hello World!")
regel door de volgende code:MLContext mlContext = new MLContext();
De MLContext klasse is een startpunt voor alle ML.NET bewerkingen en als u initialiseert
mlContext
, wordt er een nieuwe ML.NET omgeving gemaakt die kan worden gedeeld met de werkstroomobjecten voor het maken van modellen. Het is conceptueelDBContext
vergelijkbaar met in Entity Framework.
Een struct maken voor parameters van het Beginmodel
Het Inception-model heeft verschillende parameters die u moet doorgeven. Maak een struct om de parameterwaarden toe te wijzen aan beschrijvende namen met de volgende code, net na het initialiseren van de
mlContext
variabele: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 bijbehorende voorspellingen meer dan één keer weergeeft, maakt u een weergavehulpprogrammamethode om de weergave van de afbeelding en voorspellingsresultaten te verwerken.
Maak de
DisplayResults()
methode, net na deInceptionSettings
struct, met behulp van de volgende code:void DisplayResults(IEnumerable<ImagePrediction> imagePredictionData) { }
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
Maak de
ClassifySingleImage()
methode, net vóór deDisplayResults()
methode, met behulp van de volgende code:void ClassifySingleImage(MLContext mlContext, ITransformer model) { }
Maak een
ImageData
-object dat het volledig gekwalificeerde pad en de naam van het afbeeldingsbestand voor de eneImagePath
bevat. Voeg de volgende code toe als de volgende regels in deClassifySingleImage()
methode:var imageData = new ImageData() { ImagePath = _predictSingleImage };
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);
Gebruik de predict()- methode om de voorspelling op te halen. De 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 dePredictionEnginePool
service, waarmee eenObjectPool
vanPredictionEngine
-objecten wordt gemaakt voor gebruik in uw toepassing. Raadpleeg deze handleiding over het gebruikPredictionEnginePool
in een ASP.NET Core web-API.Notitie
PredictionEnginePool
de service-extensie is momenteel in preview.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 pijplijn voor het ML.NET-model maken
Een ML.NET modelpijplijn is een keten van schattingen. Er vindt geen uitvoering plaats tijdens het bouwen van de pijplijn. De estimator-objecten worden gemaakt, maar niet uitgevoerd.
Een methode toevoegen om het model te genereren
Deze methode vormt de kern van de zelfstudie. Er wordt een pijplijn voor het model gemaakt en de pijplijn wordt getraind om het ML.NET model te produceren. Het model wordt ook geëvalueerd op basis van enkele eerder ongeziene testgegevens.
Maak de
GenerateModel()
methode, net na deInceptionSettings
struct en net vóór deDisplayResults()
methode, met behulp van de volgende code:ITransformer GenerateModel(MLContext mlContext) { }
Voeg de schattingen toe om de pixels uit de afbeeldingsgegevens te laden, het formaat ervan te wijzigen en te extraheren:
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.
Voeg de estimator toe om het TensorFlow-model te laden en maak een score:
.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. Het toepassen van invoer op een deep learning-model en het genereren van een uitvoer met behulp van het model, wordt scoren genoemd. Wanneer u het model in zijn geheel gebruikt, maakt scoren een deductie of voorspelling.
In dit geval gebruikt u het hele TensorFlow-model, met uitzondering van de laatste laag, de laag die de deductie maakt. De uitvoer van de voorlaatste laag heeft het
softmax_2_preactivation
label . De uitvoer van deze laag is in feite 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.
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"))
Voor de ML.NET trainer die vervolgens wordt toegevoegd, moeten de labels een indeling hebben in
key
plaats van willekeurige tekenreeksen. Een sleutel is een getal met een een-op-een-toewijzing aan een tekenreekswaarde.Voeg het ML.NET trainingsalgoritmen toe:
.Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName: "LabelKey", featureColumnName: "softmax2_pre_activation"))
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
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 gegevens in tabelvorm (numeriek en tekst) te beschrijven. Gegevens kunnen vanuit een tekstbestand of in realtime (bijvoorbeeld SQL-database of logboekbestanden) naar eenIDataView
object worden geladen.Train het model met de gegevens die hierboven zijn geladen:
ITransformer model = pipeline.Fit(trainingData);
Met de
Fit()
methode wordt uw model getraind door de trainingsgegevensset toe te passen op de pijplijn.
De nauwkeurigheid van het model evalueren
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 door het model kunnen worden getransformeerd.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, gebruikt u de methode Evaluate():
- Evalueert het model (vergelijkt de voorspelde waarden met de testgegevensset
labels
). - Retourneert de metrische gegevens van de modelprestaties.
- Evalueert het model (vergelijkt de voorspelde waarden met de testgegevensset
De metrische gegevens van 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 is.Per class Log-loss
. U wilt dat logboekverlies per klasse zo dicht mogelijk bij nul ligt.
Voeg de volgende code toe om het getrainde model als volgende regel te retourneren:
return model;
Nu kunt u de toepassing uitvoeren.
Voeg de aanroep toe aan
GenerateModel
na het maken van de MLContext klasse:ITransformer model = GenerateModel(mlContext);
Voeg de aanroep toe aan de
ClassifySingleImage()
methode na de aanroep van deGenerateModel()
methode:ClassifySingleImage(mlContext, model);
Voer uw console-app uit (Ctrl + F5). De resultaten moeten vergelijkbaar zijn met de volgende uitvoer. (Mogelijk ziet u waarschuwingen of verwerkingsberichten, maar deze berichten zijn voor de duidelijkheid verwijderd uit de volgende resultaten.)
=============== 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 gemaakt 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 zelfstudie heeft u het volgende geleerd:
- Inzicht in het probleem
- 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 bekijken.