Dela via


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

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:

pizza bildnallebjörn bildbrödrost bild

Anteckning

Föregående bilder tillhör Wikimedia Commons och tillskrivs på följande sätt:

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 modelmö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.

TensorFlow transformera ML.NET Arch-diagram

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

  1. Skapa ett C# -konsolprogram med namnet "TransferLearningTF". Klicka på knappen Nästa.

  2. Välj .NET 6 som ramverk att använda. Klicka på knappen Skapa.

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

  1. Ladda ned zip-filen project assets directory och packa upp.

  2. Kopiera katalogen till projektkatalogen assetsTransferLearningTF . 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.

  3. Ladda ned startmodellen och packa upp.

  4. Kopiera innehållet i katalogen som just har packats upp i projektkatalogen inception5hassets/inceptionTransferLearningTF. Den här katalogen innehåller modellen och ytterligare supportfiler som behövs för den här självstudien, enligt följande bild:

    Kataloginnehåll för start

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

  1. Lägg till följande ytterligare using instruktioner överst i Filen Program.cs :

    using Microsoft.ML;
    using Microsoft.ML.Data;
    
  2. 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");
    
  3. 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.
  4. 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 en string (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

  1. Initiera variabeln mlContext med en ny instans av MLContext. Ersätt raden Console.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ässigt DBContext i Entity Framework.

Skapa en struct för startmodellparametrar

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

  1. DisplayResults() Skapa metoden, precis efter InceptionSettings structen, med hjälp av följande kod:

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

  1. ClassifySingleImage() Skapa metoden precis före DisplayResults() metoden med hjälp av följande kod:

    void ClassifySingleImage(MLContext mlContext, ITransformer model)
    {
    
    }
    
  2. Skapa ett ImageData -objekt som innehåller den fullständigt kvalificerade sökvägen och avbildningsfilens namn för den enskilda ImagePath. Lägg till följande kod som nästa rader i ClassifySingleImage() metoden :

    var imageData = new ImageData()
    {
        ImagePath = _predictSingleImage
    };
    
  3. 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 du PredictionEnginePool tjänsten, som skapar en ObjectPool av PredictionEngine objekt som ska användas i hela programmet. Se den här guiden om hur du använder PredictionEnginePool i ett ASP.NET Core webb-API.

    Anteckning

    PredictionEnginePool tjänsttillägget är för närvarande i förhandsversion.

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

  1. 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 efter InceptionSettings structen och precis före DisplayResults() metoden med hjälp av följande kod:

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

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

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

  5. Lägg till ML.NET träningsalgoritm:

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

  1. 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 ett IDataView objekt.

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

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

  2. 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.
  3. 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.
  4. Lägg till följande kod för att returnera den tränade modellen som nästa rad:

    return model;
    

Kör programmet!

  1. Lägg till anropet till GenerateModel när klassen har skapats MLContext :

    ITransformer model = GenerateModel(mlContext);
    
  2. Lägg till anropet ClassifySingleImage() till metoden efter anropet GenerateModel() till metoden :

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