Машинное обучение в .NET

ML.NET - это кроссплатформенный фреймворк машинного обучения, который предоставляет самые современные алгоритмы машинного обучения, преобразования и компоненты. ML.NET позволяет разработчикам .NET разрабатывать / обучать модели и интегрировать машинное обучение со своими приложениями .NET, даже без предварительного опыта в тонкой настройке моделей машинного обучения.

В этом сообщении блога мы создадим веб-приложение для распознавания рукописных чисел с помощью ML.NET. Демонстрационное веб-приложение (ссылка) работает в контейнере Linux, что демонстрирует кроссплатформенные возможности ML.NET и ASP.NET Core. Вы можете найти полное решение в этом репозитории GitHub.

В демонстрационном веб-приложении мы можем нарисовать однозначное число [0–9] на холсте с помощью мыши или касания. Затем мы выполняем вызов API, который возвращает результат предсказания числа на основе изображения холста, нарисованного на веб-странице. На следующей записи экрана показаны некоторые прогнозы почерка, сделанные веб-приложением.

Основная часть веб-приложения - это конечная точка API, которая предсказывает написанные от руки числа с использованием предварительно обученной модели ML.NET. В следующих разделах мы сосредоточимся на том, как построить модель машинного обучения из набора обучающих данных и как обслуживать обученную модель в веб-API ASP.NET Core. В конце этого сообщения в блоге я обобщаю некоторые учебные материалы для начинающих.

Получите набор данных MNIST optdigits для обучения

Репозиторий GitHub для примеров ML.NET (ссылка) содержит некоторые общие наборы данных. Мы можем скачать набор данных MNIST для рукописных цифр отсюда. Набор данных содержит тысячи рукописных цифр в формате CSV. Мы сохраняем файлы optdigits-train.csv (набор данных для обучения) и optdigits-test.csv (набор данных для тестирования) в папке Data для дальнейшего использования.

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

В наборе данных каждая цифра представляет собой изображение с 64 пикселями и представлена ​​в виде одномерного массива (также известного как вектор) в первых 64 столбцах каждой строки данных. Каждый пиксель представляет собой целое число от 0 до 16. Все строки данных правильно помечены своими фактическими номерами в последнем (65-м) столбце.

Будьте осторожны, поскольку исходный набор данных может не так хорошо работать с вашим почерком, когда вы пробуете производственное веб-приложение. По крайней мере, для моего почерка мне нужно было добавить пару сотен новых строк данных в набор обучающих данных, чтобы научить модель распознавать числа, которые я написал. Об этом мы поговорим позже.

Обращение к репозиторию образцов ML.NET (ссылка) является хорошей отправной точкой для новых проектов, поскольку репозиторий образцов ML.NET предоставляет нам массу часто встречающихся проблем машинного обучения и их решений. Мы можем следить за примерами кода, копируя и вставляя их, когда работаем над нашими новыми проектами. Кроме того, мы можем изучить множество передовых практик из примеров решений.

С другой стороны, ML.NET предлагает фантастический инструмент для «чайников» машинного обучения. Сегодня мы рассмотрим этот инструмент и увидим, насколько он прост.

Постройте модель, используя ML.NET Model Builder

Конструктор моделей ML.NET (ссылка) - это интуитивно понятное расширение Visual Studio для создания, обучения и развертывания пользовательских моделей машинного обучения. На момент написания инструмент ML.NET Model Builder все еще находится в стадии предварительной версии, но уже имеет много полезных функций. Чтобы установить инструмент, следуйте документации здесь и убедитесь, что у вас есть подходящие версии Visual Studio и .NET Core SDK. На следующем снимке экрана показана успешная установка инструмента в Visual Studio.

Установив инструмент ML.NET Model Builder, мы можем приступить к построению модели. Используя Visual Studio 2019, мы сначала создаем решение HandwritingRecognition и добавляем новый проект MVC ASP.NET Core 3.0 с именем HandwritingRecognition. Затем мы щелкаем правой кнопкой мыши веб-проект MVC в Visual Studio и выбираем «Add», затем щелкаем «Machine Learning». Виола ~ мы находимся в центре сцены и собираемся сыграть шоу. На следующей записи экрана показаны все необходимые шаги.

Вкратце, шаги следующие:

  1. Выберите сценарий. Нам нужно решить MultiClass проблему классификации, поэтому мы выбираем «Пользовательский сценарий», чтобы продолжить.
  2. Загрузите данные и установите столбцы Label и Features. В этом проекте мы загружаем данные обучения из файла. Вы также можете загрузить данные из базы данных. ПРИМЕЧАНИЕ. Текущая версия Построителя моделей работает только с данными со строкой заголовка. Чтобы позволить Построителю моделей идентифицировать столбцы Label и Features, я вручную добавил строку заголовка в файл CSV. Кроме того, я бы хотел, чтобы построитель моделей поддерживал столбцы типа Vector (ссылка).
  3. Тренироваться. Мы выбираем MultiClass Classification в качестве задачи машинного обучения и даем ему тренироваться в течение 100 секунд. Инструмент опробует доступные алгоритмы и ранжирует их по метрикам. По окончании обучения инструмент выберет для нас лучший алгоритм (также известный как тренер). В этом проекте лучший алгоритм - LightGbmMulti (ссылка). Другие алгоритмы тоже очень хороши, и вы можете позже изменить трейнер в коде, если хотите.
  4. Оценивать. Этот шаг позволяет нам попробовать несколько отдельных прогнозов. На мой взгляд, этот шаг полезен, если Построитель моделей может выполнить оценку по набору данных тестирования. Я пропустил этот шаг, потому что построитель моделей уже оценил алгоритмы с помощью перекрестной проверки (ссылка) при итерации по обучающим программам.
  5. Генерация кода. Используя выбранный алгоритм и набор обучающих данных, Построитель моделей генерирует два проекта с полезным для нас кодом. Первый проект - HandwritingRecognitionML.Model, который представляет собой библиотеку классов, которая содержит классы ввода и вывода модели. Другой проект - HandwritingRecognitionML.ConsoleApp, который представляет собой консольное приложение, которое содержит классы построителя моделей и тестирования. Когда инструмент Построитель моделей добавляет новые проекты, он также устанавливает для нашего веб-проекта ссылку на библиотеку классов HandwritingRecognitionML.Model.

Очень удобно, не правда ли? Как вы видели, этот простой графический пользовательский интерфейс позволяет разработчикам, не имеющим опыта машинного обучения, обучать и использовать модель машинного обучения в своих приложениях.

В эти стартовые проекты я внес несколько изменений, чтобы улучшить код. Во-первых, я обновил целевую структуру проекта до netcoreapp3.0, чтобы она соответствовала структуре моего веб-приложения, чтобы упростить процесс сборки докеров. Затем я обновил класс ModelBuilder в приложении Console, чтобы использовать относительные пути к файлу обучающих данных и выходному файлу модели, и установил местоположение выходных данных модели на ContentRoot веб-проекта, чтобы веб-проект мог использовать модель напрямую всякий раз, когда построен новый.

Я также обновил файл ModelInput.cs до следующего фрагмента, чтобы отразить лучшую схему входных данных.

Первые 64 столбца объединены в одно свойство PixelValues с аннотацией VectorType(64). Считается хорошей практикой использовать VectorType (ссылка) для множества столбцов одного типа и всегда предназначенных для совместного использования. После изменения ModelInput класс ModelBuilder.cs необходимо соответственно немного обновить (см. Код в моем репозитории GitHub).

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

В этом случае, когда мы запускаем консольное приложение, модель будет повторно обучена, и новый MLModel.zip файл будет доставлен в веб-приложение для использования. Теперь, когда у нас есть MLModel.zip файл в ContentRoot веб-проекта, мы можем начать добавлять конечную точку API для прогнозов машинного обучения.

Создание веб-API для обслуживания модели машинного обучения

Нам нужно создать метод действия в контроллере, чтобы получить файл изображения или строку изображения base 64 из HTTP-запроса. Чтобы упростить проект, мы добавим метод действия Upload(string base64Image) в HomeController, который возвращает результаты прогнозирования.

В этом методе действия мы можем делать прогнозы, следуя коду приложения Console, которое создает экземпляр MLContext, затем загружает модель и, наконец, создает механизм прогнозирования для прогнозов.

Однако механизм прогнозирования не является потокобезопасным, и им сложно управлять по мере роста приложения. Вместо этого в документации (ссылка) рекомендуется использовать PredictionEnginePool, который находится в контейнере DI, для повышения производительности и безопасности потоков.

Чтобы использовать PredictionEnginePool, нам нужно установить пакет NuGet Microsoft.Extensions.ML. После этого мы можем зарегистрировать наш пул механизма прогнозирования в контейнере DI следующим образом.

Модель идентифицируется параметром modelName, который имеет статическое строковое значение HWRModel.Name в строке 15. PredictionEnginePool может иметь более одной модели для каждого приложения, которое будет перезагружено при изменении.

После регистрации PredictionEnginePool в контейнере DI мы можем внедрить экземпляр PredictionEnginePool<ModelInput, ModelOutput> в конструктор HomeController следующим образом.

Затем мы можем реализовать метод действия для запроса HTTP POST. В следующем фрагменте кода показан пример.

Поскольку здесь мы имеем дело с изображениями, нам нужно добавить в этот проект пакет NuGet Microsoft.ML.ImageAnalytics. Этот пакет NuGet включает пространства имен System.Drawing и System.Drawing.Common, которые предоставляют API-интерфейсы для управления изображениями.

Входное изображение имеет размер 256 x 256 пикселей с белым фоном. Следующий метод сжимает исходное изображение до 32 x 32 пикселей, а затем объединяет области 4 x 4 пикселя в качестве окончательных значений пикселей. При агрегации небелые пиксели считаются за 1, а чисто белые пиксели - за 0, в результате чего получается область 4 x 4 со значением в диапазоне от 0 до 16. Агрегированные значения затем передаются в механизм прогнозирования.

Механизм прогнозирования всегда возвращает число в результате прогнозирования. Нас также интересуют относительные баллы среди всех чисел. Примечание. порядок оценок основан на последовательности меток, появляющихся в наборе обучающих данных, поэтому нам нужен простой метод, чтобы расположить их в правильном порядке. Вы также можете следовать примеру Iris Classification в репозитории ML.NET Samples (ссылка), в котором есть метод, использующий схему вывода для автоматического упорядочивания массива оценок.

Внешний код выходит за рамки этой статьи. Если вам это интересно, загляните в мой репозиторий GitHub.

Переучите модель

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

Чтобы подогнать модель под свои нужды, я написал пару сотен цифр и промаркировал их. Приложение записывает значения пикселей в консоль браузера, когда приложение делает прогноз. Таким образом, я могу скопировать значения пикселей и добавить их с правильной цифровой меткой в ​​виде строки в исходный файл данных обучения.

Имея дополнительные данные для обучения, мы можем повторно обучить модель, запустив приложение Console. С новым файлом MLModel.zip веб-приложение, очевидно, неплохо справляется со мной (см. Запись экрана в верхней части этого сообщения). Эта история говорит нам о том, что количество и качество данных в машинном обучении имеют решающее значение для получения надежного результата.

Хорошо. Вроде пока все работает. Следующим шагом будет его развертывание.

Докеризуйте веб-приложение и разверните его на Heroku

Вы можете обратиться к одному из моих предыдущих сообщений в блоге (ссылка) для получения подробной информации о публикации веб-приложения на Heroku. В этом проекте я создал Dockerfile для докеризации приложения, чтобы мы могли создать образ докера и отправить его в реестр контейнеров.

Предостережение: сложная часть процесса докеризации - сделать пространство имен System.Drawing доступным в контейнере Linux, поскольку образ докера .NET Core не содержит libgdiplus и другие пакеты. для графики. Мы должны сами их установить. После некоторых поисков я пришел к окончательному Dockerfile файлу, подобному следующему yml.

В Dockerfile, строки с 16 по 22 устанавливают все необходимые пакеты для пространства имен System.Drawing. При этом мы можем создать образ докера приложения и отправить его в Heroku, используя рабочий процесс в GitHub Actions. Финальный сайт находится здесь.

Насколько хорош ML.NET! С небольшими усилиями мы создали веб-приложение с интеллектуальной моделью машинного обучения, которое может читать почерк практически любого человека. Мир машинного обучения довольно велик и становится все больше. С чего начать изучение всех возможных применений машинного обучения?

Обязательные к прочтению материалы

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

Если вы новичок в машинном обучении, вы также можете начать с изучения основ из коллекции ресурсов, ориентированных на ML.NET: Learn ML.NET. После того, как вы опробовали несколько руководств, прочтите Поваренную книгу ML.NET, которая может ответить на некоторые из ваших вопросов.

Как я упоминал выше, Примеры ML.NET в GitHub - хороший ресурс, который нужно держать под рукой. Репозиторий содержит множество сценариев, таких как анализ настроений, обнаружение мошенничества, рекомендация продукта, прогноз цен, обнаружение аномалий, классификация изображений, обнаружение объектов и многие другие.

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

Спасибо за прочтение.