Учебник. Обучение модели классификации ML.NET для категоризации изображений

Узнайте, как обучить модель классификации категоризировать изображения с помощью предварительно обученной модели TensorFlow для обработки изображений.

Модель TensorFlow была обучена для классификации изображений по тысячам категорий. Поскольку модель TensorFlow способна распознавать на изображениях знакомые элементы, модель ML.NET может частично использовать ее в собственном конвейере для преобразования необработанных изображений в признаки или входные данные для обучения модели классификации.

В этом руководстве вы узнаете, как:

  • Определение проблемы
  • внедрить предварительно обученную модель TensorFlow в конвейер ML.NET;
  • обучить и оценить модель ML.NET;
  • классифицировать тестовое изображение.

Исходный код для этого руководства можно найти в репозитории dotnet/samples. По умолчанию конфигурация проекта .NET в этом руководстве предназначена для .NET Core 2.2.

Предварительные требования

Выбор типа задачи машинного обучения

Глубокое обучение

Глубокое обучение — это разновидность машинного обучения, совершающая революцию в области компьютерного зрения, распознавания речи и других подобных сферах.

Модели глубокого обучения обучаются на крупных наборах помеченных данных с использованием нейронных сетей, которые содержат множество слоев обучения. Глубокое обучение:

  • лучше решает некоторые задачи, например в области компьютерного зрения;
  • требует огромных объемов данных для обучения.

Классификация изображений — это конкретная задача их автоматической классификации по категориям, например:

  • для определения того, содержит ли изображение человеческое лицо;
  • для различения изображений котов и собак.

Она также помогает определить тип объекта на изображении — еда, игрушка или прибор:

пицца изображениеплюшевый медведь изображениетостер изображение

Примечание

Изображения выше принадлежат Викискладу и имеют следующие атрибуты:

Обучение модели классификации изображений с нуля требует задания миллионов параметров, а также использования огромных объемов помеченных обучающих данных и вычислительных ресурсов (сотни часов работы GPU). Использование предварительно обученной модели не настолько эффективно, как обучение специализированной модели с нуля, однако за счет использования лишь тысяч (а не миллионов) помеченных изображений этот подход позволяет получить требуемую модель существенно быстрее (в пределах часа) на компьютере без GPU. В этом учебнике этот процесс еще более уменьшен: используется только десяток изображений для обучения.

Модель Inception model обучена классифицировать изображения по тысяче категорий, но в этом учебнике вам столько категорий не нужно. Вам также нужны четко определенные категории. Вы можете использовать способность Inception model распознавать и классифицировать изображения в новых ограниченных категориях своего классификатора изображений.

  • еда;
  • игрушка;
  • прибор.

В этом учебнике используется TensorFlow Inception, популярная модель глубокого обучения для распознавания изображений, обученная на наборе данных ImageNet. Модель TensorFlow классифицирует все изображения по тысячам классов, таких как "зонт", "жакет" и "посудомоечная машина".

Так как Inception model предварительно обучена на тысячах различных изображений, она содержит признаки изображений, необходимые для их идентификации. Мы можем использовать эти внутренние признаки изображений в модели для обучения новой модели с гораздо меньшим числом классов.

Как показано на схеме ниже, вам нужно добавить ссылки на пакеты NuGet ML.NET в приложения .NET Core или .NET Framework. На внутреннем уровне ML.NET включает и ссылается на встроенную библиотеку TensorFlow, которая позволяет создавать код, загружающий существующую обученную модель TensorFlow.

Схема преобразования ML.NET с использованием 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

Установка

Создание проекта

  1. Создайте консольное приложение C# с именем TransferLearningTF. Нажмите кнопку Далее.

  2. Выберите .NET 6 в качестве используемой платформы. Нажмите кнопку Создать .

  3. Установите пакет NuGet для Microsoft.ML:

    Примечание

    В этом примере используется последняя стабильная версия пакетов NuGet, упомянутых выше, если не указано иное.

    • В обозревателе решений щелкните проект правой кнопкой мыши и выберите Управление пакетами NuGet.
    • Выберите nuget.org в качестве источника пакета, откройте вкладку "Обзор" и выполните поиск Microsoft.ML.
    • Нажмите кнопку Установить.
    • Нажмите кнопку ОК в диалоговом окне Предварительный просмотр изменений.
    • Нажмите кнопку Принимаю в диалоговом окне Принятие условий лицензионного соглашения, если вы согласны с условиями лицензионного соглашения для указанных пакетов.
    • Повторите эти шаги для пакетов Microsoft.ML.ImageAnalytics, SciSharp.TensorFlow.Redist и Microsoft.ML.TensorFlow.

Скачивание ресурсов

  1. Скачайте ZIP-файл каталога с ресурсами проекта и распакуйте его.

  2. Скопируйте каталог assets в каталог проекта TransferLearningTF. Этот каталог и его подкаталоги содержат данные и файлы поддержки (за исключением модели Inception, которую вы скачаете и добавите на следующем шаге), необходимые для работы с этим руководством.

  3. Скачайте модель Inception и распакуйте ее.

  4. Скопируйте содержание каталога inception5h, который вы распаковали, в каталог assets/inception проекта TransferLearningTF. Этот каталог содержит модель и дополнительные файлы поддержки, необходимые для работы с этим руководством, как показано на следующем рисунке:

    Содержание каталога Inception

  5. В обозревателе решений щелкните правой кнопкой мыши каждый файл в каталоге и подкаталогах ресурсов и выберите Свойства. В разделе Дополнительно для параметра Копировать в выходной каталог установите значение Копировать более позднюю версию.

Создание классов и определение путей

  1. Добавьте следующие новые операторы using в начало файла Program.cs:

    using Microsoft.ML;
    using Microsoft.ML.Data;
    
  2. Добавьте следующий код в строку прямо под операторами 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");
    
  3. Создайте классы для входных данных и прогнозов.

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

    ImageData является классом входных данных изображения и имеет следующие поля String:

    • ImagePath содержит имя файла изображения.
    • Label содержит значение для метки изображения.
  4. Добавьте новый класс в свой проект для ImagePrediction:

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

    ImagePrediction является классом прогноза изображения и имеет следующие поля:

    • Score содержит процентное значение достоверности для конкретной классификации изображения.
    • PredictedLabelValue содержит значение для прогнозируемой метки классификации изображения.

    Класс ImagePrediction используется для прогнозирования после обучения модели. Он включает string (ImagePath) с путем к изображению. Label используется для применения и обучения модели. PredictedLabelValue используется для прогнозирования и оценки. Для оценки применяются входные обучающие данные, прогнозируемые значения и модель.

Инициализация переменных

  1. Инициализируйте переменную mlContext с использованием нового экземпляра MLContext. Замените строку Console.WriteLine("Hello World!") следующим кодом:

    MLContext mlContext = new MLContext();
    

    Класс MLContext является отправной точкой для любых операций ML.NET. В результате инициализации класса mlContext создается среда ML.NET, которая может использоваться всеми объектами в рамках процесса создания модели. По существу он аналогичен классу DBContext в Entity Framework.

Создание структуры для параметров модели Inception

  1. Модель 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;
    }
    

Создание служебного метода для отображения данных

Поскольку вы будете отображать данные изображения и связанные прогнозы несколько раз, создайте метод программы отображения для обработки отображения изображений и результатов прогнозирования.

  1. Создайте метод DisplayResults() сразу после структуры InceptionSettings с помощью следующего кода:

    void DisplayResults(IEnumerable<ImagePrediction> imagePredictionData)
    {
    
    }
    
  2. Заполните текст метода DisplayResults:

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

Создание метода для формирования прогноза

  1. Создайте метод ClassifySingleImage() непосредственно перед методом DisplayResults(), вставив в него следующий код:

    void ClassifySingleImage(MLContext mlContext, ITransformer model)
    {
    
    }
    
  2. Создайте объект ImageData, который хранит абсолютный путь и имя файла изображения для одного значения ImagePath. Добавьте следующий код в качестве следующих строк в методе ClassifySingleImage() :

    var imageData = new ImageData()
    {
        ImagePath = _predictSingleImage
    };
    
  3. Создайте один прогноз, добавив следующий код в виде следующей строки в методе 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 сейчас доступно в предварительной версии.

  4. Отобразите результат прогнозирования с помощью следующей строки кода в методе ClassifySingleImage():

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

Создание конвейера модели ML.NET

Конвейер модели ML.NET — это цепочка средств оценки. Во время создания конвейера выполнение не происходит. Объекты оценки создаются, но не выполняются.

  1. Добавление метода для создания модели

    Этот метод является основным в учебнике. Он создает конвейер для модели и обучает конвейер для создания модели ML.NET. Он также оценивает модель по некоторым ранее неиспользуемым тестовым данным.

    Создайте метод GenerateModel() сразу после структуры InceptionSettings и непосредственно перед методом DisplayResults() с помощью следующего кода:

    ITransformer GenerateModel(MLContext mlContext)
    {
    
    }
    
  2. Добавьте средства оценки для загрузки, изменения размера и извлечения пикселей из данных изображения:

    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. В этом случае изображения загружаются в память, преобразуются в соответствующий размер, а пиксели извлекаются в числовой вектор.

  3. Добавьте средство оценки, чтобы загрузить модель 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.

  4. Добавьте средство оценки, чтобы сопоставлять строковые метки в данных для обучения с целочисленными значениями ключа:

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

    Для обучающего алгоритма ML.NET, добавляемого далее, метки должны быть в формате key, а не в виде произвольных строк. Ключ — это число, которое содержит сопоставление по принципу "один к одному" со строковым значением.

  5. Добавьте алгоритм обучения ML.NET:

    .Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName: "LabelKey", featureColumnName: "softmax2_pre_activation"))
    
  6. Добавьте средство оценки для преобразования значения прогнозируемого ключа обратно в строку:

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

Обучение модели

  1. Загрузите данные для обучения с использованием оболочки LoadFromTextFile. Добавьте в следующую строку метода GenerateModel() приведенный ниже код:

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

    Данные на ML.NET представлены интерфейсом IDataView. IDataView позволяет гибко и полно описывать табличные данные (числовые и текстовые). Данные можно загружать в объект IDataView из текстового файла или в режиме реального времени (например, из базы данных SQL или файлов журнала).

  2. Обучите модель сна основе данных, загруженных ранее:

    ITransformer model = pipeline.Fit(trainingData);
    

    Метод Fit() обучает модель путем применения набора данных для обучения к конвейеру.

Оценка точности модели

  1. Загрузите и преобразуйте проверочные данные, добавив приведенный ниже код в следующую строку метода 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, чтобы модель могла их преобразовать.

  2. Добавьте следующий код в метод GenerateModel() для оценки модели:

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

    Получив прогноз, с помощью метода Evaluate() вы сможете:

    • оценить модель (сравнивает спрогнозированные значения с тестовым набором данных labels);
    • получить метрики производительности модели.
  3. Отобразите метрики точности модели.

    Используйте следующий код для отображения метрик, передачи результатов и выполнения действий по ним:

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

    Для классификации изображений выполняется оценка следующих метрик:

    • Log-loss — см. раздел Логарифмические потери. Значение логарифмических потерь должно быть максимально близко к нулю.
    • Per class Log-loss. Значение логарифмических потерь для каждого класса должно быть максимально близко к нулю.
  4. Добавьте следующий код, чтобы возвращать обученную модель:

    return model;
    

Запуск приложения

  1. Добавьте вызов метода GenerateModel после создания класса MLContext:

    ITransformer model = GenerateModel(mlContext);
    
  2. Добавьте вызов метода ClassifySingleImage() после вызова метода GenerateModel():

    ClassifySingleImage(mlContext, model);
    
  3. Запустите консольное приложение (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, чтобы подробнее изучить расширенный пример классификации изображений.