В этой статье выполним необходимые действия для обучения нейронной сети детектирования объектов с учетом особенностей ее имплементации на Nvidia Jetson Nano. Будем решать задачу детектирования кораблей в видеопотоке.
Выбор нейронной сети
Для разработки нейронных сетей мы используем фреймворк tensorflow (TF) от компании Google. Сложившаяся практика решения классических задач детектирования или классификации объектов выглядит следующим образом: подбирается некоторая предобученная нейронная сеть и выполняется ее дообучение на нужных вам данных. Этот процесс называют transfer learning.
Приведем небольшой пример, описанный в этом видео на нашем канале. В рамках одной бизнес-задачи было необходимо детектировать в режиме реального времени рабочих в цеху на заводе Nissan. Для решения этой задачи мы выбрали предобученную сеть зоопарка Tensorflow Zoo для TF версий 2.x.x. При выборе нейронной сети мы руководствовались следующими рассуждениями:
- рабочие не очень быстро перемещают в пространстве и допустимо обрабатывать не каждый кадр видеопотока (поэтому параметр fps не ключевой);
- детектировать необходимо всего лишь один класс – рабочих (поэтому не требуется слишком глубокая нейронная сеть);
- нам не хотелось арендовать облако для обучения, желательно было ограничиться ресурсами Google Colab версии Pro (24 Gb Ram, GPU Tesla V100 16 Gb).
Нам подошла небольшая предобученная нейронная сеть со сравнительно хорошим качеством детекции SSD MobileNet V2 FPNLite 640×640. Все сети в Tensorflow Zoo обучены на известном датасете COCO. Выбранную нейронную сеть мы дообучили на размеченных ранее данных и получили требуемый качественный детектор с помощью техники transfer learning.
В случае обучения сети для дальнейшей ее имплементации на Jetson Nano есть некоторые особенности. В предыдущей статье были описаны способы имплементации нейронной сети на Jetson Nano. Наиболее стабильный путь – это завернуть нейронную сеть в сервер TensorRT. Для этого обученную сеть необходимо сконвертировать в формат trt, подходящий для TensorRT. При конвертации с нейронной сетью будет совершен цикл преобразований:
По шагам:
- Квантование нейронной сети (подробнее здесь).
- Слияние слоев.
- Оптимизация архитектуры, выбор наиболее «информационно-ценных» слоев.
- Оптимизация хранения тензоров в оперативной памяти.
- Оптимизация архитектуры для многопоточного вычисления.
- Дополнительная оптимизация рекуррентных нейронных сетей, интеграция динамически генерируемых ядер.
Каждый шаг представляет собой сложное, наукоемкое преобразование, поэтому версия фреймворка, на котором реализована нейронная сеть, имеет критическое значение. На момент написания статьи актуальная версия TensorRT 7.2.3. Разработчики TensorRT в официальной документации обещают стабильную работу со следующими версиями популярных фреймворков:
Таким образом, на момент написания статьи мы не могли пользоваться нейронными сетями их зоопарка Tensorflow Zoo версии 2. Выбирать нейронную сеть мы были должны из зоопарка первой версии.
Ситуация с детектированием кораблей не отличалась по своим характеристикам от ситуации с детектированием рабочих. Мы остановили свой выбор на сравнительно древней архитектуре faster rcnn. Сети на базе данной архитектуры работают довольно медленно, но обеспечивают высокое качество детекции. Название выбранной сети в зоопарке «faster_rcnn_resnet50_coco».
Дообучение нейронной сети
Загруженная нейронная сеть из коробки может выполнять детекцию кораблей, что нам и нужно. Все нейронные сети в зоопарке TF обучены на датасете COCO, в котором содержатся размеченные для детекции картинки на 80 классах (транспорт, животные и др.). Но нам хочется показать полный цикл имплементации нейронной сети, поэтому мы выполнили этап дообучения сети.
Для дообучения нейронной сети необходимы размеченные данные, соответствующие решаемой задачи. В задачах детекции под размеченными данными подразумеваются изображения и сохраненные в каком-то формате прямоугольники (bounding boxes), содержащие в себе объекты классов.
В примере с детекцией рабочих в цеху, мы размечали данные вручную с помощью программы labelimg. С каждой камеры мы взяли по 30 минут видеопотока, разбили на кадры с интервалом в 1 секунду, разметили данные и сохранили в формате Pascal Voc (labelimg умеет это делать из коробки). На полученном датасете мы дообучили выбранную ранее нейронную сеть (официальный тьюториал, подробное видео с нашего канала).
Не будем повторяться и возьмем данные для обучения из датасета COCO. Хотя нейронные сети в зоопарке TF обучены на датасете COCO, дообучение нейронной сети на изображениях только одного класса, а не 80 должно увеличить качество детектирования именного этого типа объектов. Кроме того, разберемся со структурой данных хранения в COCO.
Датасет COCO
COCO – common objects in context датасет, содержащий более 330 тысяч изображений, на которых отмечены объекты из 80 классов. Причем разметка сделана как для задачи детекции объектов, так и для сегментации. Разница отражена на рисунке:
Разметка изображений для детектирования объектов представляет собой файлы с параметрами bonding boxes (как правило левая верхняя координата прямоугольника, длина, ширина и идентификатор класса, к которому принадлежит объект внутри прямоугольника) к каждому изображению.
Данные датасета COCO можно загрузить здесь. Изображения разбиты на выборки для обучения, тестирования и валидации моделей:
Изображения загружаются по левым ссылкам, разметка и информация об изображениях по соответствующим ссылками справа. Посмотрим, что из себя представляет разметка.
Для знакомства со структурой данным мы загрузили небольшую порцию изображения «2017 Val images» и соответствующую им разметку. В загруженном архиве содержатся 5000 совершенно различных изображений формата jpeg разного качества. В архиве с разметкой видим несколько JSON-файлов.
Нас будет интересовать файлы captions_val2017.json и instances_val2017.json. В этом блокноте мы десериализуем эти файлы, конвертируем их в формат DataFrame популярного пакета для работы с данными pandas и выполняем join нескольких датасетов для того, чтобы все нужные данные об изображении были в одной таблице. Итоговый результат выглядит следующим образом.
Названия столбцов очевидным образом отражают содержания ячеек. Для примера приведем одно изображения с нанесенным на него bounding boxes:
Конвертация разметки COCO в PascalVoc
Для дообучения нейронной сети из зоопарка TF необходима разметка изображений в формате Pascal Voc. Разметка изображения в формате Pascal Voc представляет из себя файл в формате xml со следующей структурой:
В начале xml расположены поля с информацией об изображении, в полях <object> расположены bounding boxes в таком же виде, как в датасете COCO (левая верхняя координата прямоугольника, длина, ширина). Нам необходимо было сконвертировать COCO разметку в xml файлы формата Pascal Voc. Велосипед изобретать не пришлось, мы воспользовались одним github проектом и получили требуемую xml разметку. Далее в точном соответствии с нашим видео мы дообучили нейронную сеть.
В следующей статье имплементация нейронной сети на Jetson Nano.