Как я создал задачу компьютерного зрения на основе конечной точки REST с помощью Flask

Это продолжение моего процесса знакомства с компьютерным зрением и методами машинного обучения. Как веб-разработчик (читается как разработчик рельсов) я нашел эту растущую сферу захватывающей, но не работаю с этими технологиями изо дня в день. Это третий месяц из двухлетнего путешествия по изучению этой области. Если вы еще не читали, вы можете увидеть Часть 1 здесь: От веб-разработки до компьютерного зрения и географии и Часть 2 здесь: Два месяца изучения глубокого обучения и компьютерного зрения.

Общие мысли

Разработчики на Rails умеют быстро создавать веб-приложения с минимальными усилиями. Благодаря каркасам, понятной логике модель-представление-контроллер и множеству рубиновых жемчужин, имеющихся в вашем распоряжении, приложения Rails со сложной логикой могут быть развернуты за короткое время. Например, я бы не стал моргать при создании чего-то, что требует учетных записей пользователей, загрузки файлов и различных каналов данных. Я мог бы даже сделать его хорошо тестируемым с отличной документацией. Между Devise, Carrierwave (или многими другими драгоценными камнями для загрузки файлов), Sidekiq и всеми другими доступными гемами я бы начал работать на Heroku в течение 15 минут.

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

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

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

Я начал выстраивать простую часть проекта, понимая, что мне нужно «натренировать» свою «модель» на хорошем граффити. Я выбрал несколько аккаунтов в Instagram хороших художников-граффити, где я знал, что могу найти изображения высокого качества. После сканирования учетных записей Instagram (что заняло намного больше времени, чем ожидалось из-за ограничений API Instagram) и анализа изображений, я понял, что это большая проблема. Выбранные аккаунты были отличными, но в них было много изображений без граффити, в основном людей. Чтобы получить «хорошие граффити» изображения, мне сначала нужно было отфильтровать изображения людей.

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

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

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

Приложение (со ссылками на код)

Я использовал Ruby on Rails для веб-приложений, которые управляли базой данных и отображали контент. Я выполнял большую часть сканирования изображений Instagram с помощью Ruby через библиотеку Redis под названием Sidekiq. Это упрощает выполнение отложенных задач.

Для логики машинного обучения у меня был пример кода для обнаружения объектов с использованием OpenCV из учебника PyImageSearch.com. Пример кода был неполным, поскольку он обнаружил один из 30 различных элементов в модели обученного изображения, одним из которых были люди, и нарисовал рамку вокруг обнаруженного объекта. В моем случае я немного изменил пример и поместил его в простое веб-приложение на основе Flask.

Я создал приложение Flask с конечной точкой, которая принимает большой двоичный объект JSON с URL-адресом изображения. Приложение загрузило URL-адрес изображения и обработало его с помощью примера кода, который нарисовал ограничивающую рамку вокруг обнаруженного объекта. Меня интересовал только пример кода, обнаруживающий людей, поэтому я создал базовое условие, чтобы дать определенный ответ для обнаружения человека и общий ответ для всего остального.

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

Для тех, кому интересно, код для них ниже.



Заключительные реализации

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

Изучив, как получить доступ к логике обнаружения объектов, я нашел несколько сервисов, которые казались важными, но в конечном итоге оказались не совсем тем, что мне было нужно. В частности, есть инструмент под названием Tensorflow Serving, который, кажется, должен быть простым веб-сервером для Tensorflow, но не совсем прост. Возможно, это то, что мне нужно, но идея иметь сервер или веб-приложение, которое запускает только Tensorflow, довольно сложно настроить.

Машинное обучение на основе веб-сервисов

Многие примеры машинного обучения, которые я нахожу в Интернете, очень замкнуты. Примеры начинаются с проблемы, затем предоставляется код для локального запуска примера. Часто изображение - это входные данные, предоставляемые путем пути к файлу через интерфейс командной строки, а выходными данными является окно, сгенерированное python, которое отображает измененное изображение. Это не очень полезно в качестве веб-приложения, поэтому создание конечной точки REST кажется основным следующим шагом.

Встраивать логику машинного обучения в конечную точку REST несложно, но есть некоторые моменты, которые следует учитывать. В моем случае сервер работал на настольном компьютере с достаточным количеством ЦП и памяти для быстрой обработки запросов. Это может быть не всегда так, поэтому будущей конечной точке может потребоваться асинхронный запуск задач с использованием чего-то вроде Redis. HTTP-запрос здесь, скорее всего, зависнет и, возможно, истечет время ожидания, поэтому для медленных запросов необходимо учитывать некоторую базовую логику микросервисов.

Бинарные ожидания и бренды машинного обучения

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

Веб-приложениям требуются бинарные заключения, чтобы действовать. Классификатор изображений предоставит процентную оценку того, присутствует ли обнаруженный объект. В моделях обнаружения более крупных объектов классификатор будет иметь более одного объекта, рекомендованного как потенциально обнаруживаемый. Например, вероятность присутствия человека на фотографии составляет 90%, вероятность самолета - 76% и вероятность гигантского банана - 43%. Это не очень полезно, когда приложение, обрабатывающее ответы, просто должно знать, присутствует ли что-то.

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

Напротив, поскольку качество задач машинного обучения сильно различается, бренду может быть сложно продемонстрировать свою ценность для пользователя. Когда двоичное качество решения задачи машинного обучения привязано к сумме в долларах, например, за запрос API, возможность делать что-то бесплатно будет привлекательной. С точки зрения цены, развернуть собственный бесплатный классификатор объектов будет лучше, чем использовать сторонний сервис. Рынку фирменных услуг машинного обучения еще предстоит пройти долгий путь, прежде чем он станет явно предпочтительным по сравнению с автономными реализациями.

Специфика классификации объектов очень важна

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

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

Финальный финал

В целом приложение работает и было очень полезно. Это позволило избавиться от тайны того, как работают сервисы машинного обучения и распознавания изображений. Как я отмечал выше, этот процесс также сделал меня более осведомленным о недостатках этих услуг и местах, где эта область еще не определена. Я определенно думаю, что это то, чему должны научиться все программисты. Я полагаю, что до того, как доступные инструменты станут простыми в использовании, будет хороший период сложной экосистемы для навигации. Подобно войнам браузеров до того, как были сформированы веб-стандарты, между поставщиками машинного обучения будет много соперничества за долю рынка. Вы уже можете увидеть это в сервисах крупных компаний, таких как Amazon, Google и Apple. На аппаратном и программном уровне это также очень очевидно между CUDA от Nvidia и ценовой привлекательностью AMD.

Еще не все!