инференс в машинном обучении это
What Is Machine Learning Inference?
Machine learning (ML) inference is the process of running live data points into a machine learning algorithm (or “ML model”) to calculate an output such as a single numerical score. This process is also referred to as “operationalizing an ML model” or “putting an ML model into production.” When an ML model is running in production, it is often then described as artificial intelligence (AI) since it is performing functions similar to human thinking and analysis. Machine learning inference basically entails deploying a software application into a production environment, as the ML model is typically just software code that implements a mathematical algorithm. That algorithm makes calculations based on the characteristics of the data, known as “features” in the ML vernacular.
An ML lifecycle can be broken up into two main, distinct parts. The first is the training phase, in which an ML model is created or “trained” by running a specified subset of data into the model. ML inference is the second phase, in which the model is put into action on live data to produce actionable output. The data processing by the ML model is often referred to as “scoring,” so one can say that the ML model scores the data, and the output is a score.
ML inference is generally deployed by DevOps engineers or data engineers. Sometimes the data scientists, who are responsible for training the models, are asked to own the ML inference process. This latter situation often causes significant obstacles in getting to the ML inference stage, since data scientists are not necessarily skilled at deploying systems. Successful ML deployments often are the result of tight coordination between different teams, and newer software technologies are also often deployed to try to simplify the process. An emerging discipline known as “MLOps” is starting to put more structure and resources around getting ML models into production and maintaining those models when changes are needed.
How Does Machine Learning Inference Work?
To deploy a machine learning inference environment, you need three main components in addition to the model:
The data sources are typically a system that captures the live data from the mechanism that generates the data. For example, a data source might be an Apache Kafka cluster that stores data created by an Internet of Things (IoT) device, a web application log file, or a point-of-sale (POS) machine. Or a data source might simply be a web application that collects user clicks and sends data to the system that hosts the ML model.
The host system for the ML model accepts data from the data sources and inputs the data into the ML model. It is the host system that provides the infrastructure to turn the code in the ML model into a fully operational application. After an output is generated from the ML model, the host system then sends that output to the data destinations. The host system can be, for example, a web application that accepts data input via a REST interface, or a stream processing application that takes an incoming feed of data from Apache Kafka to process many data points per second.
The data destinations are where the host system should deliver the output score from the ML model. A destination can be any type of data repository like Apache Kafka or a database, and from there, downstream applications take further action on the scores. For example, if the ML model calculates a fraud score on purchase data, then the applications associated with the data destinations might send an “approve” or “decline” message back to the purchase site.
Challenges of Machine Learning Inference
As mentioned earlier, the work in ML inference can sometimes be misallocated to the data scientist. If given only a low-level set of tools for ML inference, the data scientist may not be successful in the deployment.
Additionally, DevOps and data engineers are sometimes not able to help with deployment, often due to conflicting priorities or a lack of understanding of what’s required for ML inference. In many cases, the ML model is written in a language like Python, which is popular among data scientists, but the IT team is more well-versed in a language like Java. This means that engineers must take the Python code and translate it to Java to run it within their infrastructure. In addition, the deployment of ML models requires some extra coding to map the input data into a format that the ML model can accept, and this extra work adds to the engineers’ burden when deploying the ML model.
Also, the ML lifecycle typically requires experimentation and periodic updates to the ML models. If deploying the ML model is difficult in the first place, then updating models will be almost as difficult. The whole maintenance effort can be difficult, as there are business continuity and security issues to address.
Another challenge is attaining suitable performance for the workload. REST-based systems that perform the ML inference often suffer from low throughput and high latency. This might be suitable for some environments, but modern deployments that deal with IoT and online transactions are facing huge loads that can overwhelm these simple REST-based deployments. And the system needs to be able to scale to not only handle growing workloads but to also handle temporary load spikes while retaining consistent responsiveness.
When pursuing a machine learning strategy, technology choice is very important to address these challenges. Hazelcast is an example of a software vendor that provides in-memory and streaming technologies that are well-suited for deploying ML inference. Open source editions are available to try out the technology with no commitment.
Оценка эффективности инференса нейронных сетей
Развитие рынка нейронных сетей подразумевает под собой удешевление стоимости железа при постоянном росте производительности. Обычно нейронная сеть проходит три жизненных этапа: обучение, деплой и инференс. Если про обучение и деплой материала в сети предостаточно, то инференс — нераскрытая тема, в которой стоит разобраться.
Инференс
Инференсом называется непрерывная работа какой-либо нейронной сети на конечном устройстве. Инференс выполняется для совершенно разных нейронных сетей, например — для распознавания марок, моделей транспортных средств, лиц, голосов, анализа текстовых материалов и много другого. То есть, это процесс исполнения сети, когда она уже готова к проведению полезной работы.
Для инференса используются процессоры общего назначения CPU, графические процессоры GPU, некоторые другие вычислительные единицы.
Инференс на CPU
В случае использования CPU, инференс выполняется на логических ядрах процессора, число которых равно числу физических ядер или, при использовании технологии Hyper-threading, увеличено вдвое. Решения на современных многоядерных процессорах достаточно дороги, а использование CPU на больших (глубоких) нейросетях неэффективно из-за ограниченного объема кэша процессора и необходимости организации обмена данными с ОЗУ, что существенно влияет на скорость работы. Кроме того, ограничения на производительность накладываются самой архитектурой — в процессе инференса решаются простые задачи сравнения, которые легко переносятся на параллельные вычисления, но количество параллельных потоков обработки всегда будет ограничено количеством логических ядер CPU.
Инференс на GPU
Оценка производительности инференса
Инференс — процесс несложный, в некоторой степени даже примитивный, однако рост сложности нейронной сети приводит к нелинейному росту необходимых для инференса ресурсов. В результате вполне реально упереться в потолок вычислительной производительности системы или канала передачи данных. Из этой проблемы очевидными видятся два выхода — отправлять данные на обработку к серьезным вычислительным мощностям, если канал передачи данных позволяет, или выполнять его на месте, увеличивая локальную производительность. Но и в первом и во втором случае возникает проблема оценки производительности устройств, осуществляющих инференс. Ведь будет очень странным, если нейросеть работает, но для ее работы требуется система стоимостью много мертвых американских президентов.
Производители устройств всегда нацелены на увеличение продаж. Методики тестирования, которые они предлагают, бывают очень своеобразными, как и выводы которые делаются на базе таких тестов. Например, пытались сравнить количество логических ядер разных устройств, заявляя, что количество ядер имеет решающее значение, хотя понятно, что сравнивать десяток Intel 80486 даже с одним Intel i5 мягко говоря неэтично. Пытались сравнить количество обрабатываемых потоков, гордо заявляя, что решение может обрабатывать 100 каналов, тактично замалчивая, что эти потоки – 240p. Каждый измерял в своих попугаях, и каждый из этих попугаев c точки зрения производителя был более правильный и более производительный.
Очевидно, что для практического применения такие методики непригодны. Мы — компания Combox Technology, как разработчики оборудования, нуждались в сравнительных характеристиках, которые позволяли бы объективно оценивать конечную стоимость эксплуатации системы. Мы попытались привязать эффективность к стоимости — той характеристике, которая прямо связана с клиентом. Было проведено исследование скорости сетей различных топологий на различных видах устройств (процессоры и видеокарты) с привязкой к стоимости. Вы можете ознакомиться с ним по ссылке. Основные метрики, которые нас интересовали — это цена за FPS (frame per second) и скорость (relative FPS).
Результаты получились очень интересные. Именно их мы использовали при разработке наших устройств для инференса. Максимальную скорость инференса при оптимальной стоимости FPS можно получить на одноплатном компьютере (SBC) Intel NUC8i5BEK, поскольку на них в полной мере раскрывается потенциал совместного инферена на CPU и GPU. Именно по этой причине мы использовали это устройство в наших устройствах SBC NUC Server. Для другого устройства OutdoorBox NUC используется Intel NUC4i5MYHE.
Эти решения создавались как раз для того, чтобы решить боль, описанную в начале статьи — максимальная эффективность с максимальной объективностью оценки.
Что же получилось в результате?
OutdoorBox NUC — высокопроизводительное решение для инференса на краю, которое используется при необходимости сократить трафик, решать локальные задачи при минимальной стоимости внедрения и эксплуатации. Устройство выполнено во всепогодном исполнении IP66, обладает низким энергопотреблением (30Вт) и обладает великолепной производительностью при низкой стоимости. Одно устройство способно одновременно эффективно работать с 10 потоками FullHD 15fps.
Для корпоративного сегмента при потребностях в высоких вычислительных мощностях мы разработали SBC NUC Server, которое объединяет в одном корпусе до 8 устройств NUC8i5BEK и обеспечивает обработку до 80 потоков FullHD 15fps.
Очевидно, что такие решения разрабатываются не из-за простого интереса к экспериментам. Мы разрабатываем, обучаем и эксплуатируем нейронные сети, например, для целей распознавания марок и моделей транспортных средств, номерных знаков. Для классификации объектов мы используем нейронную сеть на топологии YOLO (You Only Look Once), которая построена на ее упрощенной оптимизированной модели DarkNet19, использующую 19 слоев, взамен оригинальных 25, и нейронную сеть на топологии UNET для детектирования. Решение используется в коммерческом продукте EDGE с MMR (Make and Model Recognition) и LPR (Licence Plate Recognition), который активно эксплуатируется по всему миру – в национальной полиции Колумбии, Мексики, Белоруссии, Грузии, Болгарии, таможенных терминалах Украины, Азербайджана, системах городского видеонаблюдения Аргентины, Омана, Казахстана. Эффект от внедрения SBC NUC Server был очень существенным и осязаемым – в отличие от GPU-серверов на базе Tesla T4, используемых ранее, стоимостью 1 200 000 рублей, наше решение дешевле на 500 000 рублей, энергопотребление вместо 2 кВт на единицу теперь составляет всего 500 Вт. При этом экономится место в стойках – GPU-сервера обычно имеют формат 2U-4U, в отличие от 1U в нашем случае. Что очень важно – мы получили унифицированное решение на стандартной элементной базе, что позволяет в случае необходимости перепрофилировать устройство под другие задачи, кроме инференса (кластерные решения, web-сервер и пр.)
А потребитель теперь может быть уверен в объективности предлагаемых оценок — эффективность измеряется в деньгах — самых универсальных попугаях.
TensorRT 6.x.x.x — высокопроизводительный инференс для моделей глубокого обучения (Object Detection и Segmentation)
Больно только в первый раз!
Всем привет! Дорогие друзья, в этой статье я хочу поделиться своим опытом использования TensorRT, RetinaNet на базе репозитория github.com/aidonchuk/retinanet-examples (это форк официальной репы от nvidia, который позволит начать использовать в продакшен оптимизированные модели в кратчайшие сроки). Пролистывая сообщения в каналах сообщества ods.ai, я сталкиваюсь с вопросами по использованию TensorRT, и в основном вопросы повторяются, поэтому я решил написать как можно более полное руководство по использованию быстрого инференса на основе TensorRT, RetinaNet, Unet и docker.
Описание задачи
Предлагаю поставить задачу таким образом: нам необходимо разметить датасет, обучить на нём сеть RetinaNet/Unet на Pytorch1.3+, преобразовать полученные веса в ONNX, далее сконвертировать их в engine TensorRT и всё это дело запустить в docker, желательно на Ubuntu 18 и крайне желательно на ARM(Jetson)* архитектуре, тем самым минимизируя ручное развертывание окружения. В итоге мы получим контейнер готовый не только к экспорту и обучению RetinaNet/Unet, но и к полноценной разработке и обучению классификации, сегментации со всей необходимой обвязкой.
Этап 1. Подготовка окружения
Здесь важно заметить, что в последнее время я полностью ушёл от использования и развертывания хоть каких-то библиотек на desktop машине, как впрочем и на devbox. Единственное, что приходится создавать и устанавливать — это python virtual environment и cuda 10.2 (можно ограничиться одним драйвером nvidia) из deb.
Предположим, что у вас свежеустановленная Ubuntu 18. Установим cuda 10.2(deb), подробно на процессе установки я останавливаться не буду, официальной документации вполне достаточно.
Теперь установим docker, руководство по установке докера можно легко найти, вот пример www.digitalocean.com/community/tutorials/docker-ubuntu-18-04-1-ru, уже доступна 19+ версия — ставим её. Ну и не забудьте сделать возможным использования docker без sudo, так будет удобнее. После того как всё получилось, делаем вот так:
И можно даже не заглядывать в официальный репозиторий github.com/NVIDIA/nvidia-docker.
Осталось совсем чуть-чуть, для того чтобы начать пользоваться docker с nvidia-образом, нам потребуется зарегистрировать в NGC Cloud и залогиниться. Идём сюда ngc.nvidia.com, регистрируемся и после того как попадаем внутрь NGC Cloud, жмём SETUP в левом верхнем углу экрана или преходим по этой ссылке ngc.nvidia.com/setup/api-key. Жмём «сгенерить ключ». Его рекомендую сохранить, иначе при следующем посещении его придётся генерить заново и, соответственно, разворачивая на новой тачке, повторно производить эту операцию.
Username просто копируем. Ну вот, считай, среда развернута!
Этап 2. Сборка контейнера docker
На втором этапе нашей работы мы соберем docker и познакомимся с его внутренностями.
Перейдём в корневую папку по отношению к проекту retina-examples и выполним
Мы собираем docker пробрасывая в него текущего юзера — это очень полезно если вы будете что-то писать на смонтированный VOLUME с правами текущего юзера, иначе будет root и боль.
Пока собирается docker, давайте изучим Dockerfile:
Как видно из текста, мы берем все наши любимые либы, компилируем retinanet, накидываем базовых инструментов для удобства работы с Ubuntu и настраиваем сервер openssh. Первой строкой идет как раз наследование образа nvidia, для которого мы делали логин в NGC Cloud и который содержит Pytorch1.3, TensorRT6.x.x.x и еще кучу либ, позволяющих скомпилировать cpp исходники нашего детектора.
Этап 3. Запуск и отладка контейнера docker
Перейдем к основному кейсу использования контейнера и среды разработки, для начала запустим nvidia docker. Выполним:
Теперь контейнер доступен по ssh @localhost. После успешного запуска, открываем проект в PyCharm. Далее открываем
Шаг 1
Шаг 2
Шаг 3
Выбираем всё как на скриншотах,
— это будет ln на Python3.6 и
Жмём финиш, ожидаем индексирование, и всё, среда готова к использованию!
ВАЖНО. Сразу после индексирования вытянуть из docker скомпилированные файлы для Retinanet. В контектсном меню в корне проекта выберем пункт
Появятся один файл и две папки build, retinanet.egg-info и _С.so
Если ваш проект выглядит так, то среда видит все необходимые файлы и мы готовы, к обучению RetinaNet.
Этап 4. Размечаем данные и обучаем детектор
Для разметки я, в основном, использую supervise.ly — приятная и удобная тулза, в последнее време кучу косяков пофиксили и она стала существенно лучше себя вести.
Предположим что вы разметили датасет и скачали его, но сразу засунуть его в наш RetinaNet не выйдет, так как он в собственном формате и для этого нам необходимо сконвертировать его в COCO. Тулза для конвертации находится в:
Обратите внимание, что Category в скрипте это пример и вам необходимо вставить свои (категорию background добавлять не надо)
Авторы оригинального репозитория почему-то решили, что ничего кроме COCO/VOC вы обучать для детекции не будете, поэтому пришлось немного подредактировать исходный файл
Добавив тутда любимые аугментации albumentations.readthedocs.io/en/latest и выпилить жёстко вшитые категории из COCO. Также есть возможность кропнуть большие области детекции, если вы на больших картинках ищите маленькие объекты, у вас маленький датасет =), и ничего не работает, но об этом в другой раз.
В общем train loop тоже слабенький, изначально он не сохранял чекпоинты, юзал какой-то ужасный scheduler и т.д. Но теперь вам осталось только выбрать backbone и выполнить
Что бы изучить весь набор параметров посмотрите
В общем они стандартные для детекции, и у них есть описание. Запустите обучение и дождитесь результатов. Пример инференса можно посмотреть в:
или выполнить команду:
В репозитории уже встроен Focal Loss и несколько backbone, а так же легко впиливаются свои
В табличке авторы приводят некоторые характеристики:
Также есть backbone ResNeXt50_32x4dFPN и ResNeXt101_32x8dFPN, взятый из torchvision.
Надеюсь с детекцией немного разобрались, но стоит обязательно прочитать официальную документацию, чтобы понять режимы экспорта и логирования.
Этап 5. Экспорт и инференс моделей Unet c энкодером Resnet
Как вы, наверное, обратили внимание, в Dockerfile были установлены библиотеки для сегментации и в частности замечательная либа github.com/qubvel/segmentation_models.pytorch. В пакете юнет можно найти примеры инференса и экспорта pytorch чекпоинтов в engine TensorRT.
Основная проблема при экспорте Unet-like моделей из ONNX в TensoRT — это необходимость задавать фиксированный размер Upsample или пользоваться ConvTranspose2D:
С помощью этого преобразования можно сделать это автоматически при экспорте в ONNX, но уже в 7 версии TensorRT эту проблему решили, и нам осталось ждать совсем немного.
Когда я начал использовать docker у меня были сомнения на счёт его производительности для моих задач. В одном из моих агрегатов сейчас довольно большой сетевой трафик создаваемый несколькими камерами.
Разные тесты на просторах интернета говорили об относительно большом overhead на сетевое взаимодействие и запись на VOLUME, плюс ко всему неведомый и страшный GIL, а так как съемка кадра, работа драйвера и передача по сети кадра являются атомарной операцией в режиме hard real-time, задержки в сети для меня очень критичны.
P.S. Остаётся добавить ваш любимый трейн луп для сегментации и в продакшен!
Спасибо сообществу ods.ai, без него невозможно развиваться! Огромное спасибо n01z3, надоумевшему меня заняться DL, за его бесценные советы и чрезвычайный профессионализм!
Используйте в production оптимизированные модели!
Aurorai, llc
Deep Learning Inference Benchmark — измеряем скорость работы моделей глубокого обучения
Перед разработчиками встает задача определения производительности железа в задаче исполнения глубоких моделей. Например, хочется решить проблему анализа пола-возраста покупателей, которые заходят в магазин, чтобы в зависимости от этого менять оформление магазина или наполнение товаром. Вы уже знаете какие модели хотите использовать в вашем ПО, но до конца не понятно как выбрать железо. Можно выбрать самый топ и переплачивать как за простаивающие мощности, так и за электроэнергию. Можно взять самый дешевый i3 и потом вдруг окажется, что он может вывезти каскад из нескольких глубоких моделей на 8 камерах. А может быть камера всего одна, и для решения задачи достаточно Raspberry Pi с Movidius Neural Compute Stick? Поэтому хочется иметь инструмент для оценки скорости работы вашего инференса на разном железе, причем еще до начала обучения.
В целом можно выделить три направления работы с глубокими моделями:
Общую схему решения задач с использованием глубокого обучения можно представить следующим образом:
Из лекции курса по современным методам и технологиям глубокого обучения в компьютерном зрении
Как правило, требования по скорости заложены еще на этапе постановки задачи, и хочется еще до начала обучения или дообучения узнать «уложится» или нет предполагаемая модель в доступные для инференса ресурсы. И для решения этой задачи был создан DLI benchmark.
DLI benchmark
В рамках лаборатории ITLab студентами ННГУ им. Н.И.Лобачевского был разработан открытый фреймворк DLI (https://github.com/itlab-vision/dl-benchmark), который позволяет запустить измерение производительности большого количества разных моделей на доступном железе.
Основные требования, которые были заложены на этапе разработки:
Архитектура фреймворка
Схема со страницы проекта
Алгоритм работы DLI-benchmark:
Типы экспериментов
При обработке картинок по одной вычислительное устройство очень часто недогружено. Можно подать два изображения одной пачкой (batch=2), тогда они обработаются быстрее чем два изображения по отдельности. При увеличении размера пачки производительность сначала начнет расти, а потом падать, и определить лучший размер пачки весьма полезно.
В современных фреймворках поддерживается асинхронный режим работы, когда не нужно дожидаться конца обработки предыдущего изображения, можно новую картинку начать обрабатывать сразу после поступления. При использовании асинхронного API в OpenVINO можно создавать реквесты по 1 картинке независимо и при этом получать по прежнему высокую производительность и при этом низкие задержки. Возможность получать высокую производительность, сохраняя при этом низкие задержки, открывает новые возможности для инференса глубоких моделей на многосокетных высокопроизводительных системах.
Метрики производительности
В случае когда мы можем подавать несколько картинок независимо друг от друга (асинхронный запуск на обработку), мы используем другие метрики производительности.
Анализ результатов
В ходе экспериментов мы попробовали бенчмарк на различном оборудовании: CPU i7-7700K, i5-8600K, i3-7100, i7-8700, i3-8100, GPU Intel HD Graphics 630, Intel Neural Compute Stick 2.
Пока опубликовали результаты только для фреймворка OpenVINO. Докеры бенчмарка с Caffe, TensofFlow и PyTorch в разработке.
Для демонстрации примеров работы возьмем модель ResNet-152 — это очень объемная модель, которая решает задачу классификации ImageNet.
На графике ниже представлена время обработки одной пачки картинок в различных режимах. На данном графике по оси X отложено количество потоков процессора, которые были использованы для обработки изображений, а по оси Y — среднее время обработки (или задержка, latency) одной пачки изображений. На этом графике мы видим, что при удвоении использованных потоков скорость обработки увеличивается примерно в два раза — это означает отличную параллеллизацию в обработке изображений. Что важно, параллелизация показывает хорошие результаты и для большой пачки картинок, и для одиночной картинки.
Чтобы посчитать FPS (сколько в среднем картинок в секунду обработает процессор в каждом режиме работы) нужно количество картинок в пачке разделить на время обработки одной пачки. Эти данные мы приведем в таблице ниже.
Взглянув на эти цифры, мы видим, что если мы будем использовать все 6 ядер процессора, что при обработке картинок пачками по 8 штук производительность возрастает на 20% из-за более плотной упаковки вычислений. Но в прикладном ПО не слишком хочется писать дополнительные функции, чтобы собирать картинки в пачки, да и задержки тогда возрастают…
В этом случае нам на помощь приходит асинхронный запуск нескольких картинок на обработку! OpenVINO поддерживает возможность не собирать из картинок большую пачку, а подавать картинки независимо друг от друга не дожидаясь завершения обработки предыдущей. В данном режиме вы задаете в программе количество «стримов» (это не поток процессора; это сущность, которая захватывает один или несколько потоков процессора и обрабатывает в себе картинку), и можете независимо запускать на обработку картинки по мере поступления.
С использованием OpenVINO в асинхронном режиме с размером пачки в 1 картинку мы почти достигаем производительности, полученной в синхронном режиме с размером пачки 8, при этом почти не меняя код запуска моделей.
