Обнаружение лиц на видео с помощью Movidius Neural Compute Stick |
||
МЕНЮ Искусственный интеллект Поиск Регистрация на сайте Помощь проекту ТЕМЫ Новости ИИ Искусственный интеллект Разработка ИИГолосовой помощник Городские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Техническое зрение Чат-боты Авторизация |
2018-01-24 19:47 распознавание образов, реализация нейронной сети, алгоритмы машинного обучения Не так давно в свет вышло устройство Movidius Neural Compute Stick (NCS), представляющее собой аппаратный ускоритель для нейронных сетей с USB интерфейсом. Меня заинтересовала потенциальная возможность применения устройства в области робототехники, поэтому я приобрел его и задумал запустить какую-нибудь нейросеть. Однако большинство существующих примеров для NCS решают задачу классификации изображений, а мне хотелось попробовать кое-что другое, а именно обнаружение лиц. В этой публикации я хотел бы поделиться опытом, полученным в ходе такого эксперимента.
Весь код можно найти на GitHub. Подробнее об NCS Neural Compute Stick — это устройство, предназначенное для ускорения нейронных сетей (преимущественно свёрточных) на этапе применения (inference). Идея заключается в том, что NCS можно присоединить к роботу или дрону и запускать нейросети там, где для этого не хватает вычислительных ресурсов. К примеру, NCS можно подключить к Raspberry Pi. Выбор модели Отлично, мы хотим решить задачу обнаружения лиц (face detection). Есть две довольно популярные архитектуры нейросетей для задач обнаружения: это Fast-RCNN/Faster-RCNN и YOLO. Мне не хотелось на данном этапе обучать свою модель, поэтому решил поискать готовую. Конвертация модели Для конвертации модели я решил использовать вот этот проект, позволяющий переходить между форматами Darknet, Pytorch и Caffe.
Получается кое-что интересное: модель конвертируется, но выдается предупреждение о том, что слои типа Crop, Dropout и Detection распознать не удалось, из-за чего конвертер их пропустил. Можно ли обойтись без этих слоев? Оказывается, можно. Если внимательно посмотреть на код Darknet, можно заметить следующее: Слой типа Crop нужен только на этапе обучения. Он занимается тем, что расширяет выборку, поворачивая изображение на случайные углы и вырезая из него случайные фрагменты. На этапе применения он не потребуется. С Dropout немного интереснее. Dropout слой тоже нужен в основном на этапе обучения (Dropout слой обнуляет выходы нейронов с вероятностью ) для того, чтобы избежать переобучения и повысить способности модели к обобщению. На этапе применения от него можно избавиться, но при этом необходимо масштабировать выходы нейронов так, чтобы матожидание значений на входах следующего слоя не изменилось, чтобы поведение модели сохранилось (разделить на ). Если вглядеться в код Darknet, то можно заметить, что Dropout слой не только обнуляет некоторые выходы, но и масштабирует все остальные, поэтому Dropout слой можно безболезненно удалить. Что касается Detection слоя, то он находится последним и занимается тем, что переводит в более читаемый вид выходы с предпоследнего слоя, а также считает функцию потерь на этапе обучения. Функцию потерь нам считать не нужно, а вот перевод результата в читаемый вид пригодится. В итоге я решил просто использовать функцию для последнего слоя прямиком из Darknet (немного подредактировав ее), оттуда же взял функцию для NMS (Non maximum suppression — удаление избыточных ограничивающих рамок). Они находятся в файлах detection_layer.c и detection_layer.h. Тут стоит сделать замечание о том, что делает предпоследний слой. В архитектуре YOLO (You only look once) изображение разбивается на блоки сеткой размера (в данном случае ), и для каждого блока предсказывается значений, где — число ограничивающих рамок для каждого блока, а — число классов. Сами значения представляют собой: координаты, ширину, высоту и значение уверенности для каждой из рамок (то есть, всего пять значений), а также вероятность нахождения объекта в этом блоке для каждого класса. Итого получается значений. Слой Detection только разделяет разные типы данных и приводит их в структурированный вид. Осталась одна проблема: конвертер генерирует .prototxt файл с форматом входного слоя, который NCSDK не может разобрать. Различия исключительно декоративные: конвертер записывает размер входного слоя в формате: А утилита mvNCCompile, которая должна компилировать нейронную сеть в понятный NCS файл, хочет видеть формат:
Python скрипт utils/fix_proto_input_format.py призван решить эту проблему (не самому же это делать). Компиляция модели Теперь, когда модель переведена в формат Caffe, можно ее скомпилировать. Делается это довольно просто:
Эта команда должна породить бинарный файл graph, который представляет собой граф вычислений в формате, понятном NCS. Предобработка изображений Важно правильно организовать обработку изображений перед их загрузкой в граф вычислений, иначе нейросеть будет работать не так, как задумано. В качестве данных для нейросети я буду использовать кадры с веб-камеры, полученные с помощью OpenCV. Обращение к NCS и загрузка данных Тут стоит заметить, что я использую C++, а не Python, поскольку ориентируюсь на применение устройства в робототехнике и верю, что на C++ можно добиться большего быстродействия. Именно из-за этого появляются дополнительные сложности: граф вычислений получает на вход и выдает на выходе данные в формате fp16 (16-битные числа с плавающей точкой), реализации которых нет в C++ по умолчанию. В примерах NCSDK эта проблема решается использованием функций floattofp16 и fp16tofloat, выдранных из Numpy, поэтому я использую такое же решение.
Для загрузки данных и получения результата используются функции mvncLoadTensor и mvncGetResult соответственно. При этом нужно помнить про конвертацию данных и результата в fp16 и обратно. Для прекращения работы с NCS нужно освободить ресурсы, отведенные под граф вычислений (mvncDeallocateGraph) и закрыть устройство (mvncCloseDevice). Поскольку для взаимодействия с NCS нужно довольно много действий, я написал класс-обертку, у которого (помимо конструктора и деструктора) есть всего две функции: load_file для инициализации устройства и графа и load_tensor для загрузки данных и получения результата. Профилировщик В NCSDK есть полезная утилита, которая позволяет не только оценить быстродействие каждого слоя, но еще и создать схему графа вычислений, на которой отражены характеристики каждого элемента (кстати, передавать сами веса слоев при этом необязательно):
Что получилось в итоге Итоговый результат выглядит следующим образом: Источник: habrahabr.ru Комментарии: |
|