Учебник. Обучение модели классификации ML.NET для категоризации изображений
Узнайте, как обучить модель классификации категоризировать изображения с помощью предварительно обученной модели TensorFlow для обработки изображений.
Модель TensorFlow была обучена для классификации изображений по тысячам категорий. Поскольку модель TensorFlow способна распознавать на изображениях знакомые элементы, модель ML.NET может частично использовать ее в собственном конвейере для преобразования необработанных изображений в признаки или входные данные для обучения модели классификации.
В этом руководстве вы узнаете, как:
- Определение проблемы
- внедрить предварительно обученную модель TensorFlow в конвейер ML.NET;
- обучить и оценить модель ML.NET;
- классифицировать тестовое изображение.
Исходный код для этого руководства можно найти в репозитории dotnet/samples. По умолчанию конфигурация проекта .NET в этом руководстве предназначена для .NET Core 2.2.
Предварительные требования
- Visual Studio 2022
- ZIP-файл каталога ресурсов руководства.
- Модель машинного обучения Inception версии 1
Выбор типа задачи машинного обучения
Глубокое обучение
Глубокое обучение — это разновидность машинного обучения, совершающая революцию в области компьютерного зрения, распознавания речи и других подобных сферах.
Модели глубокого обучения обучаются на крупных наборах помеченных данных с использованием нейронных сетей, которые содержат множество слоев обучения. Глубокое обучение:
- лучше решает некоторые задачи, например в области компьютерного зрения;
- требует огромных объемов данных для обучения.
Классификация изображений — это конкретная задача их автоматической классификации по категориям, например:
- для определения того, содержит ли изображение человеческое лицо;
- для различения изображений котов и собак.
Она также помогает определить тип объекта на изображении — еда, игрушка или прибор:
Примечание
Изображения выше принадлежат Викискладу и имеют следующие атрибуты:
- 220px-Pepperoni_pizza.jpg, открытый источник, https://commons.wikimedia.org/w/index.php?curid=79505;
- 119px-Nalle_-_a_small_brown_teddy_bear.jpg, автор — Jonik, автофотография, лицензия CC BY-SA 2.0, https://commons.wikimedia.org/w/index.php?curid=48166;
- 193px-Broodrooster.jpg, автор — M. Minderhoud, собственное фото, лицензия CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=27403.
Обучение модели классификации изображений с нуля требует задания миллионов параметров, а также использования огромных объемов помеченных обучающих данных и вычислительных ресурсов (сотни часов работы GPU). Использование предварительно обученной модели не настолько эффективно, как обучение специализированной модели с нуля, однако за счет использования лишь тысяч (а не миллионов) помеченных изображений этот подход позволяет получить требуемую модель существенно быстрее (в пределах часа) на компьютере без GPU. В этом учебнике этот процесс еще более уменьшен: используется только десяток изображений для обучения.
Модель Inception model
обучена классифицировать изображения по тысяче категорий, но в этом учебнике вам столько категорий не нужно. Вам также нужны четко определенные категории. Вы можете использовать способность Inception model
распознавать и классифицировать изображения в новых ограниченных категориях своего классификатора изображений.
- еда;
- игрушка;
- прибор.
В этом учебнике используется TensorFlow Inception, популярная модель глубокого обучения для распознавания изображений, обученная на наборе данных ImageNet
. Модель TensorFlow классифицирует все изображения по тысячам классов, таких как "зонт", "жакет" и "посудомоечная машина".
Так как Inception model
предварительно обучена на тысячах различных изображений, она содержит признаки изображений, необходимые для их идентификации. Мы можем использовать эти внутренние признаки изображений в модели для обучения новой модели с гораздо меньшим числом классов.
Как показано на схеме ниже, вам нужно добавить ссылки на пакеты NuGet ML.NET в приложения .NET Core или .NET Framework. На внутреннем уровне ML.NET включает и ссылается на встроенную библиотеку TensorFlow
, которая позволяет создавать код, загружающий существующую обученную модель TensorFlow
.
Многоклассовая классификация
После использования модели Inception TensorFlow для извлечения признаков, подходящих в качестве входных данных для классического алгоритма машинного обучения, мы добавим многоклассовый классификатор ML.NET.
В этом случае используется алгоритм мультиномиальной логистической регрессии.
Алгоритм, реализованный этим инструктором, хорошо работает в задачах с большим количеством признаков, что характерно для модели глубокого обучения, работающей с данными изображений.
Дополнительные сведения: Сравнение глубокого и машинного обучения.
Данные
Доступны два источника данных: файл .tsv
и файлы образов. Файл tags.tsv
содержит два столбца: первый определен как ImagePath
, а во втором указана метка Label
, соответствующая изображению. В примере файла ниже отсутствует строка заголовка. Сам файл выглядит следующим образом:
broccoli.jpg food
pizza.jpg food
pizza2.jpg food
teddy2.jpg toy
teddy3.jpg toy
teddy4.jpg toy
toaster.jpg appliance
toaster2.png appliance
Изображения для обучения и тестирования расположены в папках ресурсов, которые вы скачали в виде ZIP-файла. Эти изображения принадлежат Викискладу.
Викисклад, бесплатный репозиторий мультимедиа. Получено 17 октября 2018 г. в 10:48 со страниц: https://commons.wikimedia.org/wiki/Pizzahttps://commons.wikimedia.org/wiki/Toasterhttps://commons.wikimedia.org/wiki/Teddy_bear
Установка
Создание проекта
Создайте консольное приложение C# с именем TransferLearningTF. Нажмите кнопку Далее.
Выберите .NET 6 в качестве используемой платформы. Нажмите кнопку Создать .
Установите пакет NuGet для Microsoft.ML:
Примечание
В этом примере используется последняя стабильная версия пакетов NuGet, упомянутых выше, если не указано иное.
- В обозревателе решений щелкните проект правой кнопкой мыши и выберите Управление пакетами NuGet.
- Выберите nuget.org в качестве источника пакета, откройте вкладку "Обзор" и выполните поиск Microsoft.ML.
- Нажмите кнопку Установить.
- Нажмите кнопку ОК в диалоговом окне Предварительный просмотр изменений.
- Нажмите кнопку Принимаю в диалоговом окне Принятие условий лицензионного соглашения, если вы согласны с условиями лицензионного соглашения для указанных пакетов.
- Повторите эти шаги для пакетов Microsoft.ML.ImageAnalytics, SciSharp.TensorFlow.Redist и Microsoft.ML.TensorFlow.
Скачивание ресурсов
Скачайте ZIP-файл каталога с ресурсами проекта и распакуйте его.
Скопируйте каталог
assets
в каталог проекта TransferLearningTF. Этот каталог и его подкаталоги содержат данные и файлы поддержки (за исключением модели Inception, которую вы скачаете и добавите на следующем шаге), необходимые для работы с этим руководством.Скачайте модель Inception и распакуйте ее.
Скопируйте содержание каталога
inception5h
, который вы распаковали, в каталогassets/inception
проекта TransferLearningTF. Этот каталог содержит модель и дополнительные файлы поддержки, необходимые для работы с этим руководством, как показано на следующем рисунке:В обозревателе решений щелкните правой кнопкой мыши каждый файл в каталоге и подкаталогах ресурсов и выберите Свойства. В разделе Дополнительно для параметра Копировать в выходной каталог установите значение Копировать более позднюю версию.
Создание классов и определение путей
Добавьте следующие новые операторы
using
в начало файла Program.cs:using Microsoft.ML; using Microsoft.ML.Data;
Добавьте следующий код в строку прямо под операторами using, чтобы указать пути к ресурсам:
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");
Создайте классы для входных данных и прогнозов.
public class ImageData { [LoadColumn(0)] public string? ImagePath; [LoadColumn(1)] public string? Label; }
ImageData
является классом входных данных изображения и имеет следующие поля String:ImagePath
содержит имя файла изображения.Label
содержит значение для метки изображения.
Добавьте новый класс в свой проект для
ImagePrediction
:public class ImagePrediction : ImageData { public float[]? Score; public string? PredictedLabelValue; }
ImagePrediction
является классом прогноза изображения и имеет следующие поля:Score
содержит процентное значение достоверности для конкретной классификации изображения.PredictedLabelValue
содержит значение для прогнозируемой метки классификации изображения.
Класс
ImagePrediction
используется для прогнозирования после обучения модели. Он включаетstring
(ImagePath
) с путем к изображению.Label
используется для применения и обучения модели.PredictedLabelValue
используется для прогнозирования и оценки. Для оценки применяются входные обучающие данные, прогнозируемые значения и модель.
Инициализация переменных
Инициализируйте переменную
mlContext
с использованием нового экземпляраMLContext
. Замените строкуConsole.WriteLine("Hello World!")
следующим кодом:MLContext mlContext = new MLContext();
Класс MLContext является отправной точкой для любых операций ML.NET. В результате инициализации класса
mlContext
создается среда ML.NET, которая может использоваться всеми объектами в рамках процесса создания модели. По существу он аналогичен классуDBContext
в Entity Framework.
Создание структуры для параметров модели Inception
Модель Inception имеет несколько параметров, которые необходимо передать. Создайте структуру, чтобы сопоставить значения параметров с понятными именами, с помощью следующего кода сразу после инициализации переменной
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; }
Создание служебного метода для отображения данных
Поскольку вы будете отображать данные изображения и связанные прогнозы несколько раз, создайте метод программы отображения для обработки отображения изображений и результатов прогнозирования.
Создайте метод
DisplayResults()
сразу после структурыInceptionSettings
с помощью следующего кода:void DisplayResults(IEnumerable<ImagePrediction> imagePredictionData) { }
Заполните текст метода
DisplayResults
:foreach (ImagePrediction prediction in imagePredictionData) { Console.WriteLine($"Image: {Path.GetFileName(prediction.ImagePath)} predicted as: {prediction.PredictedLabelValue} with score: {prediction.Score?.Max()} "); }
Создание метода для формирования прогноза
Создайте метод
ClassifySingleImage()
непосредственно перед методомDisplayResults()
, вставив в него следующий код:void ClassifySingleImage(MLContext mlContext, ITransformer model) { }
Создайте объект
ImageData
, который хранит абсолютный путь и имя файла изображения для одного значенияImagePath
. Добавьте следующий код в качестве следующих строк в методеClassifySingleImage()
:var imageData = new ImageData() { ImagePath = _predictSingleImage };
Создайте один прогноз, добавив следующий код в виде следующей строки в методе
ClassifySingleImage
:// Make prediction function (input = ImageData, output = ImagePrediction) var predictor = mlContext.Model.CreatePredictionEngine<ImageData, ImagePrediction>(model); var prediction = predictor.Predict(imageData);
Чтобы получить прогноз, используйте метод Predict(). Класс PredictionEngine представляет собой удобный API, позволяющий осуществить прогнозирование на основе единственного экземпляра данных.
PredictionEngine
не является потокобезопасным. Допустимо использовать в средах прототипов или средах с одним потоком. Для улучшенной производительности и потокобезопасности в рабочей среде используйте службуPredictionEnginePool
, которая создаетObjectPool
объектовPredictionEngine
для использования во всем приложении. См. руководство по использованиюPredictionEnginePool
в веб-API ASP.NET Core.Примечание
Расширение службы
PredictionEnginePool
сейчас доступно в предварительной версии.Отобразите результат прогнозирования с помощью следующей строки кода в методе
ClassifySingleImage()
:Console.WriteLine($"Image: {Path.GetFileName(imageData.ImagePath)} predicted as: {prediction.PredictedLabelValue} with score: {prediction.Score?.Max()} ");
Создание конвейера модели ML.NET
Конвейер модели ML.NET — это цепочка средств оценки. Во время создания конвейера выполнение не происходит. Объекты оценки создаются, но не выполняются.
Добавление метода для создания модели
Этот метод является основным в учебнике. Он создает конвейер для модели и обучает конвейер для создания модели ML.NET. Он также оценивает модель по некоторым ранее неиспользуемым тестовым данным.
Создайте метод
GenerateModel()
сразу после структурыInceptionSettings
и непосредственно перед методомDisplayResults()
с помощью следующего кода:ITransformer GenerateModel(MLContext mlContext) { }
Добавьте средства оценки для загрузки, изменения размера и извлечения пикселей из данных изображения:
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))
Данные изображения должны обрабатываться в формате, который требуется модели TensorFlow. В этом случае изображения загружаются в память, преобразуются в соответствующий размер, а пиксели извлекаются в числовой вектор.
Добавьте средство оценки, чтобы загрузить модель TensorFlow и оценить ее:
.Append(mlContext.Model.LoadTensorFlowModel(_inceptionTensorFlowModel). ScoreTensorFlowModel(outputColumnNames: new[] { "softmax2_pre_activation" }, inputColumnNames: new[] { "input" }, addBatchDimensionInput: true))
Этот этап конвейера загружает модель TensorFlow в память, а затем обрабатывает вектор значений пикселей через сеть модели TensorFlow. Применение входных данных к модели глубокого обучения и формирование выходных данных с помощью модели называется оценкой. При полном использовании модели оценка делает вывод или прогноз.
В этом случае используется вся модель TensorFlow, за исключением последнего слоя, который делает вывод. Выходные данные предпоследнего слоя помечаются как
softmax_2_preactivation
. Выходные данные этого слоя фактически являются вектором признаков, характеризующих исходные входные изображения.Этот вектор признаков, созданный моделью TensorFlow, будет использоваться в качестве входных данных для алгоритма обучения ML.NET.
Добавьте средство оценки, чтобы сопоставлять строковые метки в данных для обучения с целочисленными значениями ключа:
.Append(mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "LabelKey", inputColumnName: "Label"))
Для обучающего алгоритма ML.NET, добавляемого далее, метки должны быть в формате
key
, а не в виде произвольных строк. Ключ — это число, которое содержит сопоставление по принципу "один к одному" со строковым значением.Добавьте алгоритм обучения ML.NET:
.Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName: "LabelKey", featureColumnName: "softmax2_pre_activation"))
Добавьте средство оценки для преобразования значения прогнозируемого ключа обратно в строку:
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabelValue", "PredictedLabel")) .AppendCacheCheckpoint(mlContext);
Обучение модели
Загрузите данные для обучения с использованием оболочки LoadFromTextFile. Добавьте в следующую строку метода
GenerateModel()
приведенный ниже код:IDataView trainingData = mlContext.Data.LoadFromTextFile<ImageData>(path: _trainTagsTsv, hasHeader: false);
Данные на ML.NET представлены интерфейсом IDataView.
IDataView
позволяет гибко и полно описывать табличные данные (числовые и текстовые). Данные можно загружать в объектIDataView
из текстового файла или в режиме реального времени (например, из базы данных SQL или файлов журнала).Обучите модель сна основе данных, загруженных ранее:
ITransformer model = pipeline.Fit(trainingData);
Метод
Fit()
обучает модель путем применения набора данных для обучения к конвейеру.
Оценка точности модели
Загрузите и преобразуйте проверочные данные, добавив приведенный ниже код в следующую строку метода
GenerateModel
: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);
Есть несколько примеров изображений, которые можно использовать для оценки модели. Как и данные для обучения, их нужно загрузить в
IDataView
, чтобы модель могла их преобразовать.Добавьте следующий код в метод
GenerateModel()
для оценки модели:MulticlassClassificationMetrics metrics = mlContext.MulticlassClassification.Evaluate(predictions, labelColumnName: "LabelKey", predictedLabelColumnName: "PredictedLabel");
Получив прогноз, с помощью метода Evaluate() вы сможете:
- оценить модель (сравнивает спрогнозированные значения с тестовым набором данных
labels
); - получить метрики производительности модели.
- оценить модель (сравнивает спрогнозированные значения с тестовым набором данных
Отобразите метрики точности модели.
Используйте следующий код для отображения метрик, передачи результатов и выполнения действий по ним:
Console.WriteLine($"LogLoss is: {metrics.LogLoss}"); Console.WriteLine($"PerClassLogLoss is: {String.Join(" , ", metrics.PerClassLogLoss.Select(c => c.ToString()))}");
Для классификации изображений выполняется оценка следующих метрик:
Log-loss
— см. раздел Логарифмические потери. Значение логарифмических потерь должно быть максимально близко к нулю.Per class Log-loss
. Значение логарифмических потерь для каждого класса должно быть максимально близко к нулю.
Добавьте следующий код, чтобы возвращать обученную модель:
return model;
Запуск приложения
Добавьте вызов метода
GenerateModel
после создания класса MLContext:ITransformer model = GenerateModel(mlContext);
Добавьте вызов метода
ClassifySingleImage()
после вызова методаGenerateModel()
:ClassifySingleImage(mlContext, model);
Запустите консольное приложение (CTRL + F5). Результаты выполнения должны выглядеть примерно так, как указано ниже. (Могут отображаться предупреждения или сообщения об обработке, но эти сообщения были удалены из следующих результатов для ясности.)
=============== 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
Поздравляем! Итак, вы завершили создание в ML.NET модели классификации изображений с использованием предварительно обученной модели обработки TensorFlow.
Исходный код для этого руководства можно найти в репозитории dotnet/samples.
В этом руководстве вы узнали, как:
- Определение проблемы
- внедрить предварительно обученную модель TensorFlow в конвейер ML.NET;
- обучить и оценить модель ML.NET;
- классифицировать тестовое изображение.
Ознакомьтесь с примерами Машинного обучения в репозитории GitHub, чтобы подробнее изучить расширенный пример классификации изображений.
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по