Självstudie: Träna en ML.NET klassificeringsmodell för att kategorisera bilder
Lär dig hur du tränar en klassificeringsmodell för att kategorisera bilder med hjälp av en förtränad TensorFlow-modell för bildbearbetning.
TensorFlow-modellen tränades för att klassificera bilder i tusen kategorier. Eftersom TensorFlow-modellen vet hur mönster identifieras i bilder kan den ML.NET modellen använda en del av den i pipelinen för att konvertera råbilder till funktioner eller indata för att träna en klassificeringsmodell.
I den här guiden får du lära dig att:
- Förstå problemet
- Införliva den förtränade TensorFlow-modellen i ML.NET pipeline
- Träna och utvärdera ML.NET modellen
- Klassificera en testbild
Du hittar källkoden för den här självstudien på lagringsplatsen dotnet/samples . Som standard är .NET-projektkonfigurationen för den här självstudien inriktad på .NET Core 2.2.
Krav
- Visual Studio 2022
- Katalogen för självstudietillgångar .ZIP fil
- Maskininlärningsmodellen InceptionV1
Välj rätt maskininlärningsuppgift
Deep learning
Djupinlärning är en delmängd av Machine Learning, som revolutionerar områden som visuellt innehåll och taligenkänning.
Djupinlärningsmodeller tränas med hjälp av stora uppsättningar märkta data och neurala nätverk som innehåller flera inlärningslager. Djupinlärning:
- Presterar bättre på vissa uppgifter som visuellt innehåll.
- Kräver enorma mängder träningsdata.
Bildklassificering är en specifik klassificeringsuppgift som gör att vi automatiskt kan klassificera bilder i kategorier som:
- Identifiera ett mänskligt ansikte i en bild eller inte.
- Identifiera katter jämfört med hundar.
Eller som i följande bilder och avgöra om en bild är en mat, leksak eller installation:
Anteckning
Föregående bilder tillhör Wikimedia Commons och tillskrivs på följande sätt:
- "220px-Pepperoni_pizza.jpg" offentlig domän, , https://commons.wikimedia.org/w/index.php?curid=79505
- "119px-Nalle_-_a_small_brown_teddy_bear.jpg" Av Jonik - Självfotograferad, CC BY-SA 2.0, https://commons.wikimedia.org/w/index.php?curid=48166.
- "193px-Broodrooster.jpg" Av M.Minderhoud - Eget arbete, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=27403
Träning av en bildklassificeringsmodell från grunden kräver att du ställer in miljontals parametrar, massor av märkta träningsdata och en stor mängd beräkningsresurser (hundratals GPU-timmar). Även om det inte är lika effektivt som att träna en anpassad modell från grunden kan du använda en förtränad modell för att genväg till den här processen genom att arbeta med tusentals bilder jämfört med miljontals märkta bilder och skapa en anpassad modell ganska snabbt (inom en timme på en dator utan GPU). Den här självstudien skalar ned processen ytterligare med bara ett dussin träningsbilder.
Inception model
Är tränad att klassificera bilder i tusen kategorier, men för den här självstudien måste du klassificera bilder i en mindre kategoriuppsättning och endast dessa kategorier. Du kan använda Inception model
möjligheten att identifiera och klassificera bilder till de nya begränsade kategorierna i din anpassade bildklassificerare.
- Mat
- Leksak
- Apparat
I den här självstudien används djupinlärningsmodellen TensorFlow Inception , en populär bildigenkänningsmodell som tränats på datamängden ImageNet
. TensorFlow-modellen klassificerar hela bilder i tusen klasser, till exempel "Umbrella", "Jersey" och "Diskmaskin".
Inception model
Eftersom redan har förtränats på tusentals olika bilder innehåller den internt de bildfunktioner som behövs för bildidentifiering. Vi kan använda dessa interna bildfunktioner i modellen för att träna en ny modell med mycket färre klasser.
Som du ser i följande diagram lägger du till en referens till ML.NET NuGet-paket i dina .NET Core- eller .NET Framework-program. Under täcket innehåller ML.NET och refererar till det interna TensorFlow
biblioteket som gör att du kan skriva kod som läser in en befintlig tränad TensorFlow
modellfil.
Klassificering med flera klasser
När vi har använt TensorFlow-startmodellen för att extrahera funktioner som är lämpliga som indata för en klassisk maskininlärningsalgoritm lägger vi till en ML.NET klassificerare med flera klasser.
Den specifika tränare som används i det här fallet är algoritmen för multinomlogikregression.
Algoritmen som implementeras av den här tränaren presterar bra på problem med ett stort antal funktioner, vilket är fallet för en djupinlärningsmodell som arbetar med bilddata.
Mer information finns i Djupinlärning jämfört med maskininlärning .
Data
Det finns två datakällor: .tsv
filen och bildfilerna. Filen tags.tsv
innehåller två kolumner: den första definieras som ImagePath
och den andra motsvarar Label
bilden. Följande exempelfil har ingen rubrikrad och ser ut så här:
broccoli.jpg food
pizza.jpg food
pizza2.jpg food
teddy2.jpg toy
teddy3.jpg toy
teddy4.jpg toy
toaster.jpg appliance
toaster2.png appliance
Tränings- och testbilderna finns i de resursmappar som du laddar ned i en zip-fil. Dessa bilder tillhör Wikimedia Commons.
Wikimedia Commons, den kostnadsfria medielagringsplatsen. Hämtad 10:48, 17 oktober 2018 från: https://commons.wikimedia.org/wiki/Pizzahttps://commons.wikimedia.org/wiki/Toasterhttps://commons.wikimedia.org/wiki/Teddy_bear
Installation
Skapa ett projekt
Skapa ett C# -konsolprogram med namnet "TransferLearningTF". Klicka på knappen Nästa.
Välj .NET 6 som ramverk att använda. Klicka på knappen Skapa.
Installera Microsoft.ML NuGet-paketet:
Anteckning
Det här exemplet använder den senaste stabila versionen av De NuGet-paket som nämns om inget annat anges.
- I Solution Explorer högerklickar du på projektet och väljer Hantera NuGet-paket.
- Välj "nuget.org" som paketkälla, välj fliken Bläddra och sök efter Microsoft.ML.
- Välj knappen Installera .
- Välj knappen OK i dialogrutan Förhandsgranska ändringar .
- Välj knappen Jag accepterar i dialogrutan Licensgodkännande om du godkänner licensvillkoren för de paket som anges.
- Upprepa de här stegen för Microsoft.ML.ImageAnalytics, SciSharp.TensorFlow.Redist och Microsoft.ML.TensorFlow.
Ladda ned tillgångar
Ladda ned zip-filen project assets directory och packa upp.
Kopiera katalogen till projektkatalogen
assets
TransferLearningTF . Den här katalogen och dess underkataloger innehåller data och supportfiler (förutom startmodellen, som du ska ladda ned och lägga till i nästa steg) som behövs för den här självstudien.Ladda ned startmodellen och packa upp.
Kopiera innehållet i katalogen som just har packats upp i projektkatalogen
inception5h
assets/inception
TransferLearningTF. Den här katalogen innehåller modellen och ytterligare supportfiler som behövs för den här självstudien, enligt följande bild:I Solution Explorer högerklickar du på var och en av filerna i tillgångskatalogen och underkatalogerna och väljer Egenskaper. Under Avancerat ändrar du värdet för Kopiera till utdatakatalog till Kopiera om nyare.
Skapa klasser och definiera sökvägar
Lägg till följande ytterligare
using
instruktioner överst i Filen Program.cs :using Microsoft.ML; using Microsoft.ML.Data;
Lägg till följande kod på raden precis nedanför användningsuttrycken för att ange tillgångssökvägarna:
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");
Skapa klasser för dina indata och förutsägelser.
public class ImageData { [LoadColumn(0)] public string? ImagePath; [LoadColumn(1)] public string? Label; }
ImageData
är dataklassen för indatabilder och har följande String fält:ImagePath
innehåller bildfilens namn.Label
innehåller ett värde för bildetiketten.
Lägg till en ny klass i projektet för
ImagePrediction
:public class ImagePrediction : ImageData { public float[]? Score; public string? PredictedLabelValue; }
ImagePrediction
är bildförutsägelseklassen och har följande fält:Score
innehåller konfidensprocenten för en viss bildklassificering.PredictedLabelValue
innehåller ett värde för den förutsagda bildklassificeringsetiketten.
ImagePrediction
är den klass som används för förutsägelse när modellen har tränats. Den har enstring
(ImagePath
) för bildsökvägen.Label
används för att återanvända och träna modellen.PredictedLabelValue
används under förutsägelse och utvärdering. För utvärdering används indata med träningsdata, förutsagda värden och modellen.
Initiera variabler
Initiera variabeln
mlContext
med en ny instans avMLContext
. Ersätt radenConsole.WriteLine("Hello World!")
med följande kod:MLContext mlContext = new MLContext();
Klassen MLContext är en startpunkt för alla ML.NET åtgärder, och initiering
mlContext
skapar en ny ML.NET miljö som kan delas mellan arbetsflödesobjekten för modellskapande. Det liknar begreppsmässigtDBContext
i Entity Framework.
Skapa en struct för startmodellparametrar
Startmodellen har flera parametrar som du behöver skicka in. Skapa en struct för att mappa parametervärdena till egna namn med följande kod, precis efter att variabeln har initierats
mlContext
: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; }
Skapa en visningsverktygsmetod
Eftersom du ska visa bilddata och relaterade förutsägelser mer än en gång skapar du en visningsverktygsmetod för att hantera visning av bild- och förutsägelseresultat.
DisplayResults()
Skapa metoden, precis efterInceptionSettings
structen, med hjälp av följande kod:void DisplayResults(IEnumerable<ImagePrediction> imagePredictionData) { }
Fyll i brödtexten i
DisplayResults
metoden:foreach (ImagePrediction prediction in imagePredictionData) { Console.WriteLine($"Image: {Path.GetFileName(prediction.ImagePath)} predicted as: {prediction.PredictedLabelValue} with score: {prediction.Score?.Max()} "); }
Skapa en metod för att göra en förutsägelse
ClassifySingleImage()
Skapa metoden precis föreDisplayResults()
metoden med hjälp av följande kod:void ClassifySingleImage(MLContext mlContext, ITransformer model) { }
Skapa ett
ImageData
-objekt som innehåller den fullständigt kvalificerade sökvägen och avbildningsfilens namn för den enskildaImagePath
. Lägg till följande kod som nästa rader iClassifySingleImage()
metoden :var imageData = new ImageData() { ImagePath = _predictSingleImage };
Gör en enda förutsägelse genom att lägga till följande kod som nästa rad i
ClassifySingleImage
metoden :// Make prediction function (input = ImageData, output = ImagePrediction) var predictor = mlContext.Model.CreatePredictionEngine<ImageData, ImagePrediction>(model); var prediction = predictor.Predict(imageData);
Använd metoden Predict() för att hämta förutsägelsen. PredictionEngine är ett bekvämlighets-API som gör att du kan utföra en förutsägelse på en enda instans av data.
PredictionEngine
är inte trådsäkert. Det är acceptabelt att använda i entrådade miljöer eller prototypmiljöer. För bättre prestanda och trådsäkerhet i produktionsmiljöer använder duPredictionEnginePool
tjänsten, som skapar enObjectPool
avPredictionEngine
objekt som ska användas i hela programmet. Se den här guiden om hur du använderPredictionEnginePool
i ett ASP.NET Core webb-API.Anteckning
PredictionEnginePool
tjänsttillägget är för närvarande i förhandsversion.Visa förutsägelseresultatet som nästa kodrad i
ClassifySingleImage()
metoden :Console.WriteLine($"Image: {Path.GetFileName(imageData.ImagePath)} predicted as: {prediction.PredictedLabelValue} with score: {prediction.Score?.Max()} ");
Konstruera ML.NET modellpipelinen
En ML.NET modellpipeline är en kedja av beräknare. Ingen körning sker under pipelinekonstruktionen. Beräkningsobjekten skapas men körs inte.
Lägga till en metod för att generera modellen
Den här metoden är hjärtat i självstudien. Den skapar en pipeline för modellen och tränar pipelinen att producera ML.NET modellen. Den utvärderar också modellen mot vissa tidigare osedda testdata.
GenerateModel()
Skapa metoden, precis efterInceptionSettings
structen och precis föreDisplayResults()
metoden med hjälp av följande kod:ITransformer GenerateModel(MLContext mlContext) { }
Lägg till beräknarna för att läsa in, ändra storlek på och extrahera bildpunkterna från bilddata:
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))
Bilddata måste bearbetas till det format som TensorFlow-modellen förväntar sig. I det här fallet läses bilderna in i minnet, storleksanpassas till en konsekvent storlek och bildpunkterna extraheras till en numerisk vektor.
Lägg till beräknaren för att läsa in TensorFlow-modellen och poängsätta den:
.Append(mlContext.Model.LoadTensorFlowModel(_inceptionTensorFlowModel). ScoreTensorFlowModel(outputColumnNames: new[] { "softmax2_pre_activation" }, inputColumnNames: new[] { "input" }, addBatchDimensionInput: true))
Det här steget i pipelinen läser in TensorFlow-modellen i minnet och bearbetar sedan vektorn för pixelvärden via TensorFlow-modellnätverket. Att tillämpa indata på en djupinlärningsmodell och generera utdata med hjälp av modellen kallas bedömning. När du använder modellen i sin helhet gör bedömning en slutsatsdragning eller förutsägelse.
I det här fallet använder du hela TensorFlow-modellen förutom det sista lagret, vilket är det lager som gör slutsatsdragningen. Utdata från det näst sista lagret är märkta
softmax_2_preactivation
. Utdata från det här lagret är i praktiken en vektor med funktioner som kännetecknar de ursprungliga indatabilderna.Den här funktionsvektorn som genereras av TensorFlow-modellen används som indata till en ML.NET träningsalgoritm.
Lägg till beräknaren för att mappa strängetiketterna i träningsdata till heltalsnyckelvärden:
.Append(mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "LabelKey", inputColumnName: "Label"))
Den ML.NET tränare som läggs till härnäst kräver att etiketterna är i format i
key
stället för godtyckliga strängar. En nyckel är ett tal som har en en till en-mappning till ett strängvärde.Lägg till ML.NET träningsalgoritm:
.Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName: "LabelKey", featureColumnName: "softmax2_pre_activation"))
Lägg till beräknaren för att mappa det förutsagda nyckelvärdet tillbaka till en sträng:
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabelValue", "PredictedLabel")) .AppendCacheCheckpoint(mlContext);
Träna modellen
Läs in träningsdata med loadFromTextFile-omslutningen . Lägg till följande kod som nästa rad i
GenerateModel()
metoden :IDataView trainingData = mlContext.Data.LoadFromTextFile<ImageData>(path: _trainTagsTsv, hasHeader: false);
Data i ML.NET representeras som ett IDataView-gränssnitt.
IDataView
är ett flexibelt och effektivt sätt att beskriva tabelldata (numeriska data och text). Data kan läsas in från en textfil eller i realtid (till exempel SQL-databas eller loggfiler) till ettIDataView
objekt.Träna modellen med de data som lästs in ovan:
ITransformer model = pipeline.Fit(trainingData);
Metoden
Fit()
tränar din modell genom att tillämpa träningsdatauppsättningen på pipelinen.
Utvärdera modellens noggrannhet
Läs in och transformera testdata genom att lägga till följande kod till nästa rad i
GenerateModel
metoden: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);
Det finns några exempelbilder som du kan använda för att utvärdera modellen. Precis som träningsdata måste dessa läsas in i en
IDataView
, så att de kan omvandlas av modellen.Lägg till följande kod i
GenerateModel()
metoden för att utvärdera modellen:MulticlassClassificationMetrics metrics = mlContext.MulticlassClassification.Evaluate(predictions, labelColumnName: "LabelKey", predictedLabelColumnName: "PredictedLabel");
När du har angett förutsägelsen använder du metoden Evaluate( ):
- Utvärderar modellen (jämför de förutsagda värdena med testdatamängden
labels
). - Returnerar modellens prestandamått.
- Utvärderar modellen (jämför de förutsagda värdena med testdatamängden
Visa mått för modellnoggrannhet
Använd följande kod för att visa måtten, dela resultaten och sedan agera på dem:
Console.WriteLine($"LogLoss is: {metrics.LogLoss}"); Console.WriteLine($"PerClassLogLoss is: {String.Join(" , ", metrics.PerClassLogLoss.Select(c => c.ToString()))}");
Följande mått utvärderas för bildklassificering:
Log-loss
– se Loggförlust. Du vill att loggförlusten ska vara så nära noll som möjligt.Per class Log-loss
. Du vill att loggförlusten per klass ska vara så nära noll som möjligt.
Lägg till följande kod för att returnera den tränade modellen som nästa rad:
return model;
Kör programmet!
Lägg till anropet till
GenerateModel
när klassen har skapats MLContext :ITransformer model = GenerateModel(mlContext);
Lägg till anropet
ClassifySingleImage()
till metoden efter anropetGenerateModel()
till metoden :ClassifySingleImage(mlContext, model);
Kör konsolappen (Ctrl + F5). Resultatet bör likna följande utdata. (Du kan se varningar eller bearbeta meddelanden, men dessa meddelanden har tagits bort från följande resultat för tydlighetens skull.)
=============== 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
Grattis! Nu har du skapat en klassificeringsmodell i ML.NET för att kategorisera bilder med hjälp av ett förtränat TensorFlow för bildbearbetning.
Du hittar källkoden för den här självstudien på lagringsplatsen dotnet/samples .
I den här självstudiekursen lärde du dig att:
- Förstå problemet
- Införliva den förtränade TensorFlow-modellen i ML.NET pipeline
- Träna och utvärdera ML.NET modellen
- Klassificera en testbild
Titta på GitHub-lagringsplatsen machine learning-exempel för att utforska ett utökat bildklassificeringsexempel.