Samouczek: trenowanie modelu klasyfikacji ML.NET w celu kategoryzowania obrazów

Dowiedz się, jak wytrenować model klasyfikacji w celu kategoryzowania obrazów przy użyciu wstępnie wytrenowanego modelu TensorFlow na potrzeby przetwarzania obrazów.

Model TensorFlow został przeszkolony w celu klasyfikowania obrazów w tysiąc kategorie. Ponieważ model TensorFlow wie, jak rozpoznawać wzorce na obrazach, model ML.NET może wykorzystać część tego modelu w potoku, aby przekonwertować nieprzetworzone obrazy na funkcje lub dane wejściowe w celu wytrenowania modelu klasyfikacji.

Ten samouczek zawiera informacje na temat wykonywania następujących czynności:

  • Omówienie problemu
  • Dołączenie wstępnie wytrenowanego modelu TensorFlow do potoku ML.NET
  • Trenowanie i ocenianie modelu ML.NET
  • Klasyfikowanie obrazu testowego

Kod źródłowy tego samouczka można znaleźć w repozytorium dotnet/samples . Domyślnie konfiguracja projektu .NET dla tego samouczka jest przeznaczona dla platformy .NET Core 2.2.

Wymagania wstępne

Wybieranie odpowiedniego zadania uczenia maszynowego

Uczenie głębokie

Uczenie głębokie to podzbiór uczenia maszynowego, który rewolucjonizuje obszary, takie jak przetwarzanie obrazów i rozpoznawanie mowy.

Modele uczenia głębokiego są trenowane przy użyciu dużych zestawów oznaczonych danych i sieci neuronowych zawierających wiele warstw uczenia. Uczenie głębokie:

  • Działa lepiej w niektórych zadaniach, takich jak przetwarzanie obrazów.
  • Wymaga ogromnych ilości danych treningowych.

Klasyfikacja obrazów to konkretne zadanie klasyfikacji, które umożliwia automatyczne klasyfikowanie obrazów w kategorie, takie jak:

  • Wykrywanie ludzkiej twarzy na obrazie lub nie.
  • Wykrywanie kotów a psów.

Lub tak jak na poniższych obrazach, określając, czy obraz jest żywnością, toysem lub urządzeniem:

obraz pizzyteddy niedźwiedź obraztoster

Uwaga

Powyższe obrazy należą do Wikimedia Commons i są przypisywane w następujący sposób:

Trenowanie modelu klasyfikacji obrazów od podstaw wymaga ustawienia milionów parametrów, mnóstwa oznaczonych danych treningowych i ogromnej ilości zasobów obliczeniowych (setki godzin procesora GPU). Chociaż nie jest tak skuteczne, jak trenowanie modelu niestandardowego od podstaw, użycie wstępnie wytrenowanego modelu pozwala na skróty tego procesu przez pracę z tysiącami obrazów a milionami oznaczonych obrazami i dość szybko skompiluj dostosowany model (w ciągu godziny na maszynie bez procesora GPU). Ten samouczek skaluje proces w dół jeszcze bardziej, używając tylko kilkunastu obrazów treningowych.

Program Inception model jest wyszkolony do klasyfikowania obrazów w tysiąc kategoriach, ale w tym samouczku należy sklasyfikować obrazy w mniejszym zestawie kategorii i tylko w tych kategoriach. Możesz użyć Inception modelmożliwości rozpoznawania i klasyfikowania obrazów w nowych ograniczonych kategoriach klasyfikatora obrazów niestandardowych.

  • Żywności
  • Zabawka
  • Urządzenie

W tym samouczku użyto modelu uczenia głębokiego TensorFlow , popularnego modelu rozpoznawania obrazów wyszkolonego w zestawie ImageNet danych. Model TensorFlow klasyfikuje całe obrazy do tysięcy klas, takich jak "Umbrella", "Jersey" i "Pralka".

Inception model Ponieważ obiekt został już wstępnie wytrenowany na tysiącach różnych obrazów, wewnętrznie zawiera funkcje obrazu potrzebne do identyfikacji obrazów. Możemy użyć tych wewnętrznych funkcji obrazu w modelu, aby wytrenować nowy model z znacznie mniejszą liczbą klas.

Jak pokazano na poniższym diagramie, dodasz odwołanie do pakietów NuGet ML.NET w aplikacjach platformy .NET Core lub .NET Framework. W ramach okładek ML.NET zawiera i odwołuje się do biblioteki natywnej TensorFlow , która umożliwia pisanie kodu, który ładuje istniejący wytrenowany TensorFlow plik modelu.

Przekształcenie tensorFlow ML.NET diagram arch

Klasyfikacja wieloklasowa

Po użyciu modelu tworzenia TensorFlow w celu wyodrębnienia funkcji odpowiednich jako danych wejściowych dla klasycznego algorytmu uczenia maszynowego dodamy ML.NET klasyfikator wieloklasowy.

Konkretny trener używany w tym przypadku jest wielomianowym algorytmem regresji logistycznej.

Algorytm zaimplementowany przez tego trenera dobrze sprawdza się na problemach z dużą liczbą funkcji, co jest w przypadku modelu uczenia głębokiego działającego na danych obrazu.

Aby uzyskać więcej informacji, zobacz Uczenie głębokie a uczenie maszynowe .

Dane

Istnieją dwa źródła danych: .tsv plik i pliki obrazów. Plik tags.tsv zawiera dwie kolumny: pierwszy jest zdefiniowany jako ImagePath , a drugi jest Label odpowiadający obrazowi. Poniższy przykładowy plik nie ma wiersza nagłówka i wygląda następująco:

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

Obrazy szkoleniowe i testowe znajdują się w folderach zasobów, które zostaną pobrane w pliku zip. Te obrazy należą do Wikimedia Commons.

Wikimedia Commons, bezpłatne repozytorium mediów. Pobrano 10:48, 17 października 2018 r. z: https://commons.wikimedia.org/wiki/Pizzahttps://commons.wikimedia.org/wiki/Toasterhttps://commons.wikimedia.org/wiki/Teddy_bear

Konfigurowanie

Tworzenie projektu

  1. Utwórz aplikację konsolową języka C# o nazwie "TransferLearningTF". Kliknij przycisk Dalej.

  2. Wybierz platformę .NET 6 jako platformę do użycia. Kliknij przycisk Utwórz.

  3. Zainstaluj pakiet NuGet Microsoft.ML:

    Uwaga

    W tym przykładzie użyto najnowszej stabilnej wersji pakietów NuGet wymienionych, chyba że określono inaczej.

    • W Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt i wybierz polecenie Zarządzaj pakietami NuGet.
    • Wybierz pozycję "nuget.org" jako źródło pakietu, wybierz kartę Przeglądaj, wyszukaj Microsoft.ML.
    • Wybierz przycisk Zainstaluj .
    • Wybierz przycisk OK w oknie dialogowym Podgląd zmian .
    • Wybierz przycisk Akceptuję w oknie dialogowym Akceptacja licencji , jeśli zgadzasz się z postanowieniami licencyjnymi dotyczącymi wymienionych pakietów.
    • Powtórz te kroki dla programów Microsoft.ML.ImageAnalytics, SciSharp.TensorFlow.Redist i Microsoft.ML.TensorFlow.

Pobieranie zasobów

  1. Pobierz plik zip katalogu zasobów projektu i rozpakuj.

  2. assets Skopiuj katalog do katalogu projektu TransferLearningTF. Ten katalog i jego podkatalogi zawierają pliki danych i obsługi (z wyjątkiem modelu Inception, który zostanie pobrany i dodany w następnym kroku) wymagany do tego samouczka.

  3. Pobierz model Inception i rozpakuj.

  4. Skopiuj zawartość inception5h katalogu po prostu rozpakowana do katalogu projektu assets/inceptionTransferLearningTF. Ten katalog zawiera model i dodatkowe pliki pomocy technicznej potrzebne do tego samouczka, jak pokazano na poniższej ilustracji:

    Zawartość katalogu Inception

  5. W Eksplorator rozwiązań kliknij prawym przyciskiem myszy każdy z plików w katalogu zasobów i podkatalogach, a następnie wybierz polecenie Właściwości. W obszarze Zaawansowane zmień wartość opcji Kopiuj do katalogu wyjściowego , aby skopiować, jeśli jest nowsza.

Tworzenie klas i definiowanie ścieżek

  1. Dodaj następujące dodatkowe using instrukcje na początku pliku Program.cs :

    using Microsoft.ML;
    using Microsoft.ML.Data;
    
  2. Dodaj następujący kod do wiersza bezpośrednio poniżej instrukcji using, aby określić ścieżki elementów zawartości:

    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. Utwórz klasy dla danych wejściowych i przewidywań.

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

    ImageData to klasa danych obrazu wejściowego i ma następujące String pola:

    • ImagePath zawiera nazwę pliku obrazu.
    • Label zawiera wartość etykiety obrazu.
  4. Dodaj nową klasę do projektu dla ImagePredictionelementu :

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

    ImagePrediction jest klasą przewidywania obrazu i ma następujące pola:

    • Score zawiera wartość procentową ufności dla danej klasyfikacji obrazów.
    • PredictedLabelValue zawiera wartość etykiety przewidywanej klasyfikacji obrazów.

    ImagePrediction jest klasą używaną do przewidywania po wytrenowanym modelu. Zawiera on element string (ImagePath) dla ścieżki obrazu. Element Label służy do ponownego użycia i trenowania modelu. Element PredictedLabelValue jest używany podczas przewidywania i oceny. Do oceny są używane dane wejściowe z danymi treningowymi, wartościami przewidywanymi i modelem.

Inicjowanie zmiennych

  1. Zainicjuj zmienną mlContext przy użyciu nowego wystąpienia klasy MLContext. Zastąp Console.WriteLine("Hello World!") wiersz następującym kodem:

    MLContext mlContext = new MLContext();
    

    Klasa MLContext jest punktem wyjścia dla wszystkich operacji ML.NET, a inicjowanie mlContext tworzy nowe środowisko ML.NET, które może być współużytkowane przez obiekty przepływu pracy tworzenia modelu. Jest to podobne, koncepcyjnie, do DBContext w programie Entity Framework.

Tworzenie struktury dla parametrów modelu Inception

  1. Model Inception ma kilka parametrów, które należy przekazać. Utwórz strukturę, aby zamapować wartości parametrów na przyjazne nazwy przy użyciu następującego kodu, tuż po zainicjowaniu zmiennej 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;
    }
    

Tworzenie metody narzędzia wyświetlania

Ponieważ będziesz wyświetlać dane obrazu i powiązane przewidywania więcej niż raz, utwórz metodę narzędzia wyświetlania do obsługi wyświetlania obrazów i wyników przewidywania.

  1. Utwórz metodę DisplayResults() tuż za strukturą InceptionSettings , używając następującego kodu:

    void DisplayResults(IEnumerable<ImagePrediction> imagePredictionData)
    {
    
    }
    
  2. Wypełnij treść DisplayResults metody:

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

Tworzenie metody w celu przewidywania

  1. Utwórz metodę ClassifySingleImage() tuż przed DisplayResults() metodą przy użyciu następującego kodu:

    void ClassifySingleImage(MLContext mlContext, ITransformer model)
    {
    
    }
    
  2. ImageData Utwórz obiekt zawierający w pełni kwalifikowaną ścieżkę i nazwę pliku obrazu dla pojedynczego ImagePathobiektu . Dodaj następujący kod jako następne wiersze w metodzie ClassifySingleImage() :

    var imageData = new ImageData()
    {
        ImagePath = _predictSingleImage
    };
    
  3. Utwórz pojedyncze przewidywanie, dodając następujący kod jako następny wiersz w metodzie ClassifySingleImage :

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

    Aby uzyskać przewidywanie, użyj metody Predict(). PredictionEngine to wygodny interfejs API, który umożliwia przewidywanie pojedynczego wystąpienia danych. PredictionEngine nie jest bezpieczny wątkowo. Dopuszczalne jest użycie w środowiskach jednowątkowych lub prototypowych. Aby zwiększyć wydajność i bezpieczeństwo wątków w środowiskach produkcyjnych, użyj PredictionEnginePool usługi , która tworzy ObjectPoolPredictionEngine obiekty do użycia w całej aplikacji. Zapoznaj się z tym przewodnikiem dotyczącym sposobu używania PredictionEnginePool w internetowym interfejsie API ASP.NET Core.

    Uwaga

    PredictionEnginePool Rozszerzenie usługi jest obecnie dostępne w wersji zapoznawczej.

  4. Wyświetl wynik przewidywania jako następny wiersz kodu w metodzie ClassifySingleImage() :

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

Konstruowanie potoku modelu ML.NET

Potok modelu ML.NET to łańcuch narzędzi do szacowania. Podczas budowy potoku nie ma żadnego wykonania. Obiekty narzędzia do szacowania są tworzone, ale nie są wykonywane.

  1. Dodawanie metody generowania modelu

    Ta metoda jest podstawą samouczka. Tworzy potok dla modelu i trenuje potok w celu utworzenia modelu ML.NET. Ocenia również model pod kątem niektórych wcześniej niezamierzonych danych testowych.

    Utwórz metodę GenerateModel() tuż za strukturą InceptionSettings i tuż przed DisplayResults() metodą, używając następującego kodu:

    ITransformer GenerateModel(MLContext mlContext)
    {
    
    }
    
  2. Dodaj narzędzia do szacowania, aby załadować, zmienić rozmiar i wyodrębnić piksele z danych obrazu:

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

    Dane obrazu należy przetworzyć w formacie oczekiwanym przez model TensorFlow. W takim przypadku obrazy są ładowane do pamięci, zmieniane na spójny rozmiar, a piksele są wyodrębniane do wektora liczbowego.

  3. Dodaj narzędzie do szacowania, aby załadować model TensorFlow i ocenić go:

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

    Ten etap w potoku ładuje model TensorFlow do pamięci, a następnie przetwarza wektor wartości pikseli za pośrednictwem sieci modelu TensorFlow. Stosowanie danych wejściowych do modelu uczenia głębokiego i generowanie danych wyjściowych przy użyciu modelu jest określane jako Ocenianie. W przypadku korzystania z modelu w całości ocenianie tworzy wnioskowanie lub przewidywanie.

    W tym przypadku używasz całego modelu TensorFlow z wyjątkiem ostatniej warstwy, która jest warstwą, która sprawia, że wnioskowanie. Dane wyjściowe przedostatniej warstwy mają etykietę softmax_2_preactivation. Dane wyjściowe tej warstwy są skutecznie wektorem cech, które charakteryzują oryginalne obrazy wejściowe.

    Ten wektor funkcji wygenerowany przez model TensorFlow będzie używany jako dane wejściowe do algorytmu trenowania ML.NET.

  4. Dodaj narzędzie do szacowania, aby zamapować etykiety ciągów w danych treningowych na wartości klucza całkowitego:

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

    Dołączany następnie ML.NET trener wymaga, aby jego etykiety zostały sformatowane key , a nie w dowolnych ciągach. Klucz to liczba, która ma jedno mapowanie na wartość ciągu.

  5. Dodaj algorytm trenowania ML.NET:

    .Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName: "LabelKey", featureColumnName: "softmax2_pre_activation"))
    
  6. Dodaj narzędzie do szacowania, aby zamapować przewidywaną wartość klucza z powrotem na ciąg:

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

Trenowanie modelu

  1. Załaduj dane szkoleniowe przy użyciu otoki LoadFromTextFile . Dodaj następujący kod jako następny wiersz w metodzie GenerateModel() :

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

    Dane w ML.NET są reprezentowane jako interfejs IDataView. IDataView to elastyczny, wydajny sposób opisywania danych tabelarycznych (liczbowych i tekstowych). Dane można załadować z pliku tekstowego lub w czasie rzeczywistym (na przykład bazy danych SQL lub plików dziennika) do IDataView obiektu.

  2. Wytrenuj model przy użyciu danych załadowanych powyżej:

    ITransformer model = pipeline.Fit(trainingData);
    

    Metoda Fit() trenuje model, stosując zestaw danych trenowania do potoku.

Ocena dokładności modelu

  1. Załaduj i przekształć dane testowe, dodając następujący kod do następnego wiersza GenerateModel metody:

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

    Istnieje kilka przykładowych obrazów, których można użyć do oceny modelu. Podobnie jak w przypadku danych treningowych, należy je załadować do IDataViewobiektu , aby można je było przekształcić za pomocą modelu.

  2. Dodaj następujący kod do GenerateModel() metody , aby ocenić model:

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

    Po utworzeniu zestawu przewidywania metoda Evaluate():

    • Ocenia model (porównuje przewidywane wartości z zestawem danych labelstestowych).
    • Zwraca metryki wydajności modelu.
  3. Wyświetlanie metryk dokładności modelu

    Użyj następującego kodu, aby wyświetlić metryki, udostępnić wyniki, a następnie wykonać na nich działania:

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

    Następujące metryki są oceniane pod kątem klasyfikacji obrazów:

    • Log-loss — zobacz Log Loss (Utrata dziennika). Chcesz, aby strata dziennika nie zbliżała się do zera, jak to możliwe.
    • Per class Log-loss. Chcesz, aby na klasę Log-loss był jak najbardziej zbliżony do zera.
  4. Dodaj następujący kod, aby zwrócić wytrenowany model jako następny wiersz:

    return model;
    

Uruchom aplikację!

  1. Dodaj wywołanie metody do GenerateModel po utworzeniu MLContext klasy:

    ITransformer model = GenerateModel(mlContext);
    
  2. Dodaj wywołanie do ClassifySingleImage() metody po wywołaniu GenerateModel() metody :

    ClassifySingleImage(mlContext, model);
    
  3. Uruchom aplikację konsolową (Ctrl + F5). Wyniki powinny być podobne do następujących danych wyjściowych. (Mogą pojawić się ostrzeżenia lub przetwarzanie komunikatów, ale te komunikaty zostały usunięte z poniższych wyników, aby uzyskać jasność).

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

Gratulacje! Udało Ci się utworzyć model klasyfikacji w ML.NET w celu kategoryzowania obrazów przy użyciu wstępnie wytrenowanego biblioteki TensorFlow na potrzeby przetwarzania obrazów.

Kod źródłowy tego samouczka można znaleźć w repozytorium dotnet/samples .

W niniejszym samouczku zawarto informacje na temat wykonywania następujących czynności:

  • Omówienie problemu
  • Dołączanie wstępnie wytrenowanego modelu TensorFlow do potoku ML.NET
  • Trenowanie i ocenianie modelu ML.NET
  • Klasyfikowanie obrazu testowego

Zapoznaj się z repozytorium GitHub przykładów usługi Machine Learning, aby zapoznać się z rozszerzonym przykładem klasyfikacji obrazów.