Хабрахабр

Как программист датасаентистам кернелы писал

Стек Одноклассников формировался долгие годы, в первую очередь программистами, перешедшими в data science, но всё ещё остались близкими к проду, поэтому в его основе лежат открытые технологии JVM-стека: Hadoop, Spark, Kafka, Cassandra и т.д. Мало кто верит, что современный data science-стек может быть построен не на Python, но такие прецеденты есть :). Например, при подготовке базовых решений для участников SNA Hackathon 2019 пришлось сжать волю в кулак и погрузиться в мир динамической типизации. Это помогает нам сокращать время и затраты на ввод моделей в эксплуатацию, но иногда создаёт и сложности. Подробности (и лёгкий троллинг) под катом 🙂

Установка

Нашёлся он и на моей, аж в двух экземплярах — 2. Какой-то питон найдётся почти на любой девелоперской машине. 4. 7 и 3. 4 поставил три года назад, после того, как на SNA Hackathon 2016 участники столкнулись с эпичными проблемами, пытаясь разложить в памяти полуторагигабайтный граф (по итогам получилось небольшое обучающее видео и отдельное соревнование), но сегодня это хозяйство уже морально устарело и нуждалось в обновлении. Порывшись в закромах памяти я вспомнил, что версию 3.

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

Проекта как такового нет, но есть «окружение», и в рамках каждого окружения можно сформировать независимую экосистему из пакетов определённых версий. Что с этим в питоне? Но взаимные конфликты версий пакетов никуда не денутся.Я сразу же столкнулся с тем, что релиз Pandas 0. При этом есть и инструменты для ленивых, с помощью которых локальным питоновским окружением управлять не сложнее, чем распределённым гетерогенным кластером Клаудеры или Хортона. Но в итоге удалось всё починить, не считая страшных варнингов о новых деприкейшинах, заработало. 24 перевёл приватный метод _maybe_box_datetimelike в публичный API, и неожиданно оказалось, что много кто его в прежнем виде юзал и теперь отвалился 🙂 (и да, в мире Явы все то же самое).

Коллаборативный baseline

image

Начнём с логов (спойлер — мегапаттерн Cmd+C/Cmd+V со стэковерфлоу работает и с питоном). Задачи на SNA Hackathon 2019 разделены на три направления — рекомендации по логам, по текстам и по картинкам. Задача piece of cake: берём признаки, пихаем в логрег, профит! Данные были собраны с живого продакшина — каждому пользователю случайным образом, без взвешивания, показывался некоторый фид из его окружения, после чего в лог записывались все признаки на момент показа и итоговая реакция.

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

Jupyter, в целом, порадовал, он почти такой же удобный, хоть и не такой няшный, как Zeppelin. Но были и положительные стороны. Ну и скорость логистической регрессии на небольшом куске данных в памяти порадовала — до мощности распределённого варианта не дотягивает, но на четырёх признаках и паре сотен тысяч примеров учится мгновенно. Даже скала-ядро есть!

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

К слову, именно из-за этой особенности я всегда удивляюсь пользователям pySpark — ведь почти вся стандартная функциональность доступна в виде Spark SQL, который одинаков и в питоне, и в скале, а после появления первой питонячей юдф-ины с чем-то личным десятитысячеядерный кластер превращается в тыкву…

65 хватило девяти параграфов! Но, в итоге, все препятствия преодолены и для score 0.

Текстовый baseline

К счастью, тексты уже идут не только в сыром виде, но и обработанные нашей штатной системой препроцессинга на базе спарка и Lucene. Ну вот, теперь у нас задача посложнее — если логрег можно найти в сотне реализаций под все платформы, то уж разнообразие инструментов работы с текстами под питоном больше. Поэтому можно сразу брать список токенов и не париться токенизацией/лематизацией/стемингом.

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

Но, как обычно, сразу начались проблемы. У нас опять простой план: берём все тексты из теста, обучаем модель Doc2Vec, далее инферим её на трэйне и на её результатах учим логрег (стэкинг — наше всё!). Пришлось есть слона по частям. Несмотря на относительно скромный объём текстов в обучающей выборке (всего полтора гига), при попытке втянуть их в пандас питон отожрал 20 (20, Карл!) гигабайтов памяти, ушел в своп и не вернулся.

Это экономит её использование вдвое, документы тестового множества грузятся в память для обучения без проблем. При чтении всегда указываем, какие именно колонки поднять из паркета, что позволяет не читать сырой текст в память. Далее в загруженном файле оставляем только ID из тех дней, которые хотим использовать для обучения, и уже на них инферим эмбединги. С обучающей выборкой такого трюка мало, поэтому за раз прогружаем не более одного «паркетного» файла.

54 🙂 Логрег поверх этого работает так же быстро, и в итоге получаем 14 параграфов и score 0.

Картиночный baseline

Только котики! Что может быть популярнее deep learning? Поэтому для картиночного baseline-а мы составили гениально простой план: прогоняем на картинках из тестового множества детектор котиков, а потом ранжируем контент по полученному score 🙂

Классификация или детекция? И опять есть из чего выбирать. Главный критерий — простота реализации методом копипаста. pyTorch или Tensorflow? Лаконичность их демки пленила с первого взгляда, но потом, как обычно, начались проблемы. And the winner is… YOLOv3 на MXNet :).

С оценки производительности и необходимого машинного времени! С чего обычно начинается работа с большими данными? Добавляем загрузку и предобработку фоток — 100 в секунду, примерно час на всё, норм. Хотелось сделать baseline максимально автономным, поэтому научили его работать напрямую с tar-файлом и быстро поняли, что при скорости извлечения из tar в tmpfs 200 фото в секунду на обработку 352 758 картинок понадобится порядка получаса, норм. Добавляем вычисление нейросетки — 20 фоток в секунду, 5 часов, нуууу ок… Добавляем извлечение результата — 1 фотка в секунду, неделя, WTF?

Бинго! После пары часов танцев с бубнами приходит понимание, что NDArray, который мы наблюдаем, это ни разу ни numpy, а внутренняя структура MXNet-а, который проводит все вычисления лениво. Любой начинающий диплернер знает, что всё дело в размере батча! Что же делать? И да, после добавления батчинга со скоростью 10 фото в секунду удалось найти всех котиков :). Если MXNet вычисляет score лениво, то если мы сначала запросим их для пары десятков фото, а потом начнём их извлекать, то, быть может, обработка фоток пойдёт батчем?

504 :). Дальше применяем уже известную машинерию и за 10 параграфов получаем score 0.

Выводы

К примерно таким же выводам нас привёл и этот эксперимент: нет и не может быть идеального языка на все случаи жизни. Когда одного мудрого сэнсея спросили «Кто победит, мастер по айкидо или по карате?», он ответил «Победит мастер». В Java и Scala вы тоже можете найти много готовых инструментов и легко реализуете собственные идеи, но сами языки будут более требовательны к качеству кода. С Python вы можете быстро собрать решение из готовых блоков, но попытка отойти от них при достаточно больших объёмах данных принесёт много боли.

Ну и, конечно, удачи всем участникам SNA Hackathon 2019!

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть