Берись и делай: почему иногда полезно забить на анализ и просто разрабатывать

DesignWrites
Aug 31, 2018 · 7 min read

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

Еще пару лет назад, когда к нам приходили запросы от пользователей на разработку чего-то новенького (не входящего в генеральный план развития продукта), мы долго прогнозировали сроки, оценивали универсальность и востребованность функции у широкого круга пользователей. И часто либо отказывали, либо оценивали сроки реализации как очень долгие. Но однажды нам пришел запрос для крупного проекта. В случае успешной и быстрой реализации недостающей пользователю функции, перспективы и масштабы внедрения Macroscop были очень хорошими. И мы взялись попробовать! У нас были жесткие временные рамки, отзывчивый и готовый помогать пользователь и полная свобода действий.

И… все получилось!

Мы сделали новую функцию в короткий срок. К тому же она была точной и быстрой. Все остались довольны: пользователь получил заветный интеллектуальный модуль, разработчики получили крутой опыт, компания — продажи.
Эта практика положила начало новому подходу к разработке интеллектуальных функций в Macroscop: мы стали чаще и легче идти навстречу своим пользователям. И это дает свои результаты.

Самое важное — выявить реальную потребность пользователя и вместе с ним четко сформулировать задачу. Когда речь идет о быстрой разработке функций «на заказ» (дальше мы будем называть их быстрыми функциями), надо обязательно оговаривать требования: что пользователь хочет видеть в итоге, на что делать акценты. Потому что, условно, одним надо, чтобы в первую очередь точно работало, другим — чтобы круто выглядело. Когда мы беремся за быструю функцию, речь не идет о том, что в итоге она будет работать в любых условиях с 100%- точностью. Мы беремся проверить саму идею и пробуем создать для начала что-то адекватно работающее и приемлемое для использования на одном конкретном объекте. А уже потом в случае успеха дорабатываем и доводим до универсального продукта с хорошими показателями.

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

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

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

Ты помнишь, как все начиналось?.. (с)

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

в таком ракурсе модуль Macroscop считать умел

а в таком — научился

Ему всем нравился Macroscop, но не хватало заветной функции. Проект был очень перспективным, а пользователь готов был всячески с нами сотрудничать, лишь бы такой модуль появился, и ПО можно было установить на объект. Мы решили не упускать возможность, и приступили к разработке.

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

Группа разработки интеллектуальных функций разделилась на 3 подгруппы, и каждая стала пробовать свой метод. Все они были основаны на применении нейросетей.
Первая — пробовала перенести в модуль для подсчета людей в очередях инфраструктору разработанного нами детектора отсутствия касок (см. Статью о том, как мы попробовали применить современные нейросетевые технологии, чтобы находить каски на головах людей). Этот подход казался очень логичным: детектор касок на определённом этапе работы решает схожую задачу.

Вторая группа пробовала применить регрессионную нейросеть. Она считает количество людей на изображении, но при этом не выделяет конкретные объекты, из-за чего её сложно контролировать. При обучении на регрессионную нейросеть подается картинка и указывается количество человек, которые на ней присутствуют, а нейросеть выдает одно число — сколько человек она нашла. Наполняя выборку новыми изображениями, мы стремились обучить ее считать правильно.

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

Третья группа тестировала один достаточно известный детектор общего назначения, который умеет детектировать разнообразные объекты в режиме реального времени. Он умеет искать тысячу видов разных объектов, но не решать нашу задачу со всеми ее особенностями. Мы доработали этот детектор, обучили его на собственноручно созданной обширной выборке и получили вполне неплохой результат — счетчик людей с приемлемой точностью. Новыми выборками улучшили еще, и в итоге получили прототип, который уже было нестыдно отдать пользователю на тест. И его оценка была… положительной! Он сказал, что в целом решение уже конкурентоспособное, однако точность еще не была высокой — всего 60–70%.

Первая версия счетчика людей в очереди была создана преимущественно с использованием роликов от этого пользователя. Мы решали задачу — чтобы заработало конкретно у него,- но понимали, если обучим нейросеть и сделаем модуль под один конкретный проект, ни о каком дальнейшем масштабировании не может быть речи. Поэтому далее обучение велось на более универсальной выборке, что привело к росту точности даже без глобальных внутренних доработок. Затем мы стали работать над упаковкой модуля — улучшили интерфейс, прикрутили разные настройки, обратили внимание на удобство использования и логику. Параллельно исправили ряд багов в нашем прототипе (кстати, один из них неожиданно ускорил работу модуля в 7 раз), придумали, как снизить потребление ресурсов процессора, подключили работу на видеокарте. В итоге получили объективно хорошо работающий и удобный в управлении модуль, который анализировал быстро, выдавал точные результаты, умел работать на видеокарте, не загружая при этом процессор.
Наш пользователь был просто счастлив! Он поехал ставить новую версию в свои магазины, и подтвердил, что на практике все отлично работает. Нам удалось достичь 85–90%-точности (для ситуаций, когда люди в очереди не перекрывают друг друга полностью, и их можно различить).

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

Хеппи энд

Сейчас применение модуля подсчета людей в очереди новой версии расширяется на другие магазины этого пользователя. А финальный вариант — ушел в продакшн и вошел в версию Macroscop, которая готовится к релизу. Кстати, пользователю настолько понравился результат и в целом способ работы, что поступил еще один запрос — сделать детектор пустых полок. И мы снова взялись, и снова сделали (но это уже совсем другая история).

Если подводить какой-то итог, то для сравнения: разработка и доработка старой версии модуля подсчета людей в очереди (4 года назад) заняла около 8 месяцев. Новый модуль мы сделали за 2 месяца (причем первый рабочий прототип передали пользователю уже через 2–3 недели).

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

В любом случае, для себя мы вывели несколько правил, соблюдение которых — половина успеха разработки быстрых функций:

  • Попробовать пойти навстречу пользователю, но не забывать о собственных целях: браться за проекты, которые можно масштабировать, вкладывать силы в то, что будет полезно в долгосрочной перспективе.
  • Докопаться до истинных задач и потребностей пользователя, выявить приоритеты.
  • Заручиться поддержкой пользователя. Если он готов активно коммуницировать, тестировать, давать обратную связь и предоставлять необходимые данные (видео с реального объекта, например), то есть все шансы разработать хорошо и быстро.
  • Не бояться провала и относиться к нему как к одному из возможных результатов.
  • Не стремиться разработать что-то уникальное с нуля, а по возможности использовать существующий опыт: в нашем случае пытаться применять части алгоритмов из уже реализованных модулей. А уже если получившееся решение окажется жизнеспособным — уделять время исследованиям и кастомизации.

Источник

    DesignWrites

    Written by

    Наш Телеграмм канал: https://t.me/designwrite

    Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
    Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
    Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade