newsmode
search
Меню
arrow_back Назад

My Notes From Spark+AI Summit 2020 (Application-Specific Talks)

auto_awesomeКраткое саммари

Статья представляет заметки Eugene Yan с конференции Spark+AI Summit 2020, посвящённые прикладным докладам. Рассматриваются фреймворк Zipline от Airbnb для декларативного извлечения point-in-time признаков и Sputnik — фреймворк дата-инженерии, устраняющий шаблонный код Spark-задач. Описывается Feast от Gojek — хранилище признаков, модуляризирующее ML-пайплайн от обучения до продакшена. Netflix делится подходом к качеству данных через статистический тест Колмогорова–Смирнова и «дорожки» (swim lanes) для ETL-пайплайнов, что привело к 80% проактивному обнаружению ошибок и 15% экономии на хранении. LinkedIn применяет методы обучения без учителя — изолирующие леса и кластеризацию графов — для борьбы со злоупотреблениями, а Zynga использует обучение с подкреплением для персонализации в мобильных играх.

Мои заметки с Spark+AI Summit 2020 (прикладные доклады)

[ machinelearning deeplearning production survey ] · 15 мин. чтения

В продолжение предыдущего обзора докладов общего характера — вот мои заметки по некоторым прикладным сессиям.

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

Содержание

Zipline: декларативная инженерия признаков (24 июня)

Nikhil Simha, старший инженер ML-инфраструктуры Airbnb, рассказал о Zipline (аналогичный доклад на Strata 2018) и о том, как Airbnb использует его для решения проблемы сбора point-in-time (PIT) признаков.

Что такое PIT-признаки? В момент Point 1 (P1) последние PIT-признаки — F1=7, F2=3, F3=8. Однако в момент P2 последние PIT-признаки для F1 и F2 изменились на 4 и 2 соответственно. Вычисление этих PIT-признаков (по историческим данным) — очень сложная задача — обычно она включает агрегацию по last и временные джойны. (Эта тема также затрагивается в докладе Gojek о Feast ниже.)

Получить последние значения непросто, особенно если данные имеют детализацию до секунды/минуты

Собирать PIT-признаки можно двумя способами:

Логирование и ожидание: написать код для сбора PIT-признаков через логирование и ждать 3–6 месяцев для накопления достаточного объёма данных. Ручное обратное заполнение: воспроизвести логику инженерии признаков на исторических данных и выполнить обратное заполнение (backfill). Это создаёт проблемы консистентности и может занять много времени.

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

Коммутативность: a + b = b + a Ассоциативность: (a + b) + c = a + (b + c) Обратимость: (a + b) - a = b

Благодаря коммутативности и ассоциативности мы можем параллелизировать вычисления через парадигму map-reduce. Благодаря обратимости нам не нужно пересчитывать всё окно при каждом обновлении: достаточно вычесть устаревшие данные и добавить новые (например, скользящее среднее).

Однако второй класс агрегаций — необратимые. Это такие операции, как минимум, максимум, количество уникальных и т.д. В случае с максимумом мы не можем легко обновлять окна — всё, что у нас хранится, это значение максимума. Тем не менее это можно обойти с помощью бинарного дерева.

С помощью бинарного дерева можно быстро выполнять необратимые агрегации.

В примере выше мы выполняем операцию max на каждых двух периодах для получения узлов первого уровня и повторяем рекурсивно. Это сокращает пространство задачи с O(N) до O(LogN), а время вычислений — с O(N^2) до O(NLogN). Мы жертвуем дополнительным хранилищем (2x) ради более быстрых вычислений (Log(365) = 8.5).

Дополнительное чтение:

Sputnik: фреймворк дата-инженерии (25 июня)

Egor Pakhomov, старший инженер-разработчик в Airbnb Infra, рассказывает о том, как Sputnik встраивает лучшие практики Spark и инженерии, улучшая опыт разработки.

В Spark-задачах (и коде) есть два типа логики:

Логика задачи: бизнес-логика, указание входных и выходных таблиц, партиционирование данных, способ валидации результата и т.д. Логика запуска: парсинг аргументов, создание SparkSession, планирование, создание таблиц, ввод-вывод, запуск в dev и т.д. (в основном шаблонный код).

Большая часть кода в Spark-задаче — шаблонный код; лишь малая часть — собственно преобразование данных.

Sputnik реализует логику запуска, чтобы дата-инженеры могли сосредоточиться на логике задачи. Задачи в Sputnik просты: вход → преобразование → выход; никакого шаблонного кода.

Sputnik также встраивает лучшие практики. Возьмём, к примеру, HiveTableWriter. Он выполняет следующее с минимальными усилиями со стороны дата-инженеров:

Создаёт таблицу, если она не существует; обновляет метаданные Перепартиционирует данные для уменьшения количества файлов на диске Выполняет проверки данных перед записью (например, проверка на нулевое количество) Обновляет имена выходных таблиц (для dev, staging, prod) Нормализует схему DataFrame в соответствии с выходной схемой

Последняя возможность особенно интересна. По умолчанию HiveWriter в Spark сопоставляет столбцы по позиции — а не по имени — и приводит данные к схеме Hive. Из-за этого некорректные значения записываются в столбцы без ошибок. (SPARK-14543).

Sputnik также делает обратное заполнение более эффективным. Обычно backfill задачи включает её запуск для каждой сессии (например, дня) в историческом периоде. Это снижает эффект масштаба (например, создание нового SparkSession каждый раз, батчинг по дням вместо месяцев). Sputnik также группирует исторические задачи по всему периоду или по нескольким периодам за один запуск, чтобы уложиться в ограничения ресурсов.

Sputnik делает обратное заполнение простым и эффективным.

Sputnik также имеет утилиты для тестирования на синглтон-экземпляре SparkSession, с возможностью сравнения DataFrame, загрузки данных из csv/json и очистки хранилища Hive между запусками. Он также проверяет данные на выходе (например, проверка на нулевое количество). А если мы перезапускаем задачу (например, из-за ошибочного исходного вывода), он также инициирует перезапуск нижестоящих задач.

Дополнительное чтение:

Feast: масштабирование сквозного машинного обучения (25 июня)

Willem Pienaar, руководитель платформы Data Science в Gojek, рассказывает о том, как они разработали Feast (Feature Store) для модуляризации сквозного машинного обучения.

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

Исходный монолит делал итерации медленными и хрупкими.

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

С Feast сквозной пайплайн машинного обучения становится модульным.

В части data pipeline различные источники данных (потоковые, SQL, озеро данных) проходят через Apache Beam в качестве слоя приёма данных — таким образом, они используют модель Dataflow от Google.

В большинстве задач extract-transform-load (ETL) данные рассматриваются как ограниченный батч (например, ежедневные батчи). Модель Dataflow предлагает рассматривать их как неограниченный поток (например, сессия). Это обеспечивает гибкость: потоки легко агрегировать в батчи, тогда как переход от батчей к потокам крайне сложен.

Вот аннотация из статьи (выделение моё):

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

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

В этой статье мы представляем один такой подход — модель Dataflow — вместе с детальным разбором обеспечиваемой ею семантики, обзором ключевых принципов, определивших её проектирование, и валидацией самой модели через реальный опыт, который привёл к её разработке.

Полный текст статьи — здесь.

Для хранения Gojek использует историческое хранилище признаков (предположительно на базе Hive или BigQuery) и онлайн-хранилище признаков (Redis, Cassandra). MLflow используется для логирования параметров и метрик обучения моделей, а также для отслеживания моделей при обслуживании. TensorFlow Extended и TensorFlow Data Validation используются для статистической валидации данных с визуализацией через Facets.

Дополнительное чтение:

Качество данных в Netflix для персонализации (24 июня)

Preetam Joshi и Vivek Kaushal, старшие инженеры-разработчики Netflix, представляют два подхода к борьбе с низким качеством данных — на источнике и на этапе ETL.

Существует три формы «запахов ETL»:

Флуктуации: мы ожидаем 1–2 миллиона строк данных ежечасно, но вдруг происходит скачок до 0–5 миллионов, что указывает на возможные узкие места ETL. Резкие падения: мы ожидаем 5 миллионов строк данных ежедневно, но вдруг объём падает до 1,5 миллиона. Недоиспользование: мы собираем 5 миллионов строк данных ежедневно, но в последнее время используется только 1 миллион, что указывает на расточительство и потенциальную экономию.

Отслеживание последнего пункта привело к экономии 15% затрат на хранение.

Некачественные данные появляются двумя основными путями: на источнике и через ETL.

Для обнаружения ошибок на источнике мы сравниваем распределение значений между предыдущим и текущим периодом. Однако в любой день могут быть сотни расхождений в распределениях — для их отсеивания можно применить статистический тест Колмогорова–Смирнова.

Если кратко, тест КС вычисляет максимальное расхождение между двумя кумулятивными распределениями (вертикальная красная линия ниже), значение лежит в диапазоне от 0 до 1. Большие значения указывают на большее расхождение.

Тест Колмогорова–Смирнова позволяет проверить расхождения между двумя непрерывными распределениями.

Вопрос: Тест КС работает на непрерывных значениях — а как быть с дискретными или категориальными?

Ответ: Для дискретных значений мы выполняем простые проверки (вероятно, сравнивая пропорции ключевых категорий).

Для обнаружения ошибок в ETL-пайплайнах используется подход «swim lanes» (дорожки). Допустим, мы хотим добавить или обновить атрибут (т.е. столбец) в существующем пайплайне. Код разрабатывается и коммитится в ветку dev. Затем обе ветки — dev и master — запускаются в отдельных дорожках на идентичных выборках данных. Выходные данные сравниваются, чтобы убедиться, что остальные столбцы не изменились.

Внедрение этих процессов контроля качества данных привело к:

80% проактивного обнаружения проблем 15% экономии затрат благодаря лучшему выявлению неиспользуемых данных 99% валидации при критических миграциях данных с помощью swim lanes Повышению продуктивности разработчиков

Дополнительное чтение:

SuperConductive также представила отличный доклад о качестве данных (Автоматизированное тестирование для защиты data-пайплайнов от недокументированных предположений, 26 июня).

Они рассказали о Great Expectations (проект с открытым исходным кодом), который позволяет просто декларировать ожидания к данным (т.е. тесты). Он упрощает развёртывание и запуск тестов, а также хранение и предоставление результатов.

Борьба со злоупотреблениями с помощью обучения без учителя (24 июня)

James Verbus и Grace Tang, инженеры машинного обучения в LinkedIn, рассказывают о трудностях выявления злоупотреблений и мошенничества и о том, как они применяют обучение без учителя для решения этих задач.

Обнаружение злоупотреблений и мошенничества (и аномалий в целом) имеет уникальные сложности:

Мало размеченных данных для обучения и оценки моделей Ограниченный сигнал от отдельных злоумышленных аккаунтов Состязательный характер — злоумышленники быстро адаптируются

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

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

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

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

Обычные пользователи, использующие инструменты автоматизации, имеют высокие оценки аномальности.

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

Атака отчётливо видна, несмотря на разброс действий пользователей для маскировки.

Кластеризация графов применяется для выявления сетей похожих аккаунтов на основе сигналов (например, лайки одного и того же контента). Наивный подход — вычислить сходство между всеми парами пользователей. Однако это стоит O(N^2). Поэтому можно применить следующие оптимизации:

Исключить клиентов с низкой активностью (так как они низкорисковые) Исключить вирусный контент (слишком много шума и мало сигнала) Исключить пары без пересечения во взаимодействии с контентом

Для поиска сетей можно вычислить коэффициент Жаккара между двумя аккаунтами. Точнее, LinkedIn использует взвешенный коэффициент Жаккара (он же сходство Ружички), поскольку связи пользователь-контент представлены значениями от 0 до 1. Затем применяется кластеризация Джарвиса–Патрика для повышения однородности кластеров.

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

Сети злоумышленников, взаимодействующих с одним и тем же контентом, отчётливо видны, даже когда они добавляют шум для маскировки.

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

Тем не менее реальные пользователи и сообщества тоже попадают в выборку.

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

Дополнительное чтение:

Продакшен-обучение с подкреплением в Zynga (25 июня)

Patrick Halina (руководитель ML-инженерии) и Curren Pangler (ведущий инженер-разработчик) рассказывают о пути Zynga к обучению с подкреплением для персонализации.

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

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

В настоящее время они используют обучение с подкреплением, которое может персонализировать действия для каждого пользователя и непрерывно исследовать и улучшаться со временем. Время отправки ежедневного сообщения в Words With Friends определяется агентом обучения с подкреплением. Это привело к значительному росту CTR по сравнению с вручную настроенной системой.

Технический стек Zynga использует TF-Agents в качестве ядра; он включает множество RL-моделей — от базовых (DQN, DDQN) до передовых (PPO, SAC). Вокруг него создана обёртка (RL-Bakery). RL-Bakery помогает создавать буферы воспроизведения опыта, оркестрировать пайплайны обучения и разворачивать модели.

Zynga также поделилась выводами из многолетнего опыта проектирования RL-приложений:

Выбирайте правильную задачу: можно ли задачу смоделировать как последовательность (действий)? Является ли награда обучаемой (т.е. не разреженной)? Если нет — вероятно, не стоит использовать RL. Выбирайте правильные состояния: RL-агенты чувствительны к слишком большому числу входов; начинайте с простого пространства состояний. Выбирайте правильные действия: начинайте с небольшого набора дискретных действий и базовой модели (например, DDQN). Непрерывные пространства действий требуют методов Policy Gradient. Предварительно обучайте на офлайн-данных: «прогревайте» RL-агентов, чтобы они имитировали существующее поведение на основе исторических данных или вручную созданных сценариев. Тогда при запуске у них уже будет это (хорошее) поведение, и они будут улучшаться, обучаясь на реальных данных.

Они также рассказали о том, как автоматизировали подбор гиперпараметров с помощью MLflow.

Вот мой предыдущий обзор и сопутствующий GitHub о быстром проведении экспериментов с использованием Jupyter, Papermill и MLflow.

Дополнительное чтение:

Добавляю всё это в GitHub-репозиторий по прикладному машинному обучению

Нравится такой прикладной контент о машинном обучении?

Мне тоже. Настолько, что я создал для этого GitHub-репозиторий (applied-ml). Примеры из этого обзора можно найти там. Я также добавил другие материалы, которые встречал.

Если вам нравится такой контент и этот репозиторий, я буду очень признателен, если вы поставите звезду и расскажете о нём. Ещё лучше — если вы внесёте контент через pull request. Спасибо!

Ознакомьтесь с репозиторием applied-ml здесь 🌟.

P.S. Хотите поделиться кратким содержанием этой статьи? Ретвитните тред ниже!

Мои заметки по прикладным докладам на @SparkAISummit 2020👇Sputnik от Airbnb: фреймворк дата-инженерии• Убирает шаблонную логику запуска, чтобы разработчики фокусировались на логике задачи• Встраивает лучшие практики• Например, уменьшение числа файлов через repartition• Простая пакетная обработка задач backfill— Eugene Yan (@eugeneyan) 7 июля 2020

Если вы нашли это полезным, пожалуйста, цитируйте этот обзор как:

Yan, Ziyou. (Jul 2020). My Notes From Spark+AI Summit 2020 (Application-Specific Talks). eugeneyan.com. https://eugeneyan.com/writing/notes-from-sparkai-summit-application-specific/.

или

@article{yan2020spark2, title = {My Notes From Spark+AI Summit 2020 (Application-Specific Talks)}, author = {Yan, Ziyou}, journal = {eugeneyan.com}, year = {2020}, month = {Jul}, url = {https://eugeneyan.com/writing/notes-from-sparkai-summit-application-specific/} }



Присоединяйтесь к 11 800+ читателям, получающим обновления о машинном обучении, рекомендательных системах, LLM и инженерии.