Как мы выиграли внутренний хакатон, выучив skibidi, flossing и javascript
В VK есть классная традиция — внутренний хакатон, в котором могут участвовать только ребята из ВКонтакте. Расскажу про хакатон от лица команды, которая в этом году заняла первое место и погибла от утомления в полном составе, но успела примерить детектор танцевальных движений для камеры историй.
Меня зовут Павел, я руковожу топ-командой исследований ВКонтакте и тепло отношусь к хакатонам: как участник (Junction или ряд deephack-ов) и в последнее время как куратор (хакатон VK или кейс ВКонтакте на Junction — между прочим, это был первый раз, когда там участвовала российская компания). Открытый для всех VK Hackathon мы проводим четвёртый год (последний раз забрались в Главный штаб Эрмитажа), и заметная часть нашей технической команды участвовала в нём до того, как устроились в VK.
Внутренний хакатон позволяет уже самой команде вдоволь поэкспериментировать над платформой, проверить разные идеи и вообще повеселиться. Важное отличие в том, что решения могут быть заметно сильнее интегрированы в VK, что даёт нам возможность добиться интересных прототипов.
Хакатон проходит в Доме Зингера целые сутки — прямо посреди недели Штаб превращается в полуночный движ. Забавно наблюдать, как удивлённо озираются по утрам уборщики — обычно пустой в 6 утра офис вдруг оказывается наполнен лохматыми людьми, которые передвигаются, как зомби, и кричат: «Осталось пять часов!» Или когда в три часа ночи заходишь на кухню, а там пахнет, как в университетских общежитиях во время сессий: энергетиками, пиццей и паникой. Так, конечно, бывает и в обычный день, но столь массово — редко.
Три предыдущих внутренних хакатона проходили летом. В 2019 году мы решили не мелочиться и провести ещё и зимний — два хакатона намного лучше, чем один, ведь это крутая возможность поэкспериментировать и реализовать идею, на которую в обычном ритме не хватает времени. Изменились и правила: раньше в команде могло быть максимум три человека, а в этом году — четверо, но один не пишет код, а специализируется в чём-то другом. Можно было звать в команду дизайнеров, продакт-менеджеров, тестировщиков, маркетологов и других ребят. Всего в этом хакатоне участвовали 38 команд.
Дримтим (точнее, одна из 38)
Мы сговорились с Даней и вместе убедили Егора и Тёму присоединиться к команде. Модельки ожидаемо были за нами, Егор отвечал за iOS, Тёма — за продакшн и дизайн. Мобильная разработка + дизайн + немного машинного обучения и бэкенда — залог успеха на хакатоне в 2k19.
Ещё в этом году появилось разделение на треки, которого раньше не было: Медиа (в котором мы участвовали), Коммуникации, Инфраструктура, Контент и Развлечения. У нас были мощные конкуренты. Например, нас постоянно мотивировал старший дизайнер VK Илья, который приходил в нашу комнату и показывал прототипы идеи своей команды.
Идея
— Я занимал призовые места почти во всех хакатонах, в которых участвовал, — и от внутреннего этой зимой ожидал того же. (Даня был уверен в себе)
Наша (а конкретно — Данина) идея изначально была такой: хотелось поисследовать тему генерации музыки + завести всё на устройстве, иначе «слишком бэкенд». Хакатон начали с брейнсторминга — размышляли, что же можно придумать. Генерация музыки — это интересно, но хочется сделать её зависимой от пользователя. Какие-то кнопки? Может быть, рисовать на экране и в зависимости от этого генерировать музыку? Параллельно у ребят из команды Музыки узнали, как добавить нужные нам треки. Но всё ещё казалось, что это не совсем то. Соседние команды бодро что-то фигачили за своими ноутами и вызывали фрустрацию.
— А что, если сделать распознавание air guitar, как будто играешь на гитаре, и в зависимости от этого проигрывать звук гитары? (Тёма)
Бинго! Идея боевая, и в наших силах классно всё устроить. Для распознавания движений есть posenet, и она очень ок (к тому же mobile-friendly). Фигачим!
Решение
Главные задачи — завести сетку на устройстве (должно быть реально) и научиться распознавать движения. Егор занялся портированием, Тёма — придумыванием, какие движения будет интересно вкрутить (только гитару — скучно), а мы с Даней — их распознаванием. Но для этого нужны данные. Чем отличается PRO от любителя? У PRO есть кластер с GPU — это раз, а два — PRO сам себе соберет данные, когда ему это нужно. Даня организовал стенд, где с камеры писались сырые данные координат распознанной фигуры, а дальше — танцы! Той ночью мы научились танцевать flossing, skibidi и дудца.
В качестве стенда для записи движений мы использовали рабочий ноутбук, который сначала записывал лицо Дани (до этого не писал на js ни строчки), когда он видел очередную непонятную js-ошибку.
— Я не понимаю, у меня ошибка уровня: в Питоне пропал print! (Даня)
Ночные танцы (literally)
Сняли ночью много часов непрерывного движа перед камерой. Записывали сами, а ещё ловили забредших на этаж разработчиков и ЗАСТАВЛЯЛИ ТАНЦЕВАТЬ. Получилось семь разных комбинаций — теперь нам нужно было научиться их различать.
— Заходила раз в три часа проверить, живы ли ребята. Паша кричал: «У нас пивот!» — а Даня флексил из последних сил. Потом все танцевали дудца. Когда у Даниила заканчивались силы, Паша открывал окно и говорил: «Пацаны, надо освежиться». (Мадина)
Данные с фигуры предобработали: выкинули ноги, усреднили голову, перевели в полярные координаты относительно торса. Обучали детектор движений с помощью catboost — по трёхсекундному отрывку потока данных с модели. До этой ночи с библиотекой не работали — оказалась боевой, и в iOS засунуть можно.
Обучали мультиклассовую классификацию, при этом один класс был максимально скучным — просто шатание перед камерой. Самым трудным было записать движение «rock» — мы так самоотверженно трясли головой, что через какое-то время она начинала кружиться. И выставляли руку с «козой», хотя это было бессмысленно — у posenet только одна точка на целую кисть, пальцы она не видит.
— Где-то в 3 утра Паша залез в спальный мешок и час передвигался исключительно в нём, прыгая, как заправский кенгуру. (Мадина)
В районе 8 утра нас настиг небольшой кризис — всё сломалось и ничего не работало, но потом всё внезапно само заработало. Вкрутить обе модели в приложение оказалось самым большим челленджем — Егор закончил сборку буквально за пять минут до дедлайна. Дадим ему слово:
— После того как мы нашли идею, всё шло очень хорошо и продуктивно. Ребята тренировали сетку и танцевали, а я прикручивал к камере историй PoseNet на JavaScript прямо в браузере. Первичные тестовые запуски работали хорошо и на удивление быстро. Поэтому, когда к утру выяснилось, что WebGL в WebView неожиданно падает при работе с текстурами на какой-то ерунде и решения никак не найти, я почти впал в отчаяние. Но сдаваться было уже поздно: мы горели идеей. Поэтому из последних сил и на последней банке редбулла на ходу затащили в iOS-клиент альтернативную модель на CoreML и стали трекать позы уже нативно — чтобы далее отдавать их в модель с танцами и на выходе из них получать какой-то результат. По сути, мы повторили работу заново! Ещё одним вызовом стала вторая модель, которая внезапно стала ожидать на вход больше тысячи аргументов! Xcode сгенерировал для неё интерфейс, который просто нереально было бы использовать «в лоб». Благо знания Objective-C не подвели, и было найдено изящное решение. (Егор)
Питчинг
В пятницу в 14 часов железно нужно было загрузить видео про проект — несколько команд не успели, и их дисквалифицировали. А в 14:40 у нас был питч перед кураторами трека, имеющими отношение к продукту. У нас были ребята из команды Видео и Музыки, и, кажется, им на питче всё понравилось. В своём треке мы заняли второе место (хотели первое, ведь у нас такой классный проект!) и оказались в финале (из нашего трека проходили две команды).
— В этом году я впервые был куратором внутреннего хакатона. Скажу сдержанно: оценивать работы было крайне тяжело. Уровень всех без исключения команд был какой-то запредельный. Фича должна быть не просто технологичной, не просто «близкой к продакшену», не просто «потенциально полезной нашим продуктам». Необходимо, чтобы проект-победитель соответствовал всем этим критериям одновременно. Кажется, у ребят это получилось. (Андрей)
Финальный питчинг у нас был в 17:40. К этому времени нужно было подготовить ещё одно демо, уже для всей Команды, и жюри было другое — технический директор, директор по продукту и директор по маркетингу.
В пять вечера всё закончилось — погнали домой спать, ничего не зная о результатах.
Результаты, наконец
Результаты объявили только в понедельник. Сначала наградили победителей треков (не наш случай — напомню, мы были вторыми), потом и лидеров зрительского голосования (не нас), а потом третьих (и это тоже не мы), вторых (снова не мы) и, наконец, нас.
Вот с какими проектами нам пришлось соревноваться:
2 место — отзывчивый голосовой помощник;
3 место — таймлайн внутренних ошибок;
Приз зрительских симпатий — напоминалка о предстоящих встречах для чатов.
— Это лучший хакатон из тех, где я участвовал. Драйва было намного больше, чем даже на Junction. (Даня)
— Мне очень понравилось работать с коллегами из совершенного другого отдела — раньше я никогда не прикасался к машинному обучению, оно казалось мне какой-то магией, но теперь это не так. (Егор)
— Было очень круто стать частью такой клёвой команды с таким клёвым проектом. За сутки я успел побыть дизайнером, видеооператором, звукорежиссёром, монтажёром, музыкантом и копирайтером! А ещё мне единственному удалось поспать. (Тёма)
Жизнь после хакатона
Большинство проектов, разработанных на хакатонах, не добираются до прода по разным причинам: смена фокуса, сложность внедрения, что-то непредусмотренное в реализации. Внутренний хакатон — не исключение.
Тем не менее перечислим проекты, которые увидели свет: