09.02.2019       Выпуск 268 (04.02.2019 - 10.02.2019)       Статьи

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

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

Читать>>




Экспериментальная функция:

Ниже вы видите текст статьи по ссылке. По нему можно быстро понять ссылка достойна прочтения или нет

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

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

SNA Hackathon 2019

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

Установка

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

обучающее видео

и

отдельное соревнование

), но сегодня это хозяйство уже морально устарело и нуждалось в обновлении.

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

себя самих

и прячут от остальных, а остальные крутятся, как могут.

Что с этим в питоне? Проекта как такового нет, но есть «окружение», и в рамках каждого окружения можно сформировать независимую экосистему из пакетов определённых версий. При этом есть и

инструменты для ленивых

, с помощью которых локальным питоновским окружением управлять не сложнее, чем распределённым гетерогенным кластером Клаудеры или Хортона. Но взаимные конфликты версий пакетов никуда не денутся.Я сразу же столкнулся с тем, что релиз

Pandas 0.24

перевёл приватный метод

_maybe_box_datetimelike

в публичный API, и неожиданно оказалось, что много кто его в прежнем виде юзал и теперь отвалился :) (и да, в мире Явы все

то же самое

). Но в итоге удалось всё починить, не считая страшных варнингов о новых деприкейшинах, заработало.

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

image

Задачи на

SNA Hackathon 2019

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

логрег

, профит!

Но план зафэйлился на первом же этапе, на чтении данных. В теории, есть замечательный пакет

Apache Arrow

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

«паркетные» файлы

из питона без спарка. На практике же оказалось. что даже с чтением простых вложенных структур у него

проблемы

, и наша красивая иерархия превратилась в плоское убожество :(.

Но были и положительные стороны.

Jupyter

, в целом, порадовал, он почти такой же удобный, хоть и не такой няшный, как

Zeppelin

. Даже

скала-ядро

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

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

apply

или

map

, то скорость падает на порядки. В итоге, 80 % времени baselineа занимает не чтение данных, джоины, обучение модели и сортировка, а банальное составление списка.

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

Но, в итоге, все препятствия преодолены и для score 0.65 хватило

девяти параграфов

!

Текстовый baseline

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

Lucene

. Поэтому можно сразу брать список токенов и не париться токенизацией/лематизацией/стемингом.

Некоторое время я сомневался, что же взять: отечественный

BigARTM

или импортный

Gensim

. В итоге остановился на втором и скопипастил их

doc2vec туториал

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

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

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

Логрег поверх этого работает так же быстро, и в итоге получаем

14 параграфов

и score 0.54 :)

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

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

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

YOLOv3 на MXNet

:). Лаконичность их демки пленила с первого взгляда, но потом, как обычно, начались проблемы.

С чего обычно начинается работа с большими данными? С оценки производительности и необходимого машинного времени! Хотелось сделать baseline максимально автономным, поэтому научили его работать напрямую с

tar-файлом

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

После пары часов танцев с бубнами приходит понимание, что

NDArray

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

Дальше применяем уже известную машинерию и за

10 параграфов

получаем score 0.504 :).

Выводы

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

Ну и, конечно, удачи всем участникам

SNA Hackathon 2019

!



Лучшая Python рассылка




Разместим вашу рекламу

Пиши: mail@pythondigest.ru

Нашли опечатку?

Выделите фрагмент и отправьте нажатием Ctrl+Enter.

Система Orphus