Построение глубокой нейронной сети с помощью Tensorflow для Raspberry Pi

От облачных вычислений к туманным вычислениям

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

Учитывая потенциал машинного обучения, неудивительно, что более 60 компаний, включая Intel, Nvidia и Google, разрабатывают микросхемы, которые могут выполнять эти операции в гораздо более быстром масштабе. Благодаря этой технологии даже Raspberry Pi требуется всего несколько миллисекунд, чтобы пройти через глубокую нейронную сеть и произвести вывод (по сути, прогноз). Возможности этих чипов разнообразны, и они все чаще используются во многих устройствах, таких как камеры и дроны. Вы можете найти микросхему Myriad от Intel Movidius в своем дроне DJI, например, или, вскоре, в спутниках Европейского космического агентства для обработки изображений на орбите.

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

Далее я расскажу вам о своей попытке создать глубокую нейронную сеть в Tensorflow, перенести эту модель на Raspberry Pi и сделать вывод с использованием внешнего устройства для повышения производительности. Я провел этот эксперимент с чипами от двух ведущих игроков: Intel и Google.

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

Все фрагменты кода из проекта доступны в моем репозитории на github.

Давайте копаться!

Настройка и цель

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

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

Хороший вопрос. Есть много доступных моделей, предварительно обученных на огромных наборах данных, некоторые из которых даже скомпилированы для устройства, которое мы хотим использовать. Вы можете получить потрясающие результаты за несколько часов, выполняя обнаружение объектов с помощью MobileNetV2 SSD.

Однако наша цель не в том, чтобы управлять гоночным автомобилем, а в том, чтобы понять проблемы, связанные с его постройкой. Это нужно для того, чтобы понять до мельчайших деталей, что означает «вывод на грани».

Для этого конкретного проекта я использовал чипы от Intel и Google. Передо мной слева направо Intel Neural Compute Stick 2, Google Coral Accelerator и Google Coral Board.

Coral Accelerator и Intel Neural Compute Stick 2 будут подключены к Raspberry Pi3b. Обе Raspberry работают на недавно развернутом Raspbian (Raspbian GNU / Linux 9stretch). Coral Dev Board входит в стандартную комплектацию Mendel (Mendel GNU / Linux 2 Beaker). Код, который я включу в эту статью, работает также на Coral Dev Board, но здесь я остановлюсь на USB-ключах.

Создание и квантование модели Tensorflow с помощью CIFAR10

CIFAR10 - это общедоступный набор данных, который можно скачать здесь. Это набор из 60 000 изображений (32 * 32 пикселя). Каждое изображение относится к одной из следующих 10 категорий: самолет, автомобиль, птица, кошка, олень, собака, лягушка, лошадь, корабль или грузовик.

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

Существуют разные методы, которые можно использовать для построения глубокой нейронной сети в Tensorflow. Самым быстрым, безусловно, является использование модели Keras или создание своей собственной. Я сделал и то, и другое. Сначала я создал сеть MobileNetV2. Затем я построил свёртку с 3 модулями. Я использовал пост-квантование для квантования двух моделей, обе работали очень хорошо. К сожалению, пост-квантование в настоящее время не поддерживается в Google edge-tpu. Стоит упомянуть, что мне удалось запустить convnet на Intel NCS2.

Это предварительное исследование показывает, насколько чувствительны эти устройства к типу данных, которые они обрабатывают. Это, безусловно, та область, в которую игроки будут вкладывать значительные средства в ближайшие годы. В любом случае, поскольку постквантование не поддерживается на edge-tpu, нам необходимо построить квантованную сеть глубокого обучения. Поскольку Keras не поддерживает это, у нас есть два варианта. Мы можем использовать низкоуровневый Tensorflow API или построить Оценщик. Давайте попробуем сэкономить время, построив оценщик с помощью Tensorflow и проведя обучение с учетом квантования.

Наши первые слои будут состоять из двух модулей свертки. Затем мы обработаем тензоры плотным слоем из 10 единиц, чтобы охватить наши 10 категорий. У оценщика есть разные методы обучения, оценки и прогнозирования. Методы обучения и оценки строят свой собственный график. Если вы пошагово пройдетесь в записной книжке, вы заметите функцию cnn_model_fn. Здесь мы добавляем слои и делаем сантехнику.

Это графическое представление того, что мы построили. Как видите, сеть довольно мала по сравнению с предварительно обученными моделями. Мы даже можем распечатать его на странице!

В функции cnn_model_fn были добавлены две строки для квантования. Два вызова tf.contrib.quantize.create_training_graph () и tf.contrib.quantize.create_eval_grap () соответственно создают квантованный обучающий граф и граф оценки (тот, который нам нужен). Эти две функции добавляют к нашему графику множество узлов, чтобы имитировать изменение типа данных и помочь создать квантованный график.

После определения функции модели мы обучаем наш Оценщик на наборе данных CIFAR, используя AdamOptimizer и перекрестную энтропию softmax для потерь. Интересно отметить, что функция contrib для создания обучающего графа дает вам возможность начать обучение с типом данных высокой точности и закончить его с типом данных низкой точности.

Вот пример того, что вы должны увидеть в Tensorboard для потери.

После обучения модели мы начнем оценку 5000 функций, которые мы оставили в стороне для проверки нашей модели. Затем мы попросим модель предсказать случайную выборку, чтобы приблизительно оценить ее точность.

График, который нам нужно экспортировать, был создан на этапе оценки. Оценщики упрощают создание сохраненной_модели. На метод classifier.experimental_export_all стоит потратить некоторое время, так как вы можете выбрать карту тегов, которую хотите экспортировать.

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

Тест №1: вывод с помощью Google Accelerator

Google анонсировал Coral Accelerator и Dev Board 26 марта 2019 года. Ресурсы для него сейчас относительно ограничены, но Google ежедневно добавляет новые.

Развернуть среду для Google Accelerator просто. Просто следуйте инструкциям по началу работы от Google. Через 10 минут все готово. Я настоятельно рекомендую использовать виртуальную среду. После того, как все установлено, вы можете поиграть как с моделями обнаружения, так и с моделями категоризации.

Теперь, когда у нас есть среда, давайте сделаем вывод нашей модели. Во-первых, нам нужно скомпилировать нашу сохраненную_модель в модель tflite. Для этого мы должны использовать TOCO, конвертер Google.

Если вы будете следовать инструкциям блокнота до конца, вам останется только запустить:

toco -graph_def_file = frozen.pb -output_file = tflite_model.tflite -input_format = TENSORFLOW_GRAPHDEF -output_format = TFLITE -inference_type = QUANTIZED_UINT8 -input_shape = ”1,32, 32,3 - вход_массив_входа = -модель_вход_массив = модель_вход_массив -mean_value = 127 -default_ranges_min = 0 -default_ranges_max = 6

Вы можете видеть, что помимо имени входа и имени выходных тензоров важно указать отклонение, среднее значение, а также диапазоны по умолчанию для Relu. Вот почему мы решили использовать Relu6.

Еще один шаг перед перемещением ресурсов в Raspberry: конвертируйте модель tflite в модель edgetpu.tflite. Для этого есть онлайн-инструмент. Вы должны увидеть что-то вроде:

Если вы этого не сделаете, это, скорее всего, означает, что вы не соблюдаете требования.

Теперь давайте напишем код, чтобы сделать вывод. Edge-tpu API действительно прост в использовании. Вы должны использовать либо ClassificationEngine, либо DetectionEngine. Оба движка расширяют BasicEngine и предоставляют простые методы для загрузки модели и выполнения логического вывода. Файл python, который я использовал для запуска нашей модели, находится здесь.

После того, как файл python и ресурсы (т.е. edge_tpu_model и хотя бы одно изображение из CIFAR10) загружены, вы можете запустить модель и убедиться, что она работает. У вас должно получиться что-то вроде:

Поздравляю! Вы успешно построили и запустили нашу квантованную модель на Raspberry Pi с помощью Google Accelerator.

Стоит отметить, что API Google edge-tpu позволяет проводить обучение на устройстве с помощью Accelerator. Это замечательная функция, например, если вы хотите заниматься онлайн-обучением.

Тест # 2: вывод с помощью NCS

Movidius анонсировал Neural Compute Stick еще в июле 2017 года и в настоящее время на несколько кругов опережает Google. Эта технология поддерживает больше сред и имеет разные API для работы.

Я начал играть с Intel Movidius NCSDK. NCSDK включает набор программных инструментов для компиляции, профилирования и проверки глубоких нейронных сетей, а также включает Intel Movidius NCAPI для разработки приложений на C / C ++ или Python. К сожалению, NCSDK V2 предназначен только для NCS V1. Он не поддерживает NCS V2. (Да, это сбивает с толку.)

Для NCS V2 вы должны использовать OpenVino. OpenVino - это недавняя разработка, целью которой является унификация различных платформ Intel для процессоров, графических процессоров, VPU (Movidius) и FPGA (Altera). Мне очень нравится архитектура OpenVino, которая позволяет использовать разные плагины OpenVino в зависимости от вашей цели.

Я сожалею только о том, что NCSDK был действительно мощным и предлагал множество настроек; это было очень плохо, я не мог играть с этим здесь. С другой стороны, мне нравится, что OpenVino связан с OpenCV. Это обязательно поможет в будущем. И наконец, что не менее важно, удивительная новость заключается в том, что и NCSDK, и OpenVino имеют открытый исходный код под лицензией Apache License 2.0.

Что касается поиска подходящего пакета OpenVino для вашего Raspberry, я рекомендую посетить Центр загрузок Intel. Я использую l_openvino_toolkit_raspbi_p_2019.1.094.tgz. Помните, что вам также необходимо установить OpenVino на свой рабочий стол, так как именно здесь вы будете использовать все инструменты для компиляции, профилирования и проверки ваших DNN.

Для развертывания следуйте документации по установке Intel для Raspberry. Это более сложный процесс, чем в среде Google. (Что имеет смысл, поскольку чем больше у вас вариантов, тем сложнее настройка.)

После того, как вы установили среду OpenVino, вы можете поиграть с действительно классной демонстрацией, которая объединяет три модели. На картинке ниже вы можете увидеть, как они работают. Первая модель обнаруживает машину. Затем вторая модель обнаруживает номерной знак. Третья модель читает табличку.

Чтобы портировать нашу замороженную модель на Raspberry, мы должны использовать Оптимизатор модели. Оптимизатора моделей нет на Raspberry, поэтому вам нужен OpenVino на рабочем столе.

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

Вы найдете параметры, которые я использовал, в конце этой записной книжки. Когда у вас есть два файла (.xml и .bin) вашего промежуточного представления, вы перемещаете их в свое рабочее пространство на Raspberry. Вам также понадобится как минимум одно изображение CIFAR10 и файл python, чтобы сделать вывод. Вы должны увидеть что-то вроде этого:

Некоторое время я играл с OpenVino API. Я попытался понять, как подключить пару камер и использовать модуль глубины. Я также попытался использовать net.forwardAsync () для повышения производительности. У меня не получилось. API OpenVino появился совсем недавно и, похоже, отстает от API Movidius с точки зрения возможностей. К сожалению, я думаю, что нам придется подождать еще одного или двух выпусков, чтобы воспользоваться этими расширенными функциями.

Относительная производительность: Google против Intel

Оба SoC имеют очень впечатляющие характеристики и большую вычислительную мощность.

Myriad X - это третье поколение Intel Movidius VPU (блок обработки изображений). SoC предназначен для работы с 8 датчиками RGB и обработкой 4K с частотой как 30 Гц, так и 60 Гц. Он обрабатывает 700 миллионов пикселей в секунду. Чип использует более 20 аппаратных ускорителей для выполнения оптического потока и глубины стерео. Вдобавок ко всему, 16 программируемых 128-битных векторных процессоров позволяют запускать несколько параллельных конвейеров приложений технического зрения.

К сожалению, Google дает гораздо меньше информации о edge-tpu. Они рассказывают, что графический процессор edge-tpu имеет 4 шейдера и обрабатывает ошеломляющие 1,6 гигапикселей в секунду. Кроме того, Google утверждает, что блок обработки видео может обрабатывать 4kp60 в H.265 и 1080p60 для mpeg 2.

На бумаге Intel SoC кажется более мощным, чем edge-tpu.

Производительность на ватт обоих устройств кажется действительно хорошей. На двух картинках ниже показано энергопотребление двух устройств в состоянии покоя. Похоже, NCS V2 требует больше мВт, но это требует подтверждения в условиях стресса. Google любезно уведомляет нас во время настройки, что ускоритель может сильно нагреться. Я не заметил каких-либо значительных изменений температуры при запуске обнаружения объектов на Raspberry Pi. Скорее всего, спецификации Pi Cam и ограничение USB-2 затрудняют работу устройств в достаточной степени.

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

Я измерил 70 мс на вывод в мобильной сети v1 для Myriad, 60 мс для edge-tpu в мобильной сети v2 и 550 мс только для Raspberry. Мобильная сеть v2 (3,47 миллиона MAC) с ее узкими уровнями требует меньше вычислений, чем v1 (4,24 миллиона MAC). Принято считать, что мобильная сеть v2 на 15–30% быстрее. Следовательно, на Raspberry Pi эти два устройства будут находиться на одном уровне с небольшим отрывом от Myriad.

Также важно помнить, что python - не лучший вариант с точки зрения производительности. Оба устройства также имеют доступный C ++ API, который был бы моим выбором для оптимальной производительности. Интересно, что вы можете объединить Intel Movidius NCS в стек, что является действительно хорошей функцией.

Учитывая спецификации двух устройств, производительность на доллар в конечном итоге оказывается очень похожей. Стоимость Google Accelerator составляет 74,99 доллара, а INTEL NCS V2 - 99 долларов. Вы всегда можете купить Movidius V1 по цене 74 доллара.

Факторы дизайна также очень похожи, что упрощает интеграцию USB-ключей в любые проекты. Google Accelerator тоньше NCS V2, но его необходимо подключать с помощью кабеля USB-C-USB-2. Intel обратилась к одной жалобе на V1: на Raspberry дизайн V1 охватывал более одного порта USB. V2 охватывает только один.

Заключение

Вычислительная мощность обоих устройств позволяет разработчикам обрабатывать широкий спектр сценариев использования.

Множество предварительно скомпилированных сетей позволяет легко получать быстрые и хорошие результаты. Тем не менее, полное квантование ваших собственных сетей остается сложной задачей. Преобразование требует глубокого понимания вашей сети и того, как работают операции. Кроме того, потеря точности значительна при переходе от FP_32 к FP_16 и от FP_16 к UINT. Интересно отметить, что Myriad обрабатывает половину чисел с плавающей запятой, когда Google Accelerator обрабатывает только 8-битные числа с фиксированной запятой. Это означает, что Myriad будет обеспечивать большую точность.

Intel и Google явно выбрали два совершенно разных подхода. Сила Google заключается в легкости, с которой можно создать и продать интегрированный рабочий процесс от облачной платформы Google до edge-tpu. Мне очень нравится, как все компоненты сочетаются друг с другом. Intel, с другой стороны, предлагает посредническое представление Intel и плагины Openvino, которые разработчики могут использовать для оптимизации своих сетей для работы на любом оборудовании. OpenVINO в настоящее время поддерживает процессоры Intel, графические процессоры, FPGA и VPU. Задача Intel состоит в том, что в стратегии унификации всегда будет сложно использовать расширенные функции каждого компонента.

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

Мне очень понравилось быть частью сообщества Intel. Члены очень полезны. Мне не помогал Google, но это, безусловно, потому, что его продуктовая линейка очень молода. Документация Intel очень обширна, хотя иногда и сбивает с толку. В то время, когда я проводил этот эксперимент, документации Google практически не существовало. С тех пор я заметил, что эта ситуация быстро улучшается, и я ожидаю вскоре увидеть очень хорошую обучающую платформу (colab) с большим количеством ресурсов.

Выводы на грани определенно стремительно растут, и можно увидеть удивительные рыночные прогнозы. По данным ABI Research, в 2018 году выручка от поставок периферийного ИИ составила 1,3 миллиарда долларов США. Ожидается, что к 2023 году эта цифра вырастет до 23 миллиардов долларов США.

Очевидно, что одно решение не подойдет всем, поскольку предприниматели находят новые способы развертывания машинного обучения. Будет интересно посмотреть, какие доли рынка в конечном итоге захватят оба игрока. Я уверен, что облачная платформа Google будет стимулировать появление множества передовых приложений обучения, в то время как Intel будет управлять очень разнообразными проектами на всех типах оборудования со многими партнерами.

В любом случае можно быть уверенным в том, что теперь у нас есть инструменты для инноваций и ускорения четвертой промышленной революции.

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