Здесь, в Trueface, мы используем MXNet для обучения наших моделей машинного обучения. MXNet - отличный фреймворк, когда дело доходит до прототипирования и обучения, благодаря надежному и простому в использовании API, который позволяет разработчикам любого уровня подготовки приступить к работе всего с нескольких строк кода.

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

К сожалению, MXNet - не лучший кандидат на решение этой задачи. Он не только оказывается сравнительно медленным для выполнения логического вывода, но также требует многих зависимостей при построении для скорости (среди других библиотек требуется Intel MKL-DNN).

Одним из решений этой проблемы является преобразование этих моделей в более производительные фреймворки, такие как NCNN и TVM. Обе эти платформы были оптимизированы для вывода (как на CPU, так и на GPU) и упакованы как автономные статические библиотеки.

Первоначально, когда мы искали способы преодолеть разрыв между MXNet и NCNN / TVM, единственные найденные нами инструкции были либо неполными, либо требовали серьезных модификаций. Поэтому мы создали это сквозное руководство, чтобы помочь тем, кому необходимо преобразовать модели MXNet в более удобные для использования ресурсы.

В этом уроке мы конвертируем 100-слойную модель ResNet для распознавания лиц. Чтобы продолжить, загрузите LResNet100E-IRmodel с открытым исходным кодом со страницы InsightFace Github. После распаковки файлов у вас должен быть файл params и файл json. Следующее руководство было написано для Ubuntu.

MXNet в NCNN

NCNN - это высокопроизводительная вычислительная среда для нейронных сетей, оптимизированная для мобильных платформ. NCNN очень внимательно относится к развертыванию и использованию на мобильных телефонах с самого начала проектирования. NCNN не имеет сторонних зависимостей. Он кроссплатформенный и работает быстрее всех известных фреймворков с открытым исходным кодом на ЦП мобильных телефонов.

Скачайте и соберите NCNN

Начните с загрузки последней версии NCNN с их страницы Github. Мы будем использовать исполняемый файл mxnet2ncnn для выполнения преобразования. На момент написания статьи конвертер не поддерживает оператор _copy. Следовательно, мы должны добавить поддержку этого оператора, используя исправление, описанное в этой проблеме Github.

Перейдите к ncnn/tools/mxnet и откройте mxnet2ncnn.cpp в предпочитаемом вами редакторе. Добавьте в эту строку следующий код:

Затем создайте исполняемый файл, запустив mkdir build && cd build && cmake .. && make. Теперь у вас должен быть исполняемый файл с именем mxnet2ncnn. Находясь здесь, также найдите время, чтобы построить сам NCNN (нам это потребуется позже для выполнения логического вывода). Инструкции по сборке можно найти здесь.

Преобразование моделей

Переместите исполняемый файл mxnet2ncnn в каталог, в который вы извлекли файлы модели MXNet, и выполните следующую команду: ./mxnet2ncnn model-symbol.json model-0000.params. Это создаст два новых файла: ncnn.bin и ncnn.param..

Выполнение логического вывода с NCNN на C ++

Входные данные для этой модели должны быть выровненными изображениями 112x112. В этом уроке мы будем использовать предварительно выровненные изображения, которые доступны для скачивания на сайте LFW.

Следующий код демонстрирует, как выполнить логический вывод с NCNN:

Не забудьте связать соответствующие библиотеки и добавить файлы включения NCNN. Вот образец CMakeLists.txt

MXNet в TVM

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

Скачайте и соберите TVM

Начнем с клонирования репозитория TVM Github. Переместите файл конфигурации в каталог сборки:

git clone --recursive https://github.com/dmlc/tvm
cd tvm
mkdir build
cp cmake/config.cmake build

Далее устанавливаем необходимые зависимости:

sudo apt-get update
sudo apt-get install -y python3 python3-dev python3-setuptools gcc libtinfo-dev zlib1g-dev build-essential cmake python3-pip libxml2-dev

Установите один из предварительно собранных двоичных файлов LLVM. На момент написания этого руководства я использовал LLVM 8.0.0. Как только это будет завершено, отредактируйте файл config.cmake, чтобы он указывал на конфигурацию LLVM:

set(USE_LLVM /path/to/your/llvm/bin/llvm-config)

Теперь соберите библиотеку TVM:

cd build
cmake ..
make -j4

Теперь нам нужно добавить переменную PYTHONPATH, чтобы сообщить python, где он может найти библиотеку. Либо экспортируйте переменные непосредственно в свою оболочку, либо добавьте их в свой ~/.bashrc, чтобы изменения сохранялись:

export TVM_HOME=/path/to/tvm
export PYTHONPATH=$TVM_HOME/python:$TVM_HOME/topi/python:$TVM_HOME/nnvm/python:${PYTHONPATH}

Наконец, установите зависимости Python:

pip3 install --user numpy decorator attrs tornado psutil xgboost mxnet

Конвертация и автонастройка модели

На этом этапе мы могли бы преобразовать модель непосредственно в TVM. Хотя это будет успешно преобразовано, мы получим следующие предупреждения:

Cannot find config for target=llvm -mcpu=skylake, workload=('conv2d', (1, 3, 112, 112, 'float32'), (64, 3, 3, 3, 'float32'), (1, 1), (1, 1), (1, 1), 'NCHW', 'float32'). A fallback configuration is used, which may bring great performance regression.

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

Следующий скрипт сначала загрузит модели, настроит их автоматически, а затем скомпилирует их в формат TVM. Обратите внимание, что модели должны соответствовать соглашениям об именах model-symbol.json и model-XXXX.params. Измените цель, чтобы она соответствовала архитектуре вашего процессора. Задайте путь к каталогу вашей модели в указанном месте.

Запуск этого сценария приведет к появлению трех артефактов: tvm.json tvm.params и tvm_lib.so. Примечание: это может занять некоторое время, так как процесс настройки идет медленно.

Выполнение логического вывода с помощью TVM на C ++

Еще раз, входные данные для этой модели должны быть выровненными изображениями 112x112. В этом уроке мы будем использовать предварительно выровненные изображения, которые доступны для загрузки на сайте LFW.

Следующий код демонстрирует, как выполнить логический вывод с помощью TVM. Нам нужно будет загрузить tvm_lib.so во время выполнения.

Чтобы он работал правильно, нам нужно будет собрать tvm_runtime_pack.cc с нашим исполняемым файлом. Этот файл можно получить из tvm/apps/howto_deploy/. Нам также потребуются некоторые включаемые файлы из каталога TVM.

Пример CMakeLists.txt показан ниже:

Заключительные замечания

Вот и все. Мы успешно преобразовали нашу модель MXNet в NCNN и TVM. Эти более легкие модели готовы к интеграции в среду с ограниченными ресурсами без серьезной потери производительности. Обратите внимание, что модель TVM имеет небольшую разницу в точности, которая является результатом шага настройки. Мы надеемся, что это руководство будет полезно инженерам, ищущим способы преобразования фреймворков из обучающих сред в реальные развертывания.

Не стесняйтесь писать нам на [email protected] с любыми вопросами или комментариями.