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:
Uwaga
Powyższe obrazy należą do Wikimedia Commons i są przypisywane w następujący sposób:
- "220px-Pepperoni_pizza.jpg" Domena publiczna, https://commons.wikimedia.org/w/index.php?curid=79505,
- "119px-Nalle_-_a_small_brown_teddy_bear.jpg" By Jonik - Self-photographed, CC BY-SA 2.0, https://commons.wikimedia.org/w/index.php?curid=48166.
- "193px-Broodrooster.jpg" Przez M.Minderhoud - Własna praca, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=27403
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 model
moż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.
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
Utwórz aplikację konsolową języka C# o nazwie "TransferLearningTF". Kliknij przycisk Dalej.
Wybierz platformę .NET 6 jako platformę do użycia. Kliknij przycisk Utwórz.
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
Pobierz plik zip katalogu zasobów projektu i rozpakuj.
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.Pobierz model Inception i rozpakuj.
Skopiuj zawartość
inception5h
katalogu po prostu rozpakowana do katalogu projektuassets/inception
TransferLearningTF. Ten katalog zawiera model i dodatkowe pliki pomocy technicznej potrzebne do tego samouczka, jak pokazano na poniższej ilustracji: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
Dodaj następujące dodatkowe
using
instrukcje na początku pliku Program.cs :using Microsoft.ML; using Microsoft.ML.Data;
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");
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.
Dodaj nową klasę do projektu dla
ImagePrediction
elementu :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 elementstring
(ImagePath
) dla ścieżki obrazu. ElementLabel
służy do ponownego użycia i trenowania modelu. ElementPredictedLabelValue
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
Zainicjuj zmienną
mlContext
przy użyciu nowego wystąpienia klasyMLContext
. ZastąpConsole.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, doDBContext
w programie Entity Framework.
Tworzenie struktury dla parametrów modelu Inception
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.
Utwórz metodę
DisplayResults()
tuż za strukturąInceptionSettings
, używając następującego kodu:void DisplayResults(IEnumerable<ImagePrediction> imagePredictionData) { }
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
Utwórz metodę
ClassifySingleImage()
tuż przedDisplayResults()
metodą przy użyciu następującego kodu:void ClassifySingleImage(MLContext mlContext, ITransformer model) { }
ImageData
Utwórz obiekt zawierający w pełni kwalifikowaną ścieżkę i nazwę pliku obrazu dla pojedynczegoImagePath
obiektu . Dodaj następujący kod jako następne wiersze w metodzieClassifySingleImage()
:var imageData = new ImageData() { ImagePath = _predictSingleImage };
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żyjPredictionEnginePool
usługi , która tworzyObjectPool
PredictionEngine
obiekty do użycia w całej aplikacji. Zapoznaj się z tym przewodnikiem dotyczącym sposobu używaniaPredictionEnginePool
w internetowym interfejsie API ASP.NET Core.Uwaga
PredictionEnginePool
Rozszerzenie usługi jest obecnie dostępne w wersji zapoznawczej.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.
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ż przedDisplayResults()
metodą, używając następującego kodu:ITransformer GenerateModel(MLContext mlContext) { }
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.
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.
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.Dodaj algorytm trenowania ML.NET:
.Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName: "LabelKey", featureColumnName: "softmax2_pre_activation"))
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
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) doIDataView
obiektu.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
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
IDataView
obiektu , aby można je było przekształcić za pomocą modelu.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
labels
testowych). - Zwraca metryki wydajności modelu.
- Ocenia model (porównuje przewidywane wartości z zestawem danych
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.
Dodaj następujący kod, aby zwrócić wytrenowany model jako następny wiersz:
return model;
Uruchom aplikację!
Dodaj wywołanie metody do
GenerateModel
po utworzeniu MLContext klasy:ITransformer model = GenerateModel(mlContext);
Dodaj wywołanie do
ClassifySingleImage()
metody po wywołaniuGenerateModel()
metody :ClassifySingleImage(mlContext, model);
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.