Глубоко внутри множества функций и инструментов TensorFlow находится компонент под названием TensorFlow Object Detection API. Цель этой библиотеки, как следует из названия, - обучить нейронную сеть, способную распознавать объекты в кадре, например изображение.

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

Цель этой статьи - описать шаги, которые я выполнил для обучения моей собственной модели обнаружения объектов - и продемонстрировать мои навыки обнаружения Пикачу - чтобы вы могли попробовать ее самостоятельно. Во-первых, я начну с введения в пакет, резюмируя некоторые детали, описанные в исходной статье. Во-вторых, я продолжу рассказ о том, как преобразовал свои изображения Пикачу в правильный формат и создал набор данных. После этого я напишу как можно подробнее о процессе обучения и о том, как его оценить, а также о окончательной модели с использованием веб-интерфейса Tensorflow, TensorBoard. Наконец, я продемонстрирую, как использовать модель в записной книжке Python и как экспортировать ее в Android.

Код, который я использовал для этого проекта, доступен на моем Github (juandes / pikachu-detection). Все сценарии, упомянутые в этом документе, должны быть там доступны.

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

API обнаружения объектов Tensorflow

Этот пакет является ответом TensorFlow на проблему обнаружения объектов, то есть процесс обнаружения объектов реального мира (или Пикачу) в кадре. Согласно документации и бумаге, которая знакомит с библиотекой, уникальность библиотеки заключается в том, что она способна менять точность на скорость и использование памяти (также наоборот), поэтому вы можете адаптировать модель в соответствии со своими потребностями и платформой. на выбор, например телефон. Библиотека включает множество готовых архитектур обнаружения объектов, таких как SSD (детектор одиночного выстрела), Faster R-CNN (сверточная нейронная сеть на основе более быстрой области). и R-FCN (полностью сверточные сети на основе регионов), а также несколько экстракторов функций, таких как MobileNet, Inception, Resnet ; Эти экстракторы действительно важны, потому что они играют огромную роль в соотношении скорости и производительности системы.

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

Теперь, когда мы немного знаем о системе, использованной в этом эксперименте, я перейду к объяснению, как вы можете построить свою собственную модель.

Создание вашей собственной пользовательской модели

Установка

Прежде чем мы начнем, убедитесь, что на вашем компьютере установлен TensorFlow. В противном случае см. Инструкции здесь о том, как его установить. Затем клонируйте репозиторий, в который включен API обнаружения объектов. Это ссылка: https://github.com/tensorflow/models.

После клонирования репозитория перейдите в каталог «research» и выполните:

# From tensorflow/models/research/
protoc object_detection/protos/*.proto --python_out=.

Это скомпилирует библиотеки Protobuf. Если у вас не установлен Protobuf, вы можете скачать его отсюда: https://developers.google.com/protocol-buffers/docs/downloads

Наконец, вам нужно добавить библиотеки в PYTHONPATH. Это можно сделать, выполнив:

# From tensorflow/models/research/
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim

Для получения дополнительных сведений обо всех необходимых зависимостях см. Официальную документацию, доступную здесь: https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/installation.md

Теперь давайте посмотрим, как я перешел от множества изображений Пикачу к красивому и аккуратному набору данных, доступному для чтения TensorFlow.

Создание набора данных и обработка изображений

Создание набора данных - это первый из многих шагов, необходимых для успешного обучения модели, и в этом разделе я рассмотрю все шаги, необходимые для этого.

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

После того, как вы получили все изображения, следующим шагом будет их маркировка. Что это значит? Поскольку мы выполняем обнаружение объектов, нам нужна достоверная информация о том, что именно представляет собой объект. Для этого нам нужно нарисовать ограничивающую рамку вокруг объекта, чтобы система знала, что эта вещь внутри рамки - это реальный объект, который мы хотим изучить. Программное обеспечение, которое я использовал для этой задачи, представляет собой приложение для Mac под названием RectLabel.

Вот так выглядит изображение с ограничивающей рамкой:

В RectLabel вам нужно установить метку для каждого ограничивающего прямоугольника вашего изображения, в моем случае это метка «Пикачу». После того, как вы пометили все изображения, вы заметите, что у вас есть один каталог с именем «аннотации» со множеством файлов XML, описывающих ограничивающую рамку каждого изображения.

Разделить на набор данных для обучения и тестирования

После того, как все изображения были помечены, моим следующим шагом было разделение набора данных на набор данных для поезда и тестирования. Внутри того же каталога, где находятся изображения, я создал каталог с именами «train» и «test» и добавил около 70% изображений и их соответствующий XML-код в обучающую программу. каталог, а оставшиеся 30% - в тестовый каталог.

Создать TFRECORD

После разделения набора данных единственное, чего не хватает, - это преобразовать наши изображения и их XML в формат, доступный для чтения TensorFlow. Указанный формат называется tfrecord, и для его создания из наших изображений необходимо выполнить два шага. Во-первых, для простоты данные из обоих наборов XML (обучение и тестирование) были преобразованы в два файла CSV (опять же, обучение и тестирование) с использованием модифицированной версии кода xml_to_csv.py, представленного на GitHub datitran ( https://github.com/datitran/raccoon_dataset ). Затем с использованием файлов CSV создается набор данных tfrecord с использованием сценария generate_tfrecord.py (также из datitran’s). Помните, что перед запуском скрипта вы должны указать класс ваших объектов в функции class_text_to_int.

* РЕДАКТИРОВАТЬ (23.01.17): Уилл Брикнер сообщил, что xml_to_csv.py не работает должным образом с последней версией RectLabel, и он написал новый сценарий, более надежный. . Он доступен здесь: https://gist.github.com/wbrickner/efedf8ab0ce1705de1372c1e2f49dd98 Большое спасибо :)

Создание карты надписей

Требуется карта «подписи» с указанием надписей и их индексов. Вот как они выглядят.

item {
  id: 1
  name: 'Pikachu'
}

Замените метку «Пикачу» на свою и, что важно, всегда начинайте с индекса 1, потому что 0 зарезервирован. Я сохранил этот файл как object-detection.pbtxt в новом каталоге с именем «обучение».

Обучение модели

Трубопровод

Полный процесс обучения обрабатывается конфигурационным файлом, известным как pipeline. Указанный конвейер разделен на пять основных структур, которые отвечают за определение модели, параметры процесса обучения и оценки, а также входные данные набора данных для обучения и оценки. Каркас трубопровода выглядит так:

model {
(... Add model config here...)
}

train_config : {
(... Add train_config here...)
}

train_input_reader: {
(... Add train_input configuration here...)
}

eval_config: {
}

eval_input_reader: {
(... Add eval_input configuration here...)
}

Но! Вам не нужно писать весь конвейер с нуля. Фактически, разработчики TensorFlow рекомендуют, чтобы в процессе обучения использовалась одна из их собственных и уже обученных моделей в качестве отправной точки. Причина в том, что обучение совершенно новой модели с нуля может занять много времени. Таким образом, TensorFlow предоставляет несколько файлов конфигурации, которые требуют минимального количества изменений, чтобы заставить его работать в новой среде обучения. Модель, которую я использовал, была ssd_mobilenet_v1_cocossd_mobilenet_v1_pets.config06_2017 найдена здесь.

Для своего обучения я использовал конфигурационный файл ssd_mobilenet_v1_pets.config в качестве отправной точки. Изменения, которые я сделал, касались переменной num_classes, поскольку у меня всего один класс, num_steps, чтобы остановить обучение раньше, fine_tune_checkpoint, чтобы указать местоположение загруженной модели, и переменные input_path и label_map_path train_input_reader и eval_input_reader, чтобы указать на набор обучающих и тестовых данных и карта меток.

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

SSD, что означает Single Shot Detector, представляет собой архитектуру нейронной сети, основанную на единой сверточной нейронной сети с прямой связью. Он называется «одиночный снимок», потому что он предсказывает класс изображения и положение прямоугольника, представляющего обнаружение (известного как привязка) на одном и том же этапе. Противоположность этому - архитектура, требующая второго компонента, известного как «генератор предложений», для прогнозирования точного положения коробки.

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

Когда у вас будет готовый конвейер, добавьте его в каталог «training». Затем приступайте к обучению с помощью следующей команды:

python object_detection/train.py --logtostderr 
--train_dir=path/to/training/ 
--pipeline_config_path=path/to/training/ssd_mobilenet_v1_pets.config

Оценка модели во время и после обучения

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

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

python object_detection/eval.py --logtostderr 
--train_dir=path/to/training/ 
--pipeline_config_path=path/to/training/ssd_mobilenet_v1_pets.config 
--checkpoint_dir=path/to/training/ --eval_dir=path/to/training/

TensorBoard

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

Чтобы запустить TensorBoard, выполните следующую команду:

tensorboard --logdir=path/to/training/

Экспорт модели

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

Перед экспортом убедитесь, что у вас есть следующие файлы в каталоге обучения:

model.ckpt-${CHECKPOINT_NUMBER}.data-00000-of-00001,
model.ckpt-${CHECKPOINT_NUMBER}.index
model.ckpt-${CHECKPOINT_NUMBER}.meta

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

python object_detection/export_inference_graph.py                   --input_type image_tensor                                           --pipeline_config_path=path/to/training/ssd_mobilenet_v1_pets.config --trained_checkpoint_prefix=path/to/training/model.ckpt-xxxxx       --output_directory path/to/output/directory

Результатом будет файл, содержащий «замороженную» версию модели с именем frozen_inference_graph.pb.

Полученные результаты

В конце фазы обучения точность модели составила 87% с общей потерей 0,67. Однако во время обучения модель достигла максимальной точности 95%. Тем не менее, модель с высочайшей точностью оказалась не так хороша, как я ожидал. Например, он классифицировал многие желтые объекты (даже некоторых людей) как Пикачу. С другой стороны, я заметил, что модель с точностью 87% дает меньше ложных срабатываний за счет пропуска некоторых Пикачу. На изображениях ниже показан график общих потерь и точности, созданный TensorBoard.

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

В пакет обнаружения изображений входит блокнот для тестирования одной из предварительно обученных моделей, которые предоставляет TensorFlow. Тем не менее, этот блокнот можно изменить для работы с замороженной версией (той, которую мы экспортировали) специально обученной модели, что я и сделал. Ниже вы можете увидеть некоторые из обнаружений, выполненных в записной книжке.

Обнаружение Пикачу в Android

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

Перейдем к разделу Android TensorFlow. Во-первых, вам необходимо скачать Android Studio. Получив его, клонируйте репозиторий TensorFlow (который у вас уже может быть) и в Android Studio импортируйте новый проект, используя каталог из репозитория TensorFlow, который вы только что клонировали, под названием Android ». В качестве дополнительного примечания я также рекомендую просмотреть README, чтобы немного познакомиться с библиотекой.

README рекомендует сохранить сборку как самую простую и предлагает изменить nativeBuildSystem переменную сборки Gradle на none, однако я изменил ее на cmake, чтобы построить ее (ни одна из других альтернатив сборки, таких как Bazel и Makefile, у меня не сработала) .

Когда сборка будет завершена, следующим шагом будет добавление замороженной модели в каталог ресурсов. Затем также в этой папке создайте файл с именем «label» и в первой строке напишите ??? (помните, когда я сказал, что первый класс зарезервирован?), А во второй строке напишите метку вашего объекта (в моем случае я написал Pikachu).

Затем откройте файл с именем «DetectionActitivity.java», расположенный в каталоге «java»; это код, используемый приложением для обнаружения. Найдите переменную TF_OD_API_MODEL_FILE и TF_OD_API_LABELS_FILE и в первой измените ее значение на путь к замороженной модели, находящейся в папке с ресурсами, а во второй запишите путь к файлу с метками. Еще одна полезная переменная, о которой вы должны знать, - это MINIMUM_CONFIDENCE_TF_OD_API, которая представляет собой минимальную достоверность, необходимую для отслеживания обнаружения. Попробуйте поиграть с этим!

Готово! Нажмите кнопку запустить, выберите свое устройство Android и подождите пару секунд, пока приложение не будет установлено на телефоне. Важная деталь: на телефон будет установлено не одно, а четыре приложения, однако, мы используем модель обнаружения TF Detect. Если все прошло нормально и приложение запустилось, найдите несколько изображений вашего объекта и посмотрите, может ли модель их обнаружить.

Вот и все! Удачного обнаружения :)

Вот некоторые из обнаружений, которые я сделал на своем телефоне.

РЕДАКТИРОВАТЬ (05.06.2018): продолжение этой работы, обнаружение Пикачу на видео, доступно здесь:



Заключение и резюме

В этой статье я объяснил все необходимые шаги для обучения пользовательской модели с помощью библиотеки обнаружения объектов TensorFlow. Вначале я дал небольшую справочную информацию о библиотеке и о том, как она работает, а затем дал руководство о том, как маркировать и обрабатывать, а также изображения для создания набора данных. После этого я сосредоточился на том, как проводить обучение. В этом разделе я рассказал о конвейере обучения, о том, как оценивать модель с помощью TensorBoard. Затем, когда обучение было завершено, я выполнил процедуру экспорта модели и импорта в записную книжку Python и Android.

Самым сложным в этом проекте было заставить модель работать на Android. Без преувеличения, это заняло у меня около месяца, потому что я получал массу ошибок (я даже открыл проблему на Github), и я почти сдался. Для меня проблему решило изменение в файле export.py (вызываемом export_inference_graph.py) параметра optimize_graph на False. По-видимому, насколько я понял, оптимизируя модель, моя модель создавала некоторые узлы, не распознаваемые библиотекой Android, и, таким образом, она давала сбой. Я не говорю, что это решение, но вы могли бы попробовать его, если оно вам не подходит. Я рекомендую не сдаваться и продолжать попытки, чтобы вы могли произвести впечатление на своих друзей с помощью собственной системы обнаружения.

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